布局复习笔记

212 阅读22分钟

flex

一般来说 justify表示水平方向的样式设置;

align表示垂直方向的样式设置;

items表示全体元素的样式设置;

content表示整体布局的样式设置;

self表示元素自身的样式设置,其一定是应用在子元素上的。

因此,justify-content属性就表示整体布局的水平对齐设 置,align-items就表示全体元素的垂直对齐样式设置。

flex-shink是设置默认宽度

父容器属性,display:flex是基本,

  • 开启了flex布局的元素叫做flex container

  • flex container里面的直接子元素叫做flex items(也就是开启了flex布局的盒子包裹的第一层子元素)

  • 如果display对应的值是flex的话,那么flex container是以block-level的形式存在的,相当于是一个块级元素

  • 如果display的值设置为inline-flex的话,那么flex container是以inline-level的形式存在的,相当于是一个行内块元素

如果一个元素的父元素开启了flex布局;那么其子元素的display属性对自身的影响将会失效

justify-content

(flex-start;flex-end,center,space-around,space-between)沿着主轴方向排列

特点:

  1. flex items之间的距离相等
  2. flex items与main start、main end之间的距离等于flex items的距离

image.png

  • space-around

特点:

  1. flex items之间的距离相等
  2. flex items与main start、main end之间的距离等于flex items的距离的一半

image.png

  • space-between
  1. 与main start、main end两端对齐
  2. flex items之间的距离相等

image.png

  • space-evenly

除了设置 justify-content:space-between以外,还可以直接操作子项的margin

image.png

max-width属性的优先级大于width属性的优先级,能够使尺寸从固定值变成相对值

失效原因

原因一:子元素设置了 margin:auto,注意:margin-left/right auto 这些是没问题的.

最常见错误

原因二:盒子本身伪类选择器.

以上是网上容易找到的,都没解决我的问题,最后我就把子类元素所有样式全部去掉一个一个实验,最后发现是子类元素设置了 flex:1 导致的.

原因三: 子元素设置单个盒模型占比导致justify-content失效.

flex-direction

(row(),column(垂直排列),row-reverse,column-reverse)决定主轴方向,横着排,还是速着排

  • 注意:flex-direction并不是直接改变flex items的排列顺序,他只是通过改变了主轴方向间接的改变了顺序

如果flex-direction属性的值是column 或是column-reverse,则flex子项的垂直对齐不应使用align-items属性控制,而是应该使用justify-content属性控制。

flex-wrap

(nowrap,wrap,wrap-reverse) 是否换行,flex的换行只有子元素有固定宽度才会换行

flex-flow

是flex-direcrion和flex-wrap的缩写,不分先后 flex-flow: wrap column

align-items

垂直对齐属性(flex-start;flex-end,center,baseline,stretch拉伸),设置子容器如何沿交叉轴排列

align-items决定了单行flex items在cross axis(交叉轴)上的对齐方式

注意:主轴只要是横向的,无论flex-direction设置的是row还是row-reverse,其交叉轴都是从上指向下的;

主轴只要是纵向的,无论flex-direction设置的是column还是column-reverse,其交叉轴都是从左指向右的;

也就是说:主轴可能会有四种,但是交叉轴只有两种

  • stretch(默认值):当flex items在交叉轴方向上的size(指width或者height,由交叉轴方向确定,column时候是width,row的时候是height,注意父元素宽高不能是auto)为auto时,会自动拉伸至填充;但是如果flex items的size并不是auto,那么产生的效果就和设置为flex-start一样

注意:触发条件为:父元素设置align-items的属性值为stretch,而子元素在交叉轴方向上的size设置为auto

  • flex-start:与cross start对齐

  • flex-end:与cross end对齐

  • center:居中对齐

  • baseline:与基准线对齐

至于baseline这个属性值,平时用的并不是很多,基准线可以认为是盒子里面文字的底线,基准线对齐就是让每个盒子文字的底线对齐

注意:align-items的默认值与justify-content的默认值不同,它并不是flex-start,而是stretch

align-self

align-self属性的各个属性值的表现和align-items属性的 各个属性值一样,区别在于align-self属性设置的是具体某个flex 子项的垂直对齐方式

