关于盒模型+flex+position属性的总结
给碌碌无为的自己, 留下一点痕迹, 证明曾经来过。
本文主要内容有以下几点:
- 盒模型
- 布局
- float属性的引入
- BFC介绍
- Flex布局
- 定位:
postion
属性。
盒模型
在CSS中,会把所有HTML标签当作一个"透明"的盒子来处理。所有的盒子会被划分为两类
- 块级盒子
- 内联盒子
块级盒子
块级盒子的特性:
- 在网页上独占一行,所占据的宽度是父元素宽度的百分百
- 块级盒子可独立设置宽高
- 块级盒子的实际大小受到
margin,border,padding
的影响
盒模型的效果如下所示:
- 从黑色边框到箭头所指的地方为外边距:由margin属性控制。影响的是盒子与盒子之间的距离。
- 粉红色区域为内边距,由padding属性控制。控制的是内容区到border的距离。
- 黑色为边框。由border属性控制。
content
区域的大小由width,height
属性控制。
因此盒子的水平方向的大小为 margin-left
+margin-right
+ width
+ border-left
+border-right
+ padding-left
+ padding-right
盒子的垂直方向的大小为 margin-top
+ margin-bottom
+ height
+ border-top
+ border-bottom
+ padding-top
+ padding-bottom
内联盒子
内联盒子有如下特性
- 在网页上不会独占一行,默认的情况下,盒子沿着内联方向依次排列
- 不能设置宽高,大小完全由内容撑开
- 垂直方向的margin和padding会被应用,但是不会把其他元素撑开
<style>
.box2 {
width: 100px;
height: 100px;
background-color: black;
/* margin-top: 200px; */
}
span{
margin-top: 100px;
border: 1px solid red;
}
strong{
padding-top: 100px;
/* background-color: aqua; */
border: 1px solid #555;
}
</style>
<body>
<div class="box2">
我是块级盒子
</div>
<span>我是一个内联盒子被设置了 <code>margin-top:100px</code></span>
<span>我是一个内联盒子被设置了 <code>margin-top:100px</code></span>
<span>我是一个内联盒子被设置了 <code>margin-top:100px</code></span>
<span>我是一个内联盒子被设置了 <code>margin-top:100px</code></span>
<strong>我是一个内联盒子被设置了 <code>padding-top:100px</code></strong>
</body>
打开调试器(F12)可以看到span元素的margin-top
确实存在,但和box2
之间并没有100px的间距,padding在垂直方向上也是如此
此时给span和strong分别添加margin-left: 20px;
padding-left: 100px;
打开调试者窗口就可以看到如下信息
可以看到在水平方向的margin和padding都起了作用。
盒模型之间的相互转换
display属性可以切换盒子的外在变现形式,
display:block
可以将盒子的外在表现形式切换为块级元素
display:inline
可以将块级盒子切换为内联盒子
display:inline-block
可以将盒子设置为处于块级盒子和内联盒子之间的中间态: 即可以设置宽高,且不会独占一行。
外边距重合问题
盒子和盒子之间的距离由margin
属性控制,因此当相邻两个盒子设置了相对方向的margin 就会出现外边距重叠的问题
<style>
.box1 {
width: 200px;
height: 200px;
border: solid 1px #333;
background-color: #696969;
margin-bottom: 200px;
}
.box2 {
width: 200px;
height: 200px;
border: solid 1px #333;
background-color: red;
margin-top: 100px;
}
</style>
<body>
<div class="box1"></div>
<div class="box2"></div>
</body>

小记:上述盒模型的成立实在box-sizing:content-box;
条件下成立,当box-sizing:border-box;
时,也成立,只不过盒子的大小计算有差异。在这种情况下,width,height
属性控制的是整个块级盒子的大小。内容区域的大小为:整个盒子的大小 - 相应的border和margin属性的值。
文档流
Normal Flow: 在默认情况下 HTML页面元素的布局方式是:块级元素从上到下排列,内联元素沿着内联方向水平排列。
浮动
float属性最初的引入是为了进行简单的布局,如首字下沉等。 默认排版如下:

首字下沉:

