第七天到第八天,学习布局

第七天到第八天,学习布局

课程目标

学习布局的各种方式

阅读

  • MDN 定位
  • MDN 定位实战
  • MDN Flexbox
  • 学习CSS布局
  • CSS布局(三) 布局模型
  • CSS布局(四) Float
  • CSS布局(五) 网页布局方式
  • CSS布局(六) 对齐方式
  • 七种实现左侧固定,右侧自适应两栏布局的方法
  • 圣杯布局
  • 双飞翼布局
  • 圣杯布局和双飞翼布局
  • CSS深入理解流体特性和BFC特性下多栏自适应布局

阅读笔记

外边距折叠:块级元素的上外边距和下外边距有时会合并(或折叠)为一个外边距,其大小取其中的最大者。注意浮动元素和绝对定位元素的外边距不会折叠。会发生外边距折叠的三种情况:

  • 相邻元素之间:毗邻的两个元素之间的外边距会折叠(除非后一个元素需要清除之前的浮动)
  • 父元素与其第一个或最后一个子元素之间:如果在父元素与其第一个子元素之间不存在边框、内边距、行内内容,也没有创建块格式化上下文、或者清除浮动将两者的margin-top分开;或者在父元素与其最后一个子元素之间不存在边框、内边距、行内内容、height、min-height、max-height将两者的marin-bottom分开,那么这两对外边距之间会产生折叠。此时子元素的外边距会“溢出”到父元素的外面。
  • 空的块级元素

box-sizing:当你设置一个元素为box-sizing: border-box;时,此元素的内边距和边框不再会增加它的宽度。这个属性支持IE8+

Position

  1. 静态定位:每个元素获取的默认值——将元素放入它在文档布局流中的正常位置position:static;
  2. 相对定位position: relative;:与静态定位相似,占据在正常的文档流中,可以修改它的最终位置,让它与页面上的其他元素重叠。修改元素的位置:使用top,bottom,left,right。在使用相对定位时,就算元素被偏移了,但是他仍然占据着它没偏移前的空间。
  3. 绝对定位position: absolute;:绝对定位的元素不再存在于正常文档布局流中。
  4. z-index:网页上有一个Z轴——一条从屏幕表面到你的脸的虚线。z-index值影响定位元素位于该轴上的位置——正值将它们移动到堆栈上方,负值将它们向下移动到堆栈中。z-index只接受无单位索引值。
  5. 固定定位:fixed,不会保留它原本页面应有的空隙(脱离文档流)。与绝对定位的工作方式完全相同,只有一个区别——绝对定位固定元素是相对于元素或其最近的定位祖先,而固定定位固定元素则是相对于浏览器视口本身。
  6. position: sticky;相对位置和固定位置之间的混合,其允许定位的元件像它被相对定位一样动作,直到其滚动到某一阀值点,之后它变得固定。
  7. 所谓的“单页应用”正在变得非常流行,尤其是移动网页UI,因为把一切的服务放在一个单独的文件上可以减少HTTP请求的数量来浏览所有内容,从而提高性能。

    checkbox hack技术:可以提供无JS的方法来控制一个元素,通过一个按钮的联系。

    // 核心代码,将表单元素的状态与其他标签绑定在一起
    input[type="checkbox"]:checked + aside {
    
    }
    