align-content

align-content属性和align-items属性的区别在于align-items属性设置的是每一个flex子项的垂直对齐方式,而align-content属性将所有flex,align-content控制子项的内容大小,而align-items控制在这个大小内的摆放

stretch可以看成弹性布局中align-content属性的默认值,表示每一行flex子项都等比例拉伸。例如,如果共两行flex子 项,则每一行拉伸的高度是50%。

flex-star是逻辑CSS属性值,与文档流方向相关,默认表现为顶部堆砌。

flex-end是逻辑CSS属性值,与文档流方向相关,默认表现为底部堆放。

center表现为整体垂直居中对齐。

space-between表现为上下两行两端对齐,剩下的每一行元素等分剩余空间。

space-around表现为每一行元素上下都享有独立不重叠的空白空间。

space-evenly表现为每一行元素上下的空白空间的大小都是一致的。

子容器属性
  • flex是flex-grow || flex-shrink?|| flex-basis的简写,说明flex属性值可以是一个、两个、或者是三个,剩下的为默认值

  • 默认值为flex: 0 1 auto

  • none: 0 0 auto

  • auto:1 1 auto

(1)如果flex的属性值只有1个值,则具体规则如下。

如果是数值,如flex: 1,则这个1为flex-grow属性的值,此 时flex-shrink属性和flex-basis属性的值分别是1和0%。注 意,这里的flex-basis属性的值是0%,而不是默认值auto。 如果是长度值,如flex:100px,则这个100px显然为flex-basis属性的值,因为3个缩写CSS属性中只有flex-basis的属 性值支持长度值。此时flex-grow属性和flex- shrink属性 的值都是1,注意,这里的flex-grow属性的值是1,而不是默认 值0。

(2)如果flex的属性值有2个值,则第一个值一定是flex-grow属性值(因为表示0个或1个的问号“?”在flex-shrink的后 面),第二个值根据值的类型不同对应不同的CSS属性,具体规则如 下。 如果第二个值是数值,例如flex: 1 2,则这个2是flex-shrink属性的值,此时flex-basis属性计算值是0%,并非默 认值auto。 如果第二个值是长度值,例如flex: 1 100px,则这个100px 为flex-basis属性值。

(3)如果flex的属性值有3个值,则长度值为flex-basis属性 值,其余2个数值分别为flex-grow和flex-shrink的属性值。下面两行CSS语句都是合法的,且含义也是一样的: 下面两行CSS语句含义是一样的 *

flex: 1 2 50%;
flex: 50% 1 2;

flex:100px等同于flex:1 1 100px,即flex-grow使用的 不是默认值0,而是使用的1。按照CSS规范的说法,这样设计的目的是让flex属性的表现更符 合我们日常开发需要的效果。意思就是,当我们使用flex:1的时 候,正常情况下就是要flex-basis为0%,即基础尺寸为0;当我们使用flex:100px的时候,正常情况下就是需要flex-grow为1,也 就是尺寸保持向外的弹性。这样更人性化

故事是这样的,有一个人家生了5个孩子,分别叫作老大、 老二、老三、老四和老五。要是只有一个孩子,那这个孩子就继承 100%的家产,但是现在有5个孩子,家长需要提早定好家产分配规 则。而flex属性的作用就如同制定分配家产的规则。

flex-basis属性用来分配基础数量的家产。

flex-grow属性用来家产仍有富余的时候该如何分配。

flex-shrink属性用来家产不足的时候该如何分配。

flex-grow

弹性延伸比例

  • 可以设置任何非负数字(正整数、正小数、0),默认值为0 所有剩余空间总量是1。

如果只有1个flex子项设置了flex-grow属性值,则有两种分配

情况1

如果flex-grow属性值小于1,则flex子项扩展的空间就是 总剩余空间和这个比例的计算值。有空间剩余

情况2

如果flex-grow属性值大于1,则flex子项独享所有剩余空 间。 如果有多个子项flex设置了flex-grow属性值,则有两种分配

如果有多个子项flex设置了flex-grow属性值,则有两种分配 情况

情况1

