本文主要讲一些关于CSS布局的方法,在此之前,我看到了不少关于布局方面的好文章,也收到了非常多的启发,所以写此文章,将一些想法给记录下来。
说到布局,大多数人肯定会想到的几个常用的属性:position、float、flex等。本文主要讲述这几个属性的使用方法以及分栏布局的实现。
本文的结构如下:
- HTML的布局要点(盒模型、普通流)
- positon属性
- float属性
HTML的布局要点:
对position、float等属性熟练使用的话,那么HTML的基本布局特点是要了如指掌的。HTML的基本布局特点有两个:
- 盒子模型(box model)
- 普通流(normal flow)
盒模型
盒模型包括四个部分:margin(外边距)+border(边框)+padding(内边距)+content(内容)。css中包括两种不同的盒模型,可以通过box-sizing设置不同的模型。两种盒子模型,主要是width的宽度不同.
在标准的盒模型中,一个元素的范围包括margin、border、padding、content,width=content。当把box-sizing属性设置为border-box时,width=content+padding+border的总和。
在IE盒模型中,元素的范围和标准盒模型相同,但是width大小不同,这里的width=content+padding+border。
对于不同的模型的宽度是不同的。宽度默认的属性值是auto,这个属性值会使得内部元素的长度自动填充满父元素的width。height的属性值也是默认的auto,为什么没有像width一样呢?其实,auto这个属性值表示的是浏览器自动计算。这种自动计算,需要一个基准,一般浏览器都是允许高度滚动的,所以,会导致一个问题——浏览器找不到垂直方向上的基准。同样地道理也会被应用在margin属性上。相信如果考察居中时,水平居中你可能闭着眼睛都能写出来,但是垂直居中却绕着脑袋想。这是因为如果是块级元素水平居中只要将水平方向上的margin设置成auto就可以了。但是,垂直方向上却没有这么简单,因为你设置成auto时,margin为0。这个问题,还是需要仔细思考一下的。
HTML元素中的盒模型分为两类:块元素和行内元素。
- 块元素(block)可以设置width、height属性,而行内元素(inline)设置无效。
- 块元素会独占一行(直观的说就是会换行显示,无法与其他元素在同一行内显示,除非你主动修改元素的样式),而行内元素则都会在一行内显示。
- 块状类型的元素的width默认为100%,而行内(Inline)类型的元素则是根据自身的内容及子元素来决定宽度。
常见的元素分类:
- 块元素:div、article、canvas、ul....
- 行内元素:button、input、label、select、textarea
普通流(文档流)
什么是普通流?简单说就是元素按照其在 HTML 中的位置顺序决定排布的过程。并且这种过程遵循标准的描述。行内元素是从左到右排布,块级元素是从上到下排布。只要不是float和绝对定位方式布局(absolute)的,都在普通流里面。
如果不改变元素的样式,那么所有元素在普通流中都占有一个位置。具体的大小、位置则是由元素的盒模型决定。
position属性
关于定位,首先想到的就是position属性。position有五个常用个属性:static、relative、absolute、fixed、sticky。
- static(默认):该关键字指定元素使用正常的布局行为,即元素在文档常规流中当前的布局位置。此时
top
,right
,bottom
,left
和z-index
属性无效。 - relative:它的偏移是相对于原先在文档流中的位置,普通流中仍然保留此元素的位置。relative不会改变行内元素的display值。
- absolute:如果其父元素没有设置position属性,则其根据body元素来变动,否则根据父元素的位置进行变动。此属性会脱离页面中的普通流并改变display的属性。行内元素应用了absolute属性后悔改变其display为block。应用了absolute/relative属性值后,很有可能会覆盖其他非定位元素(static),可以设置z-index的值以防止被覆盖。
- fixed:元素设置为此属性值后,其会脱离普通流,而且其根元素是浏览器窗口,即当你滚动网页,这个元素依旧会显示在浏览器的那个位置。fixed属性会创建新的层叠上下文。和absolute相同,fixed也会使行内元素的display变成block。
- sticky:盒位置根据正常流计算(这称为正常流动中的位置),然后相对于该元素在流中的 flow root(BFC)和 containing block(最近的块级祖先元素)定位。在所有情况下(即便被定位元素为
table 时
),该元素定位均不对后续元素造成影响。当元素 B 被粘性定位时,后续元素的位置仍按照 B 未定位时的位置来确定。position: sticky 对 table 元素的效果与 position: relative 相同。
<!DOCTYPE html> <html> <head> <title></title> <style type="text/css"> .container {background:yellow;width:200px;height:200px;top:50px;left:50px;position:absolute} .strong{background:blue} .thin{background:red} .test{background:green;top:50px;left:50px;position:relative} </style> </head> <body> <div class="container"> <span class="strong">strong</span><span class= "thin">thin</span><span class="test">test</span> </div> </body> </html>
relative下元素的定位(相对于原先文档流的位置):
position下元素的定位(相对于其父元素的位置):
fixed下元素的定位(相对于浏览器视口):
更多关于absolute的使用,如果是使用在多层的元素嵌套中,absolute和relative如何搭配使用呢?下面举个嵌套的例子:
<body style="background: yellow;"> <div style="background: #58c9f3"> A <div style="background: #e38cf3"> A - 1 <div style="background: #fac362;"> A - 2 </div> </div> </div> </body>
现在对A-2设置绝对定位:
<div style="background: #fac362;position:absolue;top:0;left:0">A - 2</div>
可以看到A-2根据body来产生了位移,让我们对比分别设置一下父元素position。
从上面的图,我们可以总结以下几个结论:
- 块状元素在position(relative/static)的情况下width为100%,但是设置了position: absolute之后,会将width变成auto(会受到父元素的宽度影响)。
- 元素设置了position: absolute之后,如果没有设置top、bottom、left、right属性的话,浏览器会默认设置成auto,而auto的值则是该元素的“默认位置”。即设置position: absolute前后的offsetTop和offsetLeft属性值不变。
Float属性
float的属性值有none、left、right,有几个要点:
- 只有横向浮动,并没有纵向浮动。
- 当元素应用了float属性后,将会脱离普通流,其容器(父)元素将得不到脱离普通流的子元素高度。
- 会将元素的display属性变更为block。
- 浮动元素的后一个元素会围绕着浮动元素(典型运用是文字围绕图片),与应用了position的元素相比浮动元素并不会遮盖后一个元素。
- 浮动元素的前一个元素不会受到任何影响(如果你想让两个块状元素并排显示,必须让两个块状元素都应用float)。
与position的兼容:
- 元素同时应用了position: relative、float、(top / left / bottom / right)属性后,则元素先浮动到相应的位置,然后再根据(top / left / bottom / right)所设置的距离来发生偏移。
- 元素同时应用了position: absolute及float属性,则float失效。
- 第一个元素应用了position之后会覆盖着接下来的float元素(如果两个元素所处的位置相同)
- 同时应用position: absolute和float: left会导致清除浮动无效(position: relative则可以清除浮动)。
常用的清除浮动的方法有两种:- 通过在容器中添加一个标签,设置该标签的样式为 clear: both
- 容器设置overflow: hidden
【参考资料】
- 从网易与淘宝的font-size思考前端设计稿与工作流:http://www.cnblogs.com/lyzg/p/4877277.html ???
- 对CSS中的Position、Float属性的一些深入探讨 (http://www.cnblogs.com/coffeedeveloper/p/3145790.html)????
- Rem布局的原理解析:http://yanhaijing.com/css/2017/09/29/principle-of-rem-layout/ ????
- CSS布局说:https://github.com/laizimo/zimo-article/issues/36 ???
- https://www.w3.org/TR/CSS2/indexlist.html ????
- http://www.cnblogs.com/iyangyuan/archive/2013/03/27/2983813.html ???