弹性盒子display: flex

  1. 弹性盒子能方便且灵活实现的:
    • 在父内容里面垂直居中一个块内容
    • 使容器的所有子项占用等量的可用宽度/高度,而不管有多少宽度/高度可用
    • 使多列布局中的所有列采用相同的高度,即使它们包含的内容量不同
  2. 假如你想设置行内元素为fleible box,也可以设置display属性的值为inline-flex
  3. flex模型

    • 主轴(main axis)是沿着flex元素放置的方向延伸的轴(比如页面上的横向的行、纵向的列)。该轴的开始和结束被称为main startmian end
    • 交叉轴(cross axis)是垂直于flex元素放置方向的轴。该轴的开始和结束被称为cross startcross end
    • 设置了display: flex的父元素被称之为flex容器(flex container)
    • 在flex容器中表现为柔性的盒子的元素被称之为flex项(flex item)
  4. flex-direction:指定主轴的方向(弹性盒子子类放置的地方),默认值是row

    .box {
        flex-direction: row | row-reverse | column | column-reverse;
    }
    
  5. flex-wrap:如果一条轴线排不下,如何换行

    .box {
        flex-wrap: nowrap (默认,不换行) |  wrap (换行,第一行在上方) | wrap-reverse (换行,第一行在下方)
    
  6. flex-flow:是flex-direction属性和flex-wrap属性的简写
  7. flex: 1;:这是一个无单位的比例值,表示每个flex项沿主轴的可用空间大小
  8. flex: 1 200px;表示每个flex项将首先给出200px的可用空间,然后,剩余的可用空间将根据分配的比例共享。
  9. flex:是一个可以指定最多三个不同值的缩写属性:
    • flex-grow:无单位比例,定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大,如果所有的flex-grow属性都为1,则它们将等分剩余空间。如果一个项目的flex-grow属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍。
    • flex-shrink:无单位比例,定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。如果所有项目的flex-shrink属性都为1,当空间不足时,都将等比例缩小。如果一个项目的flex-shrink属性为0,其他项目都为1,则空间不足时,前者不缩小。负值对该属性无效。
    • flex-basis:定义了在分配多余空间之前,项目占据的主轴空间。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小。
  10. align-items:定义项目在交叉轴上如何对齐
    • stretch:默认,是所有flex项沿着交叉轴的方向拉伸以填充父容器。如果父容器在交叉轴方向上没有固定宽度(即高度),则所有flex项将变得与最长的flex项一样长(即高度保持一致)。
    • flex-start:交叉轴的起点对齐
    • flex-end:交叉轴的终点对齐
    • center:交叉轴的中点对齐
    • baseline:项目的第一行文字的基线对齐
  11. align-self:允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。默认值为auto,表示继承align-items属性,如果没有父元素,则等同于stretch
  12. justify-content:定义项目在主轴上的对齐方式
    • flex-start:默认值,左对齐
    • flex-end:右对齐
    • center:居中
    • space-between:两端对齐,项目之间的间隔都相等,不会在两端留空间。
    • space-around:每个项目两侧的间隔相等。会在两端留空间。
  13. order:定义项目的排序顺序,数值越小,排列越靠前,默认为0。相同order值的flex项按源顺序显示。
  14. 兼容性:IE10+

Display

  1. block:块级元素
  2. inline:行内元素
  3. none:一些特殊元素的默认display值是它,例如scriptdisplay: none通常被JS用来在不删除元素的情况下隐藏或显示元素。它和visibility属性不一样。把display设置成none元素不会占据它本来应该显示的空间,但是设置成visibility: hidden还会占据空间
  4. inline-block
    • vertical-align属性会影响到inline-block元素,你可能会把他的值设置为top
    • 你需要设置每一列的宽度
    • 如果HTML源代码中元素之间有空格,那么列与列之间会产生空隙

Float

  1. 清除浮动

    • overflow: auto;想支持IE6,加上zoom: 1;

    • 为父元素添加overflow: hidden;:这样父元素就有高度了,父元素的高度便不会被破坏。
    • clear: both;:通过在所有浮动元素下方添加一个clear: both;的元素,可以消除float的破坏性
    • 浮动父元素
    • clearfix:定义一个.clearfix类,然后对float元素的父元素应用这一样式即可

      .clearfix:after {
          content: '';
          display: block;
          clear: both;
      }
      .clearfix {
          *zoom: 1;
      }
      
  2. float的特性
    • 破坏性:被设置了float的元素会脱离文档流
    • 包裹性:div设置了float之后,其宽度会自动调整为包裹住内容宽度,而不是撑满整个父容器。
    • 清空格:根本原因是由于float会导致节点脱离文档流结构。它都不属于文档流结构了,那么它身边的什么换行、空格就都和它没关系的,它就尽量的往一边去靠拢,能靠多近就靠多近,这就是请空格的本质
  3. 浮动的应用
    • 设置float属性后,元素实际上会inline-block块状化
    • 可以去掉排列间的空格
    • 实现文字的环绕效果

BFC

BFC全称“Block Formatting Context”,中文为“块级格式化上下文”。BFC元素特性表现原则就是,内部子元素再怎么翻江倒海,翻云覆雨都不会影响外部的元素。

什么时候会触发BFC呢?常见的如下:

  • float的值不为none
  • overflow的值为autoscrollhidden
  • display的值为table-celltable-captioninline-block中的任何一个。
  • position的值不为relativestatic

媒体查询

“响应式设计”是一种让网站针对不同的浏览器和设备“呈现”不同显示效果的策略

媒体查询就是做此事所需的最强大的工具。

水平居中

  1. 块级元素

    • 定宽

      margin: 0 auto;
      

      唯一的问题是:当浏览器窗口比元素的宽度还要窄时,浏览器会显示一个水平滚动条来容纳页面

      改进方案:使用max-width替代width可以使浏览器更好地处理小窗口的情况。所有的主流浏览器包括IE7+在内都支持max-width

    • 不定宽
      1. 加入table标签:利用table标签的长度自适应型——即不定义其长度也不默认父元素body的长度(table其长度根据其内文本长度决定),因此可以看做是一个定宽度块元素,然后再利用定宽度块状居中的margin的方法,使其水平居中。
        • 为需要设置的居中元素外面加入一个table标签(包括)。
        • 为这个table设置“左右margin居中”(这个和定宽块状元素的方法一样)。
      2. 设置display:inline:改变块级元素的display为inline类型(设置为行内元素显示),然后使用text-align:center来实现居中效果。
        • 设置position:relativeleft:50%:利用相对定位的方式,将元素向左偏移50%,即达到居中的目的
  2. 行内元素:如果被设置元素为文本、图片等行内元素时,在父元素中设置text-align: center;实现行内元素水平居中

垂直居中设置

  • 父元素高度确定的单行文本

    通过设置父元素的height和line-height高度一致来实现的。(height:该元素的高度,line-height:顾名思义,行高(行间距),指在文本中,行与行之间的基线间的距离)。

    弊端:当文字内容的长度大于块的宽时,就有内容脱离了块。

  • 父元素高度确定的多行文本
    • 方法一:使用插入table(包括tbody、tr、td)标签,同时设置vertical:middle
    • 方法二:在chrome、firefox及IE8以上的浏览器下可以设置块级元素的display为table-cell(设置为表格单元显示),激活vertical-align属性,但注意IE6、7并不支持这个样式,兼容性比较差。
  • 不知道自己高度和父容器高度的情况,利用绝对定位只需要以下三行:

    parentElement {
        position: reletive;
    }
    childElement {
        position: absolute;
        top: 50%;
        transform: translateY(-50%);
    }
    
  • 若父容器下只有一个元素,且父元素设置了高度,则只需要使用相对定位即可

    prentElement {
        height: xxx;
    }
    
    childElement {
        position: reletive;
        top: 50%;
        transform: translateY(-50%);
    }
    
  • 不考虑兼容老式浏览器的话,用Flex布局简单直观一劳永逸:

    parentElement{
        display:flex;/*Flex布局*/
        display: -webkit-flex; /* Safari */
        align-items:center;/*指定垂直居中*/
    }
    

水平垂直居中

  1. 单行文本

    text-align: center;
    line-height: 100px;
    
  2. 子元素是div

    Smile
    // text-align + vertical-align .parent { border: 1px solid black; display: table-cell; text-align: center; vertical-align: middle; height: 100px; width: 200px; } .child { display: inline-block; } // 相对 + 绝对定位 .parent { position: relative; width: 200px; height: 100px; } .child { position: absolute; top: 0; left: 0; right: 0; bottom: 0; height: 50px; width: 80px; margin: auto; }
  3. 子元素是图像:可不是用table-cell,而是其父元素用行高代替高度,且font-size: 0;。子元素本身设置vertical-align: middle;
  4. 如果要居中的元素的宽/高是不变的或者说是确定的,比如width/height=100px,那么设置absolute的top/left=50%,然后margin-left/margin-top=-50px即可
  5. 如果要居中的元素的宽/高是不确定的,这时margin负值就不能使用具体的px了,可以使用百分比。但由于margin的百分比都是相对于包含块的宽度,所以这里限制了只能设置宽高相同的居中元素。包含块的宽度如何获得呢?利用absolute的包裹性,在需要居中的元素外面套一个空的

    元素即可。或者:

    .parent {
        position: relative;
    }
    .child {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
    }
    
  6. 如果可以使用flexbox

    .parent {
        display: flex;
        justify-content: center;
        align-items: center;
    }
    
  7. 如果可以使用grid

    body, html {
        height: 100%;
        display: grid;
    }
    span { /* thing to center */
        margin: auto;
    }
    

布局模型

  1. 流动模型(Flow)默认
  2. 浮动模型(Float)
  3. 层模型(Layer)
    • 相对定位
    • 绝对定位
    • 固定定位

常见的布局

  1. 一列布局:一般都是固定的宽高,设置margin: 0 auto来水平居中,用于界面显著标题的展示等
  2. 两列布局:左侧固定,右侧自适应。常用的宽度自适应的方法通常是利用了block水平的元素宽度能随父容器调节的流动特性。另外一种思路是利用CSS中的calc()方法来动态设定宽度。还有一种思路是,利用CSS中的新型布局flex layoutgrid layout

    基本的HTML布局

    左边固定宽度,高度不固定。高度可能很小,也可能很大。
    这里的内容可能比左侧高,也可能比左侧低。宽度需要自适应

    基本的样式:两个盒子相距20px,左侧盒子宽120px,右侧盒子宽度自适应

    • inline-block方案:通过width: calc(100% - 140px)来动态计算右侧盒子的宽度。需要知道左侧盒子的宽度,两个盒子的距离,还要设置各个元素的box-sizing;需要消除空格字符的影响;需要设置vertical-align: top;满足顶端对齐

      .wrapper-inline-block {
          box-sizing: content-box;
          font-size: 0;    // 消除空格的影响
      }
      
      .wrapper-inline-block .left,
      .wrapper-inline-block .right {
          display: inline-block;
          vertical-align: top;    // 顶端对齐
          font-size: 14px;
          box-sizing: border-box;
      }
      
      .wrapper-inline-block .right {
          width: calc(100% - 140px);
      }
      
    • float方案:浮动的block元素在有空间的情况下会依次紧贴,排列在一行

      .wrapper-double-float {
          overflow: auto;        // 清除浮动
          box-sizing: content-box;
      }
      
      .wrapper-double-float .left,
      .wrapper-double-float .right {
          float: left;
          box-sizing: border-box;
      }
      
      .wrapper-double-float .right {
          width: calc(100% - 140px);
      }
      
    • float + margin-left方案block级别的元素会认为浮动的元素不存在,但是inline级别的元素能识别到浮动的元素。这样,block级别的元素就可以和浮动的元素同处在一行了。

      .wrapper-float {
          overflow: hidden;        // 清除浮动
      }
      
      .wrapper-float .left {
          float: left;
      }
      
      .wrapper-float .right {
          margin-left: 150px;
      }
      
    • 使用absolute + margin-left方法:使用了绝对定位,若是用在某个div中,需要更改父容器的position;没有清除浮动的方法,若左侧盒子高于右侧盒子,就会超出父容器的高度。因此只能通过设置父容器的min-height来放置这种情况

      .wrapper-absolute .left {
          position: absolute;
      }
      
      .wrapper-absolute .right {
          margin-left: 150px;
      }
      
    • 使用float + BFC方法:左侧浮动,右侧盒子通过overflow: auto;形成了BFC,因此右侧盒子不会与浮动的元素重叠,父元素需要清除浮动

      .wrapper-float-bfc {
          overflow: auto;
      }
      
      .wrapper-float-bfc .left {
          float: left;
          margin-right: 20px;
      }
      
      .wrapper-float-bfc .right {
          margin-left: 0;
          overflow: auto;
      }
      
    • flex方案:可以说是最好的方案了,flex容器的一个默认属性值:align-items: stretch;,这个属性导致了列等高的效果,为了让两个盒子高度自动,需要设置align-items: flex-start;

      .wrapper-flex {
          display: flex;
          align-items: flex-start;
      }
      
      .wrapper-flex .left {
          flex: 0 0 auto;
      }
      
      .wrapper-flex .right {
          flex: 1 1 auto;
      }
      
    • grid方案:可以满足需且,但这并不是它发挥用处的真正地方。注意:grid布局也有列等高的默认效果,需要设置align-items: start;

      .wrapper-grid {
          display: grid;
          grid-template-columns: 120px 1fr;
          align-items: start;
      }
      
      .wrapper-grid .left,
      .wrapper-grid .right {
          box-sizing: border-box;
      }
      
      .wrapper-grid .left {
          grid-column: 1;
      }
      
      .wrapper-grid .right {
          grid-column: 2;
      }
      
    • 极限情况:
      • 动态计算宽度的情况:两种方案:双inline-block方案和双float方案。宽度极限小时,右侧的div宽度会非常小,由于遵循流动布局,所以右侧div会移动到下一行
      • 动态计算右侧margin-left的情况:两种方案:float + margin-left方案和absolute + margin-left方案。宽度极限小时,由于右侧的div忽略了文档流中左侧div的存在,所以其依旧会存在于这一行,并被隐藏
      • float + BFC方案的情况下:由于BFC与float的特殊关系,右侧div在宽度减小到最小后,也会掉落到下一行
      • flexgrid情况:默认两种布局方式都不会放下div移动到下一行,不过flex布局可以通过flex-flow: wrap;来设置多余的div移动到下一行。grid布局暂不支持。
  3. 三列布局:两侧定宽中间自适应

    • 首先设置父级元素的宽度,可以左左右设置浮动,然后中间设置margin调整间距,也可以都设置左浮动,设置margin,调整间距。同样注意清除浮动的影响。
    • 绝对定位法:左右两栏采用绝对定位,分别固定于页面的左右两侧,中间的主体栏用左右margin值撑开距离。

      代码:
      
      // HTML
      
          
      // CSS