如果flex-grow属性值的总和小于1,则每个flex子项扩展 的空间就是总剩余空间和当前flex子项设置的flex-grow 比例的计算值。有空间剩余

情况2

如果flex-grow属性值的总和大于1,则所有剩余空间被利 用,分配比例就是各个flex子项的flex-grow属性值的比 例。例如,所有flex子项都设置flex-grow:1,则表示剩 余空间等分;如果设置的flex-grow比例是1:2:1,则中间 的flex子项占据一半的剩余空间,剩下另外一半的剩余空间 由前后两个flex子项等分。

flex-basis

默认原始尺寸,flex不为0时失效 (会有flex-grow设置为0的情况,比如flex:0 1 100px)

  • flex-basis用来设置flex items主轴方向上的base size,以后flew-growflex-shrink计算时所需要用的base size就是这个
  • auto(默认值)、content:取决于内容本身的size,这两个属性可以认为效果都是一样的,当然也可以设置具体的值和百分数(根据父盒子的比例计算)
  • 决定flex items最终base size因素的优先级为max-width/max-height/min-width/min-height > flex-basis > width/height > 内容本身的size
  • 可以理解为给flex items设置了flex-basis属性且属性值为具体的值或者百分数的话,主轴上对应的size(width/height)就不管用了

最终尺寸计算的优先级是: 最大最小尺寸限制 > 弹性增长或收缩 > 基础尺寸

基础尺寸由flex-basis属性或width属性,以及box-sizing盒模型共同决定; 内容尺寸指最大内容宽度,当没有设置基础尺寸时会顶替基础尺 寸的角色; 弹性增长指的是flex-grow属性,弹性收缩指的是flex-shrink属性; 最大尺寸主要受max-width属性限制;最小尺寸则比较复杂,受 最小内容宽度、width属性和min-width属性共同影响。

如果flex-basis属性和width属性同时设置了具体的数 值,width属性值会被忽略,优先使用flex-basis的属性值作为基础尺寸

如果flex-basis的属性值是初始值auto,则会使用 width属性设置的长度值作为基础尺寸。

如果flex-basis和width的属性值都是auto,则会使用 flex子项的最大内容宽度(文字内容全部一行显 示的宽度)作为基础尺寸,此时称为“内容尺寸”。示 意效果如图6-62所示,最终尺寸大小是由文字内容长度决定的。

image.png

而设置了box-sizing:border-box后

image.png

这是因为flex-basis属性不支持box-sizing属性吗?其实并 不是,设置flex-basis属性的元素的最小尺寸是最小内容宽度(文 字内容在所有换行点换行后的尺寸),

如果flex-shrink属性不为0, 则: 如果min-width属性值不是auto,则元素的最小尺寸就是minwidth的属性值,此时width属性无法影响最小尺寸,哪怕 width的属性值大于min-width的属性值;

比较width属性的计算值和最小内容宽度的大小,较小的值就是 元素的最小尺寸;

如果width的属性值和min-width的属性值均为auto,则元素 的最小尺寸就是最小内容宽度;

如果flex子项设置了overflow:hidden,且最小尺寸是由最小 内容宽度决定的,则最小尺寸无效。

flex-basis属性下的最小尺寸是由内容决定的, 而width属性下的最小尺寸是由width属性的计算值决定的。

flex-shrink

- 当flex items在主轴方向上超过了flex container的size之后,flex-shrink属性才会生效

  • flex-shrink属性指定了容器剩余空间不足时候的分配规 则,默认值是1,表示空间不足要分配,
  • 可以设置任意非负数字(正小数、正整数、0),默认值是1

如果只有1个flex子项设置了flex-shrink属性值,则有两种分配情况。

  • 如果flex-shrink属性值小于1,则收缩不完全,会有一部 分内容溢出flex容器。 如果flex-shrink属性值大于等于1,则收缩完全,元素正 好填满flex容器。

如果多个flex子项设置了flex-shrink属性,则有两种分配情况。

  • 如果flex-shrink属性值的总和小于1,则收缩不完全,

收缩比例 = flex-shrink * flex item的基础尺寸,基础尺寸就是flex item放入flex container之前的size

