学以致用,CSS页面布局基本原理

149 阅读10分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第1天,点击查看活动详情

继CSS基本原理之后,本文将整理CSS中最重要的三种改变文档流的方式:浮动、Flexbox 和网格布局所涉及的核心概念

浮动

浮动特性

  • margin: 0 auto对设置浮动的元素无效
  • 浮动不区分块级/行内/行内块元素,无论是谁都可以水平排版,无论是谁都可以设置宽高,很像行内块元素
  • 浮动的特性
    • 脱标:浮动元素是一种“半脱离文档流”的排版方式,浮动元素浮动之后的位置由其之前在标准流中的位置来确定
    • 贴靠:与包含浮动元素的容器宽度相关
    • 字围:浮动的设计初衷,标准流中的文字不会被浮动的盒子遮挡住
    • 收缩:浮动元素若没设置宽度,便会收缩为内容的宽度

清除浮动

  • 容器折叠与清除浮动
    • 容器折叠

      • 浮动是为了实现文字围绕浮动元素排列的效果而设计的,因此浮动元素的高度不会加到父元素上
    • 清除浮动的本质

      • 清除浮动元素由于容器折叠对后面元素造成的影响
      • 如果浮动元素的容器有高度,那么浮动元素就不会影响后面的元素,正是因为容器的高度不方便给,所以需要清除浮动
      • 清除浮动之后,容器的高度会被内容撑开,浮动元素被关在容器里,不会影响后面的元素
    • 清除浮动的方法

      • 在HTML中解决

        <div style="clear:both"></div>
        
      • 在CSS中解决

        .clearfix元素是包含浮动元素的容器,不是浮动元素本身;clear属性只对块级元素生效

        .clearfix::after {
          display: block;
          content: " ";
          clear: both;
        }
        

      ⭐考虑防止外边距折叠的方案

        ```css
        .clearfix::after,.clearfix::before {
          display: table;
          content: " ";
        }
        
        .clearfix::after {
          clear: both;
        }
        ```
        
      
💡 页面布局的思路:从上到下,从左到右;垂直方向用标准流排版,水平方向用浮动流排版

Flexbox

重要概念

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/fd1d7575b874401ea51663e10583000c~tplv-k3u1fbpfcp-zoom-1.image

  • 弹性容器:像块元素一样填满100%可用宽度,高度则由弹性子元素决定;能够控制弹性子元素的布局
  • 弹性子元素:默认在同一行按照从左到右的顺序并排排列,不一定填满其弹性容器的宽度;高度相等,由它们的内容决定
  • 弹性子元素的间距
    • 不等间距:外边距
    • 等间距:justify-content 属性
  • 弹性子元素的大小
    • 在主轴方向上的大小(宽度):弹性子元素的flex: flex-grow flex-shrink flex-basis属性
      • flex-basis :元素大小的基准值。元素若设置了width,初始值为width;若没设置width,初始值为自身内容大小
      • flex-grow :增长因子,代表它是否应该增长到填满容器flex-grow 值为 0,则不会增长;flex-grow 值大于0,它的宽度会增长到分配完剩余空间
      • flex-shrink :收缩因子,代表它是否应该收缩来防止溢出flex-shrink 值为 0,则不会增长;flex-shrink 值大于0,则会收缩到不再溢出

