布局/BFC/居中/table-cell/flex
Published by Shangyu Liu,
有三种布局:正常流、浮动、绝对定位、fixed
浮动、绝对定位(包括fixed)后,我们认为元素都飘了起来,会以最近定位的父元素为参照点(fixed会以浏览器左上角为参照点),但不同之处在于,absolute之间会遮挡(比如left、top设置相同的值),但同样float起来的元素,相互不会重叠
1、float
(1)float元素
float的元素是不能说完全脱离正常文档流的(可以将文档视作两层,float浮动到上一层,其他所有正常流的元素在下一层,浮动起来的元素会互相可见、碰 撞,下一层,即正常文档流中的元素“看不到"浮动、绝对定位元素,但是同属于float的元素相互是可见的,而且文字是可以看到float元素的),因为看不到,所以容纳float的div就会坍缩(本来div是靠它内部对div可见 的元素撑起来的),因此需要清除浮动,参考文献非常清晰详细:ref:http://www.w3school.com.cn/css/css_positioning_floating.asp。
2018-3-27更新:再论float,通过实验可以发现这样的特性,我们首先按照静态布局的行为排布所有的元素,然后再加上float,这样,float所占的原来的位置就空了出来,向着它float的方向流动,但是,它是不能够浮动到他前面的未脱离文档流的元素之上的!而且之前也知道float元素互相是不能重叠的,它之后的元素(比如div)将看不到他,很可能直接钻到它底下去,但是!div里的内容是能够看到它的(这个内容指的是文字,不是div,比如div里嵌套div,里面的div看不到float元素,除非他自己也float了),这就是为什么会产生文字环绕,此时为了避免文字环绕需要将div的margin-left(float:left)设置为浮动元素的宽度。
(2)清除浮动
清除浮动:clear(left/right/both/none),意思是不允许包含clear的css属性的元素的(左/右/两边/none)边上有 浮动元素存在,原理是加margin-top,这样对于父容器坍缩情况,可以在父容器内最后的位置添加一个div,由于此div沉底,让它左右都不许出现 浮动元素,这样父div会被撑开,进一步不要这个div,改成after伪元素,相当于有了一个div但不在html中写进去(破坏html结构),设置 div为block(margin-top对行内元素无效),这样就可以使得父div撑开
2、absolute
最重要的是记得给包裹的父元素设置定位(relative、absolute都行,就是不能是static),因为只有absolute的包含块不能是static的,会继续查找最近的非static定位的元素,这样之后才能有正确的参照系。由于完全脱了了文档流,所以其他元素相对于absolute视而不见(不管其他元素是怎样定位的)。
3、relative
此时定位的四个值是与自己本身所应该在的位置而言的,一旦设定会拥有z-index,会产生遮挡,但不会脱离文档流,原来占据的位置仍然会对其他元素产生影响。
css中百分比定位都是相对谁:(来自知乎)
相对于父元素宽度的:[max/min-]width、left、right、padding、margin 等;
相对于父元素高度的:[max/min-]height、top、bottom 等;
相对于继承字号的:font-size 等;
相对于自身字号的:line-height 等;
相对于自身宽高的:border-radius、background-size、transform: translate()、transform-origin、zoom、clip-path 等;
BFC(块级格式化上下文)
块级格式化上下文是一个区域,这个区域内的所有元素对外不产生任何影响,
使得一个元素变成BFC的条件如下:
1、根元素
2、float属性不为none
3、position为absolute或fixed
4、display为inline-block, table-cell, table-caption, flex, inline-flex
5、overflow不为visible
BFC元素内的布局效果如下:
1、内部的Box会在垂直方向,一个接一个地放置。
2、Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠
3、每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
4、BFC的区域不会与float box重叠。
5、BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
6、计算BFC的高度时,浮动元素也参与计算(这一条使得清除浮动有了新的办法)
table-cell与flex
这两种布局方法个人感觉非常类似,flex是加强版。两者默认都是元素在行内显示,不会换行,填充满整个区域。
flex,父元素设置display:flex,子元素设置flex:weight;table,父元素设置display:table,子元素设置display:table-cell。同样如果设置了宽度的百分比,会按照比例分配(如20%,30%,则比例为2:3)。
都可以用来居中,flex在水平方向布局是justify-content,垂直方向布局是align-items,居中都是center
但是,table布局的居中不是这样的,它的居中是在子元素(table-cell)内部署居中,在table-cell的元素上设置vertical-align/text-align
居中问题:
1、【相对定位,水平居中】,最简单的是margin: xxpx auto,左右就居中了。
2、【绝对定位,水平竖直居中,需要知道宽高】负边距,设置left为50%(父元素的一半),margin-left为自身宽度的50%且为负,此方法适用于垂直居中,但是如果是relative的元素,最邻近定位元素直接是body的话,top:50%是不会奏效的,absolute可以。
3、【绝对定位,水平竖直居中,无需知道宽高】:transform,同样设置top、left为50%,transform: translate(-50%,-50%);
4、【相对定位,无需知道宽高】之前说了那么多关于line-height的问题,就在这里使用,注意需要是inline-block元素,relative定位,原因如前所述,将父元素line-height设置为父元素的高度,把font-size设置为0以便将所有的线坍缩到绝对中点。
5、【父元素display: flex】flex居中,水平竖直分别为align-items:center; justify-content:center; 父元素top、left无效,margin有效。
6、【父元素display: table】父元素display指定为table-cell,并指定其vertical-align为middle(这是个只对行内元素有效的属性,记住是设置在父元素上面的,在这里css标准规定了它对于table-cell的效果),子元就能垂直居中了,但是父元素的top、left和marin、padding都失效了。
7、【父元素display: grid】
flex:
flex元素,设置垂直居中,justify-content:center,水平居中,align-items:center,注意使用flex后,每个元素可以设置宽高(如果当flex-wrap为wrap,也就是允许换行的时候才有效,当nowrap的时候,各个元素会按照实际的宽度比值来分配宽度,比如父元素300px,其他元素20%,也就是60px,某元素设置为120px,当元素个数太多的时候,就会按照1:2分配这两种元素),没设置的填满剩下的。
flex-direction,指定填充方向(row,column),默认是column
flex-wrap,指明是否换行(nowrap不换行,wrap换行)
justify-content,主轴方向上的对齐方式,主轴就是flex-direction中指定的方式。
align-items,垂直轴的对齐方式。