每个flex item收缩的size为超出的尺寸 / 所有flex items 的收缩比例之和 * 收缩比例 (考虑到了每个item尺寸不一样的情况,所以要除所有收缩比例之和)

  • 如果flex-shrink属性值的总和大于1,则收缩完全,每个元素收缩尺寸的比例和flex-shrink属性值的比例一样。

    总结:当flex items的flex-shrink属性值的总和小于1时,通过其计算收缩size的公式可知,其总共收缩的距离是超出的size * sum,由于sum是小于1的,那么无论如何子盒子都不会完全收缩至超过的距离,也就是说在不换行的情况下子元素一定会有超出

image.png

order 排列顺序,越小越靠前,默认值为0,可以负数

应该在什么时候使用flex:0/1/none/auto

flex:initial的基本表现

flex:initial等同于设置flex: 0 1 auto,可以理解为 flex属性的默认值。其行为表现用文字描述为:应用flex:initial的元素在flex 容器有剩余空间时其尺寸不会增长(flex-grow:0,不会增长把剩余空间占满),在flex容器 尺寸不足时尺寸会收缩变小(flex-shrink:1,如果子项很多,那么尺寸会缩小,比如文字换行),同时当前应用 flex:initial的元素的尺寸自适应于内容(flex-basis:auto)

flex:0和flex:none的区别

flex:0等同于设置flex: 0 1 0%,flex:none等同于设置 flex: 0 0 auto,flex:0不会增大,但是会弹性收缩,flex:none,不增大,不缩小,尺寸由内容决定

flex:1和flex:auto的区别

flex:1等同于设置flex: 1 1 0%,flex:auto等同于设置 flex: 1 1 auto

结合flex属性值的描述,我们可以得出flex:1和flex:auto的 行为表现:元素尺寸可以弹性增大,也可以弹性减小,但是flex:1 在容器尺寸不足时会优先最小化内容尺寸,flex:auto在容器尺寸不足时会优先最大化内容尺寸。

当希望元素充分利用剩余空间,同时不会侵占其他元素应有的宽度的时候,适合使用flex:1

当希望元素充分利用剩余空间,但是元素各自的尺寸又需要按照各自内容进行分配的时候,就适合使用flex:auto。

总结

flex:initial表示默认的弹性布局状态,无须专门设置,适合 小控件元素的分布布局(其中某一个flex子项的内容动态变化也 没有关系)。

flex:0适用场景较少,适合设置在替换元素的父元素上。

flex:none适合设置在内容不能换行显示的小控件元素上,如按钮。

flex:1适合等分布局。

flex:auto适合基于内容动态适配的布局。

flex最后一行排列不均匀

比如上面是4个子项,下面三个子项,排列不均匀,想让下面三个子项靠左对齐

子项宽度固定,比如子项宽度是24%

.list:not(:nth-child(4n)) { margin-right: calc(4% / 3); } 设定非第四个子项的margin

子项宽度不固定

image.png

行数不固定

用空元素占位

grid布局

.wrapper {
  /* 声明一个容器 */
  display: grid;
  /*  声明列的宽度  */ 
 repeat() 函数:可以简化重复的值。该函数接受两个参数,
 第一个参数是重复的次数,第二个参数是所要重复的值
  grid-template-columns: repeat(3, 200px);
  /*  声明行间距和列间距  */
  grid-gap: 20px;
  /*  声明行的高度  */
  grid-template-rows: 100px 200px;
}

display声明,grid块级元素网格布局,inline-grid行内元素,网格布局

网格轨道:grid-template-columns 和 grid-template-rows 属性来定义网格中的行和列。容器内部的水平区域称为行,垂直区域称为列,就是定义一行一列多少个元素

repeat() 函数

auto-fill 关键字:表示自动填充,让一行(或者一列)中尽可能的容纳更多的单元格 grid-template-columns: repeat(auto-fill, 200px) 表示列宽是 200 px,但列的数量是不固定的,只要浏览器能够容纳得下,就可以放置元素,

fr关键字 grid-template-columns: 200px 1fr 2fr 表示第一个列宽设置为 200px,后面剩余的宽度分为两部分,宽度分别为剩余宽度的 1/3 和 2/3