属性值

  • 弹性容器的属性

    • flex-direction :切换主副轴方向
    • justify-content :控制弹性子元素在主轴上的位置(均匀分布)
      • 如果任意子元素的 flex-grow 的值不为 0,或者任意子元素在主轴方向的margin为 auto,justify-content 就失效了
    • align-items:控制弹性子元素在副轴上的位置(对齐,像vertical-align
  • 弹性子元素的属性

    • flex: flex-grow flex-shrink flex-basis:控制自身在主轴方向上的大小
    • align-self:控制自身在副轴上的对齐方式
    • order:将自身从兄弟节点中移到指定位置,覆盖源码顺序

  • 浏览器前缀:如果在旧版浏览器中使用 Flexbox,需要加上-webkit的前缀

网格布局

学习网站:Grid by Example

重要概念

  • display: grid 的网格容器表现得像块元素一样填充100%可用宽度;display: inline-grid 的网格容器会在行内流动,且宽度只能够包含子元素

  • 网格容器和网格元素:网格线、网格轨道、网格单元和网格区域

    https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/03037f82a6d446838bc75e7c2493d952~tplv-k3u1fbpfcp-zoom-1.image

属性值

  • 网格容器的属性

    • grid-template-columnsgrid-template-rows:定义显式网格行列,即网格轨道的大小
      • 常用语法:repeat()/minmax()函数,auto/auto-fill/auto-fit关键字
    • grid-auto-columnsgrid-auto-rows:定义隐式网格
    • grid-gap:定义网格单元之间的间距
    • grid-template-area :为网格区域命名。每个引号内的字符串代表网格的行,字符串内用空格区分网格的列
    • grid-auto-flow:控制布局算法的行为。dense的布局方式会导致元素出现的顺序跟 HTML 里不一致
    • justify-itemsalign-items:控制网格元素的水平和垂直对齐
    • justify-contentalign-content:控制网格轨道在水平和垂直方向上的位置
  • 网格元素的属性

    • grid-columngrid-row:用网格线编号声明网格元素位置
      • grid-columngrid-column-startgrid-column-end 的简写
      • span关键字表示占据整个网格轨道
    • grid-area:用网格区域的名称声明网格元素的位置
    • justify-self:网格元素在水平方向上的对齐
    • align-self:网格元素在垂直方向上的对齐

语法

  • 网格布局的三种语法:编号的网格线、命名的网格线和命名的网格区域

    • 编号的网格线:网格容器的 grid-template-columnsgrid-template-rows属性;网格元素的grid-columngrid-row属性

      grid-template-columns: 2fr 1fr;    
      grid-template-rows: repeat(4, auto);
      
      grid-column: 1 / 3;    
      grid-row: span 1;
      
    • 命名的网格线:网格容器的 grid-template-columnsgrid-template-rows属性;网格元素的grid-columngrid-row属性

      • 声明网格轨道时,在中括号内写上网格线的名称,之后用名称来声明网格元素

        grid-template-columns: [start] 2fr 
        	 [center] 1fr 
        	 [end];
        grid-template-rows: repeat(4, [row] auto);
        grid-column: start / center
        
      • 也可以给一条网格线提供多个名称,-start-end 后缀作为关键字,定义了两者之间的区域

        grid-template-columns: [left-start] 2fr 
                               [left-end right-start] 1fr 
                               [right-end];
        grid-template-rows: repeat(4, [row] auto);
        grid-column: left;
        

    ⭐命名网格区域:网格容器的 grid-template-columnsgrid-template-rows属性和 grid-template-area 属性;网格元素的 grid-area 属性

      ```css
      grid-template-areas: "title title"    
                           "nav   nav" 
                           "main  aside1" 
                           "main  aside2";
      grid-template-columns: 2fr 1fr;    
      grid-template-rows: repeat(4, auto);
      grid-area: title;    
      ```
    

⭐Flexbox 和 Grid 的区别

  1. Flexbox 本质上是一维的,而Grid是二维的
  2. Flexbox 是以内容为切入点由内向外工作的,而Grid是以布局为切入点从外向内工作的
    • Flexbox 可以在一行或一列中安排一系列元素,允许内容对布局有更大的影响,元素的大小不需要明确指定,根据其自身的内容决定
    • Grid 旨在解决一个轨道的元素跟另一个轨道的元素对齐的问题,可以将内容限制在它所在的网格内

💡在实际使用中,网格更适合用于整体的网页布局,而 Flexbox 更适合对网格区域内的特定元素布局

定位与层叠上下文

定位

👉将元素放在屏幕的任意位置。还可以将一个元素放在另一个元素的前面或后面,彼此重叠

  • 固定定位position: fixed
    • 将元素放在浏览器视口的任意位置,元素的包含块是视口
    • 搭配toprightbottomleft使用,决定了元素的边缘在包含块里的位置,也隐式定义了元素的宽高
    • 💡常用于模态框、导航栏
  • 绝对定位position: absolute
    • 元素的包含块是最近的祖先定位元素
    • 也可以使用toprightbottomleft 改变绝对定位元素的大小
    • 💡常用于弹出菜单、工具提示以及消息盒子
  • 相对定位position: relative
    • 元素会从原来的位置移走,但是不会改变它周围任何元素的位置;依赖于文档流
    • 不可以使用toprightbottomleft 改变相对定位元素的大小;topbottom一起用会忽略bottomleftright一起用会忽略right
    • 💡常用于创建绝对定位元素的包含块

💡 关于定位的使用

  • 如果发现 z-index 没有按照预期表现,就在DOM树中找到层叠上下文的根,给它设置z-index将整个层叠上下文向前或向后放
  • 尽可能将独立的定位元素(比如模态框)放到 DOM 的顶层,结束标签之前,这样就没有外部的层叠上下文能束缚它们了
  • 定位用得越多,网页就越复杂,也就越难调试。只有在需要将元素叠放到别的元素之前时,才应该用定位
  • 粘性定位position: sticky
    • 粘性定位是相对定位和固定定位的结合体,常用于下述情况:元素会随着页面滚动,当到达屏幕的特定位置时,如果用户继续滚动,它就会“锁定”在这个位置。如侧边导航栏
    • 粘性定位元素的toprightbottomleft 表示的是“锁定”的位置与视口之间的距离
      • 粘性元素永远不会超出父元素的范围,所以父元素的高度大于粘性元素才会让粘性元素固定,父元素的底边到达粘性元素的底边时粘性元素还会恢复滚动

层叠上下文

  • 默认情况下,浏览器会先绘制所有非定位(静态)的元素,然后绘制定位元素,所以所有的定位元素都会出现在非定位元素前面

👉层叠上下文属于定位的一个隐藏的副作用,它负责决定哪些元素出现在另一些元素前面,一个层叠上下文包含一个元素或者由浏览器一起绘制的一组元素,因此层叠上下文之外的元素无法叠放在层叠上下文内的两个元素之间

💡控制定位元素层叠行为的方法

  • 固定定位的元素:调整HTML中元素的标记位置

  • 绝对定位和相对定位的元素:调整z-index属性

    • z-index 只在定位元素上生效,不能用于控制静态元素
    • 给一个定位元素加上 z-index 可以创建层叠上下文,它就成了一个新的层叠上下文的根,所有后代元素就是这个层叠上下文的一部分
    • **z-index只控制元素所处层叠上下文内的层叠顺序**:层叠上下文的根→→z-index为负数的元素及其子元素→→非定位元素及其子元素→→z-index为auto的元素及其子元素→→z-index为正数的元素及其子元素
    • 小于 1 的 opacity 属性、transformfilter 属性,包括<html>也能创建层叠上下文,根节点给页面创建的是顶级的层叠上下文