正常布局流(normal flow)与定位
我们知道了盒模型,知道了如何表示长度,本节将介绍如何控制这些“盒子”即元素的定位。
正常布局流(normal flow)
在“盒模型”一节我们了解了通过设置 margin
, padding
, border
, width
, height
改变一个元素的行为,但是没有讨论多个元素该如何排列。
在我们自定义元素定位之前,先了解下浏览器默认的行为是怎样的。在HTML 常用元素与属性章节中,我们介绍了块级元素(Block-level elements)和行内元素(Inline elements):
块级元素默认会占满父元素的宽度,前后各新起一行,隔断(Block)其之前与之后的元素。而行内元素默认不会新起一行,大小取决于自己的内容。
体现在 CSS 上,块级元素拥有 display: block
的属性,行内元素有 display: inline
的属性。比如 <span>
元素默认为 display: inline
,可以通过 CSS 改变这个默认属性。
大部分元素 display
属性的默认值是 inline
或 block
。display
还有更多值可以设置,查看 MDN 文档:display 属性 了解更多。
默认情况下,block
元素从上而下排列,而 inline
元素从前往后排列,这个排列方式叫“正常布局流(normal flow)”。
定位
可以通过定位来让元素脱离正常布局流,让他有其他的定位属性。通过设置 position
属性来改变定位,这个属性的值有 5 种:
position: static
未定位的元素 元素根据正常布局流定位,即浏览器默认属性。
position: relative
相对定位元素 元素根据正常布局流定位,加上top
,right
,bottom
,left
的偏移。偏移后不会影响其他元素的布局,仅仅影响自身。
下面代码使用了相对定位:
.relative50 {
position: relative;
left: 5px;
top: 5px;
background-color: yellow;
color: black;
}
<p>如果给元素设置了 relative 属性,<span class="relative50">该元素</span>可以相对原先位置偏移</p>
如果给元素设置了 relative 属性,该元素可以相对原先位置偏移
position: absolute
绝对定位元素 元素脱离正常布局流。后面的元素会当作其不存在而占用其原本的空间。元素的位置根据离他最近的,定位过的祖先元素决定,此时 top
,right
,bottom
,left
属性即离这个祖先元素的顶端,右边,地步,左边的距离。定位过的元素表示 position
的值不是默认值 static
的元素。
下面的代码使用了 position: absolute
.relative0 {
position: relative;
width: 300px;
height: 300px;
background-color: #555;
}
.absolute50 {
position: absolute;
width: 100px;
height: 100px;
right: 50px;
bottom: 50px;
background-color: yellow;
color: #000;
}
<div class="relative0">
<div class="absolute50">
该元素相对于父元素绝对定位
</div>
</div>
position: fixed
绝对定位元素 元素脱离正常布局流。后面的元素会当作其不存在而占用其原本的空间。与 absolute
不一样的是,此时元素不相对于某个其他元素定位,而是与 viewport 相对,top
,right
,bottom
,left
属性即离 viewport 顶端,右边,地步,左边的距离。
下面的代码使用了 position: fixed
.fixed5 {
position: fixed;
width: 100px;
height: 100px;
right: 5px;
bottom: 5px;
background-color: yellow;
color: #000;
}
<div class="fixed50">
position: fixed 例子:保持在浏览器窗口的右下角
</div>
position: sticky
粘性定位元素 此时元素可以认为是 static
和 absolute
的结合。当元素在最近的有滚动机制的(overflow
属性不为默认值 visible
)祖先元素一定范围之内时,行为与static
一样,当超过了范围,行为与absolute
一样,根据 top
,right
,bottom
,left
和这个祖先元素决定位置。
这个属性是相对比较新的,在实际使用的时候注意浏览器兼容性。
下面例子中的 I'm sticky 元素是粘性定位,可以试着滚动后的效果。
<div style="height: 200px; overflow: scroll; margin: 0; padding: 0;">
<div style="height: 70px; background-color: #1587cc"></div>
<div style="height: 70px; background-color: #158766"></div>
<div style="position: sticky; top: 0; color: #FFFFFF; background-color: #153366; text-align: center">I'm sticky</div>
<div style="height: 70px; background-color: #155566"></div>
<div style="height: 70px; background-color: #558766"></div>
<div style="height: 70px; background-color: #998766"></div>
<div style="height: 70px; background-color: #1587cc"></div>
<div style="height: 70px; background-color: #158766"></div>
<div style="height: 70px; background-color: #558766"></div>
</div>
浮动元素
浮动元素是 float
不为默认值 none
元素。浮动元素也会使元素脱离正常布局流,然后让该元素处于其父元素的左边或者右边,或者紧挨着另外一个浮动元素。与绝对定位不同的是,浮动元素会让文字环绕自己,而不是重叠。float
的值可以为 left
, right
或 none
。
例如:
<div>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi tristique sapien ac erat tincidunt, sit amet dignissim lectus vulputate. <div style="float: left; background: yellow; width: 50px; height: 50px;"></div>Donec id iaculis velit. Aliquam vel malesuada erat. Praesent non magna ac massa aliquet tincidunt vel in massa. Phasellus feugiat est vel leo finibus congue. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</div>
清除浮动 Clearing floats
在浮动元素后面的元素,可能会与之重叠。有的时候不是想要的效果,例如:
<div>
<div style="float: left; height: 50px; width: 40%; background: yellow"></div>
<div style="float: right; height: 80px; width: 40%; background: yellow"></div>
</div>
<p style="background: #1587cc; margin: 0">
新起一个块级元素,这个元素没有排列为新的段落。
</p>
新起一个块级元素,这个元素没有排列为新的段落。
上面例子初看起来有点反直觉。为什么新的 <div>
不是新起一行呢?原因是,由于第一个 <div>
元素的子元素都是浮动元素,脱离了正常布局流,因此这个 div 高度为 0。而下面的 <p>
元素就顶到最上面了。
所以解决这个问题的1方法是给第一个 <div>
设置高度:
<div style="height: 80px">
<div style="float: left; height: 50px; width: 40%; background: yellow"></div>
<div style="float: right; height: 80px; width: 40%; background: yellow"></div>
</div>
<p style="background: #1587cc; margin: 0">
新起一个块级元素,这个元素没有排列为新的段落。
</p>
新起一个块级元素,设置前面元素的高度使这个元素成为新的段落。
但是如果浮动的元素高度不确定,就不起效果了。解决这类问题最好的方法是:清除浮动。我们给 <p>
元素加上 clear: both;
后:
<div>
<div style="float: left; height: 50px; width: 40%; background: yellow"></div>
<div style="float: right; height: 80px; width: 40%; background: yellow"></div>
</div>
<p style="background: #1587cc; margin: 0; clear: both;">
新起一个块级元素,clear: both 使这个元素成为新的段落。
</p>
新起一个块级元素,clear: both 使这个元素成为新的段落。
clear
属性可以为 left
, right
, both
, none
。left
/right
设置后面的元素比左/右浮动的元素低,both
设置元素比左右浮动的元素都低。none
为默认值,没有清除浮动的效果。
clear
属性也可以作用于非浮动元素,可以通过 MDN 文档:clear 属性 查看详情。
浮动元素曾经常用作页面布局,例如左侧菜单,右侧内容的两列布局。现代 HTML 有更好的方式:Flexbox 和 Grid(将在后面章节介绍),因而浮动元素的使用也变少了。
参考
- All about float: https://css-tricks.com/all-about-floats/