minmax() 函数 minmax() 函数产生一个长度范围,表示长度就在这个范围之中都可以应用到网格项目中。它接受两个参数,分别为最小值和最大值。grid-template-columns: 1fr 1fr minmax(300px, 2fr)

auto 设置auto可以自适应

grid-row-gap 属性、grid-column-gap 属性分别设置行间距和列间距。grid-gap 属性是两者的简写形式。

areas和area配置 image.png

grid-auto-flow

控制自动布局是先行后列,还是先列后行 grid-auto-flow: row; column; 如果加了dense 那就会尽可能填满表格,rou dense;colunmn dense

justify-items 属性设置单元格内容的水平位置(左中右),align-items 属性设置单元格的垂直位置(上中下)

.container {
  justify-items: start | end | center | stretch(拉伸);
  align-items: start | end | center | stretch(拉伸);
}
justify-content 属性、align-content 属性以及 place-content 属性

justify-content 属性是整个内容区域在容器里面的水平位置(左中右),align-content 属性是整个内容区域的垂直位置(上中下)。它们都有如下的属性值。跟flex一样

.container {
  justify-content: start | end | center | stretch | space-around | space-between | space-evenly;
  align-content: start | end | center | stretch | space-around | space-between | space-evenly;  
}

image.png

  • space-around - 每个项目两侧的间隔相等。所以,项目之间的间隔比项目与容器边框的间隔大一倍

  • space-between - 项目与项目的间隔相等,项目与容器边框之间没有间隔

  • space-evenly - 项目与项目的间隔相等,项目与容器边框之间也是同样长度的间隔

  • stretch - 项目大小没有指定时,拉伸占据整个网格容器

grid-column-start 属性、grid-column-end 属性、grid-row-start 属性以及grid-row-end 属性

可以指定网格项目所在的四个边框,分别定位在哪根网格线,从而指定项目的位置

  • grid-column-start 属性:左边框所在的垂直网格线
  • grid-column-end 属性:右边框所在的垂直网格线
  • grid-row-start 属性:上边框所在的水平网格线
  • grid-row-end 属性:下边框所在的水平网格线

image.png

布局

两栏布局的实现

一般两栏布局指的是左边一栏宽度固定,右边一栏宽度自适应,两栏布局的具体实现:

  • 利用浮动,将左边元素宽度设置为200px,并且设置向左浮动。将右边元素的margin-left设置为200px,宽度设置为auto(默认为auto,撑满整个父元素)。
.outer {
  height: 100px;
}
.left {
  float: left;
  width: 200px;
  background: tomato;
}
.right {
  margin-left: 200px;
  width: auto;
  background: gold;
}
  • 利用浮动,左侧元素设置固定大小,并左浮动,右侧元素设置overflow: hidden; 这样右边就触发了BFC,BFC的区域不会与浮动元素发生重叠,所以两侧就不会发生重叠。
.left{
     width: 100px;
     height: 200px;
     background: red;
     float: left;
 }
 .right{
     height: 300px;
     background: blue;
     overflow: hidden;
 }
  • 利用flex布局,将左边元素设置为固定宽度200px,将右边的元素设置为flex:1。
.outer {
  display: flex;
  height: 100px;
}
.left {
  width: 200px;
  background: tomato;
}
.right {
  flex: 1;
  background: gold;
}
  • 利用绝对定位,将父级元素设置为相对定位。左边元素设置为absolute定位,并且宽度设置为200px。将右边元素的margin-left的值设置为200px。
.outer {
  position: relative;
  height: 100px;
}
.left {
  position: absolute;
  width: 200px;
  height: 100px;
  background: tomato;
}
.right {
  margin-left: 200px;
  background: gold;
}
  • 利用绝对定位,将父级元素设置为相对定位。左边元素宽度设置为200px,右边元素设置为绝对定位,左边定位为200px,其余方向定位为0。
.outer {
  position: relative;
  height: 100px;
}
.left {
  width: 200px;
  background: tomato;
}
.right {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 200px;
  background: gold;
}

三栏布局的实现