但是web开发人员在实际工作中发现,任何盒子都可以使用float
。而float
属性的使用也会导致其他问题。
float:left/right
当元素设置了这个属性时,该元素会脱离正常的文档流。显示效果会"高于"其他处于正常文档流的元素。浮动的元素在脱离正常文档流之后,在原本的文档流中将不占据位置。因此会导致如下情况的发生
- 父元素的高度丢失。
- 垂直方向的元素外边距塌陷
- 演示父元素高度丢失。
html代码结构:
<div class = "container">
<div class="box"><div>
<div class="box"><div>
<div>
css代码:
.container{
border: 1px solid #333;
}
.box{
width: 200px;
height: 200px;
border: solid 1px red;
margin: 10px;
background: #555;
}
效果如下
给box添加如下属性float:left;
就可以看见两个元素均脱离了原文档流。导致container容器的高度丢失。
- 外边距塌陷 [父子关系]
<style>
.container {
background-color: aqua;
width: 300px;
height: 300px;
}
.box {
margin-top: 100px;
width: 100px;
height: 100px;
background-color: #666;
}
</style>
<body>
<div class="container">
<div class="box">
</div>
</div>
</body>
可以看到本应该是灰色的盒子距离大盒子的顶部100px,实际却是父元素向下塌陷了100px;
- 非兄弟元素之间的外边距重叠问题:
<head>
<style>
.container {
/* display: flow-root; */
}
.box {
margin-bottom: 100px;
width: 100px;
height: 100px;
background-color: #666;
}
.box2 {
width: 100px;
height: 100px;
background-color: black;
margin-top: 200px;
}
</style>
</head>
<body>
<div class="container">
<div class="box">
</div>
</div>
<div class="box2"></div>
</body>
BFC
Block Formatting Context:指块级盒子的布局过程中发生的区域,为浮动或者定位的元素开启一块块级区域。可以理解为一块单独的布局区域。简称BFC。开启一块包含浮动的布局或者消除外部布局的影响
在新开启的布局区域里面。会排除掉其他布局区域元素的影响。
作用:
- 包含内部浮动:即创建包含浮动的BFC 如上面的演示父元素高度丢失的例子
- 阻止外边距重叠
- 排除外部浮动
- 包含内部浮动的作用演示:
父元素高度丢失的解决方法。
- 利用clear属性。clear属性:消除浮动的影响
.container::after{ content: ""; display: table; clear: both; }
通过
display:flow-root;
开启bfc。
- 父子间的外边距塌陷也可通过
display:flow-root;
开启bfc。解决
- 阻止外边距重叠的作用演示
上述的例子3. 按照预期结果间距应该是100+200 = 300px;因为发生了重叠,因此在父元素上添加
display:flow-root;
属性。解决方法就是给
container
开启BFC如display:float-root;
或者通过clean属性消除float元素的影响。
- 排除外部浮动
由于使用了float元素的会脱离原本的原本的位置,在其下的元素会向上移动。因此就会出现这种情况
<style>
.box{
background-color: aqua;
margin: 10px;
border: 2px solid #666;
font-size: 28px;
width: 60px;
float: left;
width: 200px;
height: 150px;
}
.info{
background-color: aquamarine;
/* display: flow-root; */
}
</style>
<div class="container">
<div class="box"></div>
<div class="info">
<p >这是一段文字。。。</p>
</div>
</div>
因此为了消除 box
对 info
的影响 只需要在info上开启BFCC即可。即display:flow-root;
除此之外还有一种情况
<style>
.container{
background-color: aquamarine;
}
.box{
background-color: aqua;
margin: 10px;
border: 2px solid #666;
font-size: 28px;
float: left;
width: 200px;
height: 150px;
}
</style>
<div class="container">
<div class="box"></div>
<p>这是一段很长的文字信息...很长很长很长。。。。。。。。</p>
</div>
此时的显示效果如下,因为box元素开启了float属性,导致其显示层级在p元素之上。因此p元素上衣,就出现了如下效果。
为了消除这种影响。可以在container元素上添加display:flow-root;
开启一个包含浮动的BFC布局
Flex布局
开启flex之后的默认行为
如果说display:block/inline;
属性改变了元素的外在表现形式。则display:flex;
改变了元素内部的排列方式。
- 在开启flex布局后,容器内的元素将会按照 主轴 (main axis) 和 交叉轴 (cross axis)的方向来排列元素。默认情况下
主轴从左到右,左边为起始方向,右边为终止方向。
交叉轴从上到下,交叉轴垂直于主轴方向。
主轴的方向由flex-direction
属性控制
flex-direction:
- row: 默认 起始在做 终止在右
- row-reverse:水平方向,起始在右,终止在左
- column:从上到下 起始在上 终止在下
- column-reverse 从下到上,起始在下,终止在上
默认值: flex-direction:row
改变主轴方向为交叉轴方向:flex-direction:column
- 在开启Flex的属性的元素中,默认全部元素在一行显示,呈一维状。可以通过
flex-wrap
属性来改变元素是否换行排列
确定flex-item的大小
在知晓了dispaly:flex
的默认行为之后,就来确定flex容器元素的大小。
- flex-basic
- flex-grow
- flex-shrink
eg3: 代码及效果如下
<style>
.flex-container{
display: flex;
width: 500px;
height: 200px;
border: solid seagreen 1px;
}
.box1{
background-color: aqua;
width: 100px;
}
.box2{
background-color: burlywood;
width: 100px;
}
.box3{
background-color: cadetblue;
width: 100px;
}
</style>
<body>
<div class="flex-container">
<div class="box1">1</div>
<div class="box2">2</div>
<div class="box3">3</div>
</div>
</body>
- flex-basic
默认情况下。flex-item元素会在交叉轴方向align-self:stretch;
拉伸至父容器的高度。
box1,box2,box3都设置了width:100px
; 于是乎空白区域的大小为 500 - 300 = 200px; 这片空白区域的大小可称为 available space
;
由于均设置了width:100px;
因此每一个item的大小就是100px,换言之。如果没有设置width属性,即flex-basic:auto;
则flex-basic
的值采用元素内容尺寸。即元素content
区域。
- flex-grow
当flex-item的大小之后小于container容器时,为了达到内容填满容器的效果,可通过此属性控制u
在上面的例子中,用于还剩下200px的 available space
。因此分别对box1,box2,box3 添加flex:5;flex:3;flex:2;
可以看到1,2,3 得到了不同程度的增大。如下图:
每个的大小分别为200px;160px;140px;计算方式为 原大小 +( 自己的flex-grow / 所有的flex-grow之和 ) * available space;
以box1为例子则:100px + (5/(2+3+5)) * 200 = 200px
;box1的盒模型图如下
- flex-shrink
flex-grow 属性负责按比例扩大元素。当所有元素大小之和大于container的宽度之时。则 flex-shrink 负责按比例缩小元素。只不过available space
不再是未填满的区域, 而是多出的空间。即 available space = 所有item之和 - container的值
。
将box1,box2,box3 的宽度都设置为200px 此时 available space = 600 - 500 = 100px
;
分别给box1,box2,box3设置flex-shrink:5;flex-shrink:3;flex-shrink:2
; 则效果图如下
可以看到 box1 目前最小,缩小得最多。此时box1的大小为 200 - (5 / 10) * 100 = 150px; box1的盒模型图如下
注:通常 flex-grow
flex-shrink
flex-basic
这三个属性不会单独使用。通常简写为flex如:flex: 1, 1, auto;
则代表 flex-grow:1;flex-shrink:1;flex-basic:auto;
flex-item在flex容器中的分布和排列顺序
- 在开启
display:flex
之后,我们知道flex-item元素默认排在一行且不会换行。 - flex容器中的每一项在交叉轴方向得到拉伸,默认是flex容器的高度。
因此如何控制每一个 flex-item 在主轴或交叉轴的排列?
属性控制:
- justify-content: 控制主轴上所有flex项目的对齐
- align-items: 控制交叉轴上所有项目的对齐
- align-self: 控制交叉轴上的单个元素的对齐
- align-content: 控制 "多条主轴"的flex项目交叉轴的对齐。
排列顺序:
有时候存在如下情况:
<style>
.container{
width: 600px;
height: 400px;
display: flex;
justify-content: space-around;
}
.box{
width: 100px;
height: 100px;
border: solid 1px red;
}
</style>
<body>
<div class="container">
<div class="box">我是第一个元素但是我想在最后</div>
<div class="box">我是第二个元素但是我想在最前面</div>
<div class="box">我是第三个元素但是我想在第一个前面</div>
<div class="box">我是最后一个但是我想在二三之间</div>
</div>
</body>
此时的显示效果如下:
因此为了达到显示的效果可以通过order
属性控制,order
属性的值越小,就越靠近主轴的开始方向。
在CSS中添加如下规则。
.container :nth-child(1){
order: 4;
}
.container :nth-child(2){
order: 1;
}
.container :nth-child(3){
order: 2;
}
.container :nth-child(4){
order: 3;
}
此时显示效果如下:
定位 position
如果说flex布局在一定程度上规定了元素的大体的框架排列。则 position
属性就相当于"微操"。即display:flex
在布局上相当于决定了一个人整体的面部,那么position
就相当于整个双眼皮这种微调。
- position
- 1.static 默认值,没有开启的定位
2.relative 开启相对定位 参照位为元素在文档流中的位置。相对于自己以前的位置。
特点:
1.开启相对定位后,如果不设置偏移量,则元素不会发生任何变化
2.offset 偏移量:改变元素的位置 开启定位后 通过下列几个值来设置偏移量 垂直方向
- top:定位元素和定位位置上边的距离 从上往下压
- bottom:定位元素和定位位置下边的距离 水平方向
- left:定位元素和定位位置左边的距离
- right:定位元素和定位位置右边的距离
3.相对定位会提高元素的层级
4.相对定位不会脱离文档流,不会改变元素的性质
.wrapper{
}
.box{
height: 100px;
width: 200px;
background-color: beige;
}
.relative-box{
width: 300px;
height: 200px;
background-color: aquamarine;
}
<body>
<div class="wrapper">
<div class="box">
我是一个参照盒子
</div>
<div class="relative-box">
我是相对定位 相对与原来的位置移动
</div>
</div>
</body>
此时两个盒子挨在一起如下图所示。 给.relative-box
添加position:relative;top:50px;
可以看到两个盒子间间隔了50px;top:50px;
相当于有个在上面的力,这个力的大小导致盒子向下移动了50px的位置。
3.absolute 开启绝对定位 特点
1.开启绝对定位后,不设置偏移量 元素的位置不会发生变化
2.元素会从文档流中脱离
3.绝对定位会改变元素的性质
4.绝对定位会提升元素层级 参照物:绝对定位相对于其包含块进行定位的。 包含块是开启了定位的元素即非static元素 包含块containing block:
1.绝对定位的包含块就是离他最近的开启了定位的祖先块元素
- 1.如果所有的祖先元素都没有开启定位,则根元素就是他的包含块 html--初始包含块
<style>
.wrapper{
position: relative;
width: 400px;
height: 300px;
background-color: #666;
}
.box{
height: 100px;
width: 200px;
background-color: beige;
}
.absolute-box{
/* position: absolute; */
width: 300px;
height: 200px;
background-color: aquamarine;
/* top: 0; */
}
</style>
<div class="wrapper">
<div class="box">
我是一个参照盒子
</div>
<div class="absolute-box">
我是绝对定位 相对于最近的开启定位的元素
</div>
</div>
默认的显示效果如下
此时添加position:absolute
可以发现元素表面上没有任何变化。添加top:0
就可以看到参照盒子被遮住了!! 这就是因为开启绝对定位后,该元素脱离了文档流,导致显示层级高于的参照盒子。
此时可以通过z-index
属性控制元素的显示, z-index
只对开启了定位的元素起作用。z-index
的值越大。显示的优先级就越高。
给参照盒子添加z-index:1;
就可以看到如下效果
4.fixed 开启固定定位 特点
- 1.一种特殊的绝对定位。永远参照于浏览器的视口进行定位。
- 2.元素不会随着网页固定定位发生改变
<head>
<style>
.wrapper{
position: relative;
width: 400px;
height: 2000px;
background-color: blanchedalmond;
}
.fixed-box{
position: fixed;
bottom: 100px;
background-color: aqua;
}
</style>
</head>
<body>
<div class="wrapper">
<div class="fixed-box">
我是一个参照盒子 <br> <code> position: fixed; bottom: 100px;</code>
</div>
</div>
</body>
</html>
此时无论怎么滑动,他的位置都不会变。
- 5.sticky :粘性定位可以被认为是相对定位和固定定位的混合。元素在跨越特定阈值前为相对定位,之后为固定定位。例如
position:sticky;top:0px
<style>
.wrapper{
width: 400px;
height: 2000px;
}
.box{
background-color: red;
width: 90%;
margin: 5px;
height: 30px;
}
.sticky-box{
position: sticky;
top: 0;
background-color: aqua;
}
</style>
<body>
<div class="wrapper">
<div class="box">1</div>
<div class="box">2</div>
<div class="sticky-box">
我是一个参照盒子 <br> <code> position: sticky; top: 20px;</code>
</div>
<div class="box">3</div>
<div class="box">4</div>
<div class="box">5</div>
<div class="box">6</div>
<div class="box">7</div>
<div class="box">8</div>
<div class="box">9</div>
</div>
</body>
默认效果是这样
当使用鼠标向下滑时:当开启position: sticky;
的元素滑指与top的距离为指定的距离后,就不再继续滑动。
参考资料:
转载自:https://juejin.cn/post/7203968787326140453