CSS 定位机制
CSS 有三种基本的定位机制:普通流、浮动和绝对定位。
普通流
除非专门指定,否则所有框都在普通流中定位。也就是说,普通流中的元素的位置由元素在 (X)HTML 中的位置决定。
块级框从上到下一个接一个地排列,框之间的垂直距离是由框的垂直外边距计算出来。
行内框在一行中水平布置。可以使用水平内边距、边框和外边距调整它们的间距。但是,垂直内边距、边框和外边距不影响行内框的高度。由一行形成的水平框称为行框(Line Box),行框的高度总是足以容纳它包含的所有行内框。不过,设置行高可以增加这个框的高度。
浮动
float 属性定义元素在哪个方向浮动。浮动元素会生成一个块级框,而不论它本身是何种元素。
float: left|right|none|inherit;
position定位
任何元素都可以定位,不过绝对或固定元素会生成一个块级框,而不论该元素本身是什么类型。相对定位元素会相对于它在正常流中的默认位置偏移。
float: absolute|fixed|relative|static|inherit;
什么是块级格式化上下文(BFC)
“BFC即 Block Formatting Contexts (块级格式化上下文), 是 W3C CSS2.1 规范中的一个概念。它是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。”
如何触发BFC
- body 根元素
- 浮动元素:float 除 none 以外的值
- 绝对定位元素:position (absolute、fixed)
- display 为 inline-block、table-cells、flex、inline-flex、flow-root(没有副作用的方案,但需注意兼容性)、grid、inline-grid等
- overflow 除了 visible 以外的值 (hidden、auto、scroll)
BFC的特性
1、内部的Box会在垂直方向上一个接一个的放置
2、垂直方向上的距离由margin决定。(完整的说法是:属于同一个BFC的两个相邻Box的margin会发生重叠(塌陷),与方向无关。)
3、每个元素的左外边距与包含块的左边界相接触(从左向右),即使浮动元素也是如此。(这说明BFC中子元素不会超出他的包含块,而position为absolute的元素可以超出他的包含块边界)
4、BFC的区域不会与float的元素区域重叠
5、计算BFC的高度时,浮动子元素也参与计算
6、BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面元素,反之亦然
BFC的应用
清除浮动(同时说明特性3、特性5、特性6)
<style>
.content-box {
background: #fff;
width: 300px;
border: 5px solid #FF4500;
}
.child1 {
width: 200px;
height: 200px;
background: #FFA500;
float: left;
}
</style>
<body>
<div class="content-box">
<div class="child1"></div>
</div>
</body>

- 子元素浮动,脱离文档流,父元素高度只剩下border
<style>
.content-box {
background: #fff;
width: 300px;
border: 5px solid #FF4500;
overflow: hidden; // 让父元素触发BFC
}
.child1 {
width: 200px;
height: 200px;
background: #FFA500;
float: left;
}
</style>

- 触发父元素的BFC,父元素高度恢复,故计算BFC的高度时,浮动子元素也参与计算(特性5)
防止元素上下margin折叠(同时说明特性2、特性6)
<style>
.content-box {
background: #fff;
width: 300px;
border: 5px solid #FF4500;
}
.child {
width: 200px;
height: 200px;
background: #FFA500;
margin: 50px auto;
}
</style>
<body>
<div class="content-box">
<div class="child"></div>
<div class="child"></div>
</div>
</body>

- 两个子元素的上下外边距发生重叠,距离只差50px(应该为第一个子元素的bottom-margin+第二个元素的top-margin=100px)
<style>
.content-box {
background: #fff;
width: 300px;
border: 5px solid #FF4500;
}
.parent {
overflow: hidden; // 将外边距折叠的元素放入两个不同的BFC容器中
}
.child {
width: 200px;
height: 200px;
background: #FFA500;
margin: 50px auto;
}
</style>
<body>
<div class="content-box">
<div class="parent">
<div class="child"></div>
</div>
<div class="parent">
<div class="child"></div>
</div>
</div>
</body>

- 将发生外边距重叠的子元素分别放入两个BFC容器中,每个BFC都是一个独立的容器
实现两栏布局
<style>
.content-box {
background: #fff;
width: 300px;
}
.left {
width: 200px;
height: 200px;
background: #FFA500;
float: left;
}
.right {
background: #FF4500;
color: #fff;
}
</style>
<body>
<div class="content-box">
<div class="left"></div>
<div class="right">
除非专门指定,否则所有框都在普通流中定位。也就是说,普通流中的元素的位置由元素在 (X)HTML 中的位置决定。
块级框从上到下一个接一个地排列,框之间的垂直距离是由框的垂直外边距计算出来。
行内框在一行中水平布置。可以使用水平内边距、边框和外边距调整它们的间距。但是,垂直内边距、边框和外边距不影响行内框的高度。由一行形成的水平框称为行框(Line
Box),行框的高度总是足以容纳它包含的所有行内框。不过,设置行高可以增加这个框的高度。
</div>
</div>
</body>

- 浮动元素会覆盖未浮动元素,但文字不会被覆盖。
<style>
.content-box {
background: #fff;
width: 300px;
}
.left {
width: 200px;
height: 200px;
background: #FFA500;
float: left;
}
.right {
background: #FF4500;
color: #fff;
overflow: hidden; // 右侧未浮动元素,触发BFC
}
</style>
<body>
<div class="content-box">
<div class="left"></div>
<div class="right">
除非专门指定,否则所有框都在普通流中定位。也就是说,普通流中的元素的位置由元素在 (X)HTML 中的位置决定。
块级框从上到下一个接一个地排列,框之间的垂直距离是由框的垂直外边距计算出来。
</div>
</div>
</body>

- 未浮动元素触发BFC,能避免被浮动元素覆盖
实现同等高度的两栏
<style>
.content-box {
background: #fff;
width: 300px;
overflow: hidden;
}
.content-box>div {
/* 注意这里 */
padding-bottom: 100000px;
margin-bottom: -100000px;
}
.left {
background: #fadc09;
height: 300px;
width: 100px;
float: left;
}
.right {
height: 100px;
background: #faa509;
display: flow-root;
}
</style>
<body>
<div class="content-box">
<div class="left"></div>
<div class="right">
除非专门指定,否则所有框都在普通流
</div>
</div>
</body>

总结
这让我想起上一次面试的时候,面试题就是让我实现这样的两栏布局,然而小菜鸟的我,还不是很理解BFC原理竟然用flex,然后写了好多样式,而且还及其不智能。哈哈哈~
以上三种对于BFC的应用都很普遍,再也不用新增新元素,用clear:both来清除浮动拉~
值得一说的是:就在我看了好多BFC相关的文章,学习了BFC相关的原理之后没几天,就有同事问我边距被压缩的问题,我一看就是边距重叠了,都没想就说你拿一个div包一下加个overflow:hidden啥的。瞬间感觉没有白学呀,感觉自己挺牛逼呀~虽然我知道我其实还是一个小菜鸟。哈哈哈~
但是我会继续努力哒~