三栏布局一般指的是页面中一共有三栏,左右两栏宽度固定,中间自适应的布局,三栏布局的具体实现:

  • 利用绝对定位,左右两栏设置为绝对定位,中间设置对应方向大小的margin的值。
.outer {
  position: relative;
  height: 100px;
}

.left {
  position: absolute;
  width: 100px;
  height: 100px;
  background: tomato;
}

.right {
  position: absolute;
  top: 0;
  right: 0;
  width: 200px;
  height: 100px;
  background: gold;
}

.center {
  margin-left: 100px;
  margin-right: 200px;
  height: 100px;
  background: lightgreen;
}
  • 利用flex布局,左右两栏设置固定大小,中间一栏设置为flex:1。
.outer {
  display: flex;
  height: 100px;
}

.left {
  width: 100px;
  background: tomato;
}

.right {
  width: 100px;
  background: gold;
}

.center {
  flex: 1;
  background: lightgreen;
}
  • 利用浮动,左右两栏设置固定大小,并设置对应方向的浮动。中间一栏设置左右两个方向的margin值,注意这种方式**,中间一栏必须放到最后:**
.outer {
  height: 100px;
}

.left {
  float: left;
  width: 100px;
  height: 100px;
  background: tomato;
}

.right {
  float: right;
  width: 200px;
  height: 100px;
  background: gold;
}

.center {
  height: 100px;
  margin-left: 100px;
  margin-right: 200px;
  background: lightgreen;
}

圣杯布局

  • 圣杯布局,利用浮动和负边距来实现。父级元素设置左右的 padding,三列均设置向左浮动,中间一列放在最前面,宽度设置为父级元素的宽度,因此后面两列都被挤到了下一行,通过设置 margin 负值将其移动到上一行,再利用相对定位,定位到两边。
.outer {
  height: 100px;
  padding-left: 100px;
  padding-right: 200px;
}

.left {
  position: relative;
  left: -100px;

  float: left;
  margin-left: -100%;

  width: 100px;
  height: 100px;
  background: tomato;
}

.right {
  position: relative;
  left: 200px;

  float: right;
  margin-left: -200px;

  width: 200px;
  height: 100px;
  background: gold;
}

.center {
  float: left;

  width: 100%;
  height: 100px;
  background: lightgreen;
}

双飞翼布局

  • 双飞翼布局,双飞翼布局相对于圣杯布局来说,左右位置的保留是通过中间列的 margin 值来实现的,而不是通过父元素的 padding 来实现的。本质上来说,也是通过浮动和外边距负值来实现的。
.outer {
  height: 100px;
}

.left {
  float: left;
  margin-left: -100%;

  width: 100px;
  height: 100px;
  background: tomato;
}

.right {
  float: left;
  margin-left: -200px;

  width: 200px;
  height: 100px;
  background: gold;
}

.wrapper {
  float: left;

  width: 100%;
  height: 100px;
  background: lightgreen;
}

.center {
  margin-left: 100px;
  margin-right: 200px;
  height: 100px;
}

分栏布局

用ul 和li布局,用li使用弹性布局或者网格布局的话,项目符号会立刻消失,例如原点或者序号。

columns

columns是columns-width 和 columns-count的缩写,顺序不限制

columns-width

每一栏/列的理想宽度,会与实际宽度有出入,更像一个期望宽度,不支持百分比,浏览器会根据这个期望宽度,来确定ul分成几栏

columns-count

理想分栏数量,最终分栏效果跟columns-width相互制约,看谁优先级高。优先级计算是全部转换成行数,看谁更小,就用谁

columns-gap

支持百分比,columns-gap其实是gap的子属性,在网格布局规范制定之后的一段时间,CSS世界中的行与列之间的 间隙使用了gap属性进行了统一,也就是分栏布局、弹性布局和网格 布局的间隙都全部统一使用gap属性表示,而gap属性实际上是 column-gap属性和row-gap属性的缩写。

columns-rule

column-rule属性和border属性的语法和规则是一模一样的, 只是column-rule是设置各个分栏的分隔线样式,border是设置元 素的边框样式 例如column-rule: dashed deepskyblue;