CSS布局
2023-08-22 18:12:46 #CSS

盒子模型的宽度计算

  • offsetWidth = width + boder + padding,无外边距
  • box-sizing: border-box; 即所设置的盒子 width = offsetWidth
1
2
3
4
5
6
7
8
9
10
11
12
13
// div1的 offsetWidth 是多少? 122px
// 如果设置了 box-sizing: border-box; 则 offsetWidth = 100px(其中宽度78px)

<style>
#div1 {
width: 100px;
padding: 10px;
border: 1px solid #ccc;
margin: 20px;
}
</style>

<div id="div1"></div>

margin 纵向重叠

  • 相邻元素的 margin-topmargin-bottom 会发生重叠
  • 空白内容的<p></p>也会重叠
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// AAA和BBB之间的距离是多少? 15px

<style>
p {
font-size: 16px;
line-height: 1;
margin-top: 10px;
margin-bottom: 15px;
}
</style>

<p>AAA</p>
<P></P>
<P></P>
<P></P>
<P>BBB</P>

margin 负值

  1. 元素设置了浮动

    • 如果设置的 margin 的方向与浮动的方向相同,那么,元素会往对应的方向移动对应的距离
    • 如果设置 margin 的方向与浮动的方向相反,则元素本身不动,元素之前或者之后的元素会向该元素的方向移动相应的距离
  2. 元素没有设置浮动,且没有设置定位或者 position 为 static

    • margin-top 和 margin-left 负值,元素向设置的方向移动相应的距离
    • margin-right 和 margin-bottom 负值,元素本身不移动,元素后面的其他元素会往该元素的方向移动相应的距离,并且会覆盖在该元素上面
  3. 元素没有设置浮动,且 position 为 relative

    • margin-top 和 margin-left 负值,元素向设置的方向移动相应的距离
    • margin-right 和 margin-bottom 负值,元素本身不移动,元素后面的其他元素会往该元素的方向移动相应的距离,该元素会覆盖在后面的元素上面
  4. 元素没有设置浮动,且 position 为 absolute

    • margin-top 和 margin-left 负值,元素向设置的方向移动相应的距离
    • margin-right 和 margin-bottom 负值,元素本身不移动,对后面的元素没有影响

BFC 理解和应用

什么是 BFC

  • Block formatting cotext,块级格式化上下文
  • 一块独立渲染区域,内部元素的渲染不会影响边界以外的元素

BFC 的布局规则

  • 内部的 Box 会在垂直方向,一个接一个地放置
  • Box 垂直方向的距离由 margin 决定,属于同一个BFC的两个相邻 Box 的 margin 会发生重叠
  • 每个盒子(块盒与行盒)的 margin box 的左边,与包含块 border box 的左边相接触(对于从左往右的格式化,否则相反),即使存在浮动也是如此
  • BFC的区域不会与 float box 重叠
  • 计算 BFC 的高度时,浮动元素也参与计算
  • BFC 就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之也如此

如何创建 BFC

  • float 不是 none
  • overflow 不是 visible
  • position 是 absolute、fixed
  • display 是 inline-block、flex

BFC 常见应用

  • 清除浮动(为浮动元素的父元素设置 overflow: hidden,以解决高度坍塌)
  • 避免 margin 重叠(在重叠元素的外层增加父元素 div,并设置 overflow: hidden)
  • 自适应两栏布局(左栏固定宽度并左浮动,右栏不设置宽度且设置 overflow: hidden)

float 布局

圣杯布局和双飞翼布局的目的

  • 三栏布局,中间一栏最先加载和渲染(内容最重要)
  • 两侧内容固定,中间内容随着宽度自适应
  • 一般用于 PC 网页

如何实现圣杯布局和双飞翼布局

  • 使用 float 布局
  • 两侧使用 margin 负值,以便和中间内容横向重叠
  • 防止中间内容被两侧覆盖,圣杯布局用 padding,双飞翼布局用 margin

圣杯布局的实现

  • header、footer 宽度 100% 撑满
  • center、left、right 都设置左浮动,left、right 设为相对定位
  • center 放在最前面,宽度 100% 撑满,left 和 right 分别定宽 200px 和 150px
  • 给外层的 container 设置 padding-left: 200px; padding-right: 150px;,给 left 和 right 空出位置
  • 设置 left 的 margin-left: -100%;,让 left 回到上一行
  • 设置 left 的left: -200px; 把 left 拉回最左侧
  • 设置 right 的 margin-right: -150px; 把 right 拉回上一行最右侧
1
2
3
4
5
6
7
8
9
<header>header</header>
<main>
<div id="container">
<div id="center" class="column">center</div>
<div id="left" class="column">left</div>
<div id="right" class="column">right</div>
</div>
</main>
<footer>footer</footer>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#header, #footer {
background-color: #ccc;
}
#container {
overflow: hidden;
padding-left: 200px;
padding-right: 150px;
}
#container .column {
float: left;
position: relative;
}
#center {
width: 100%;
background-color: darkseagreen;
}
#left {
left: -200px;
width: 200px;
margin-left: -100%;
background-color: cadetblue;
}
#right {
width: 150px;
margin-right: -150px;
background-color: palevioletred;
}

双飞翼布局的实现

  • header、footer 宽度 100% 撑满
  • left、center、right 都设置左浮动
  • center 放在最前面,宽度 100% 撑满,left 和 right 分别定宽 200px 和 150px
  • 设置负边距,left 设置margin-left: -100%;,right 设置margin-left: -150px;
  • 设置 center-wrap 的 margin 值为左右两个侧栏留出空间,margin 值大小为 left 和 right 宽度
1
2
3
4
5
6
7
8
9
10
11
<header>header</header>
<main>
<div id="container">
<div id="center" class="column">
<div class="center-wrap">center</div>
</div>
<div id="left" class="column">left</div>
<div id="right" class="column">right</div>
</div>
</main>
<footer>footer</footer>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
header, footer {
background-color: #ccc;
}
#container {
overflow: hidden;
}
#container .column {
float: left;
}
#center {
width: 100%;
background-color: darkseagreen;
}
.center-wrap {
margin: 0 150px 0 200px;
}
#left {
width: 200px;
margin-left: -100%;
background-color: palevioletred;
}
#right {
width: 150px;
margin-left: -150px;
background-color: burlywood;
}

注意!圣杯布局和双飞翼布局的优缺点:

优点 缺点
圣杯布局 结构简单,无多余 DOM 层 中间部分宽度小于左侧时布局混乱
双飞翼布局 支持各种宽高变化,通用性强 多余 DOM 层,增加渲染树生成的计算量

手写 clearfix

1
2
3
4
5
6
7
8
.clearfix:after {
content: '';
display: block;
clear: both;
}
.clearfix {
*zoom: 1; /* 兼容IE低版本 */
}
1
2
3
4
5
<div class="clearfix">
<div style="float: left">center</div>
<div style="float: left">left</div>
<div style="float: left">right</div>
</div>

flex 布局

  • 需要先指定一个容器为 flex 布局
1
2
3
.container {
display: flex(块元素)| inline-flex(行内元素);
}

注意!当设置 flex 布局之后,子元素的 float、clear、vertical-align 的属性将会失效

  • flex-direction: 主轴的方向(即项目的排列方向)
1
2
3
4
5
6
7
.container {
flex-direction:
row(默认值,主轴为水平方向,起点在左端) |
row-reverse(主轴为水平方向,起点在右端) |
column(主轴为垂直方向,起点在上沿) |
column-reverse(主轴为垂直方向,起点在下沿);
}
  • justify-content:项目在主轴的对齐方式
1
2
3
4
5
6
7
8
.container {
justify-content:
flex-start(默认值,左对齐) |
flex-end(右对齐) |
center(居中对齐) |
space-between(两端对齐,项目之间的间隔相等,即剩余空间等分成间隔) |
space-around(每个项目两侧的间隔相等,项目之间的间隔比项目与边缘的间隔大一倍);
}
  • align-items:项目在交叉轴上的对齐方式
1
2
3
4
5
6
7
8
.container {
align-items:
stretch(默认值,如果项目未设置高度或者设为 auto,将占满整个容器的高度) |
flex-start(交叉轴的起点对齐) |
flex-end(交叉轴的终点对齐) |
center(交叉轴的中点对齐) |
baseline(项目的第一行文字的基线,即文字的底部对齐);
}
  • flex-wrap:容器内项目是否可换行
1
2
3
4
5
6
.container {
flex-wrap:
nowrap(默认值,当主轴尺寸固定且空间不足时,项目尺寸会随之调整而并不会挤到下一行) |
wrap(换行,项目主轴总尺寸超出容器时换行,第一行在上方) |
wrap-reverse(换行,第一行在下方);
}
  • align-content:定义多根轴线的对齐方式,如果项目只有一根轴线,那么该属性将不起作用。即当 flex-wrap 设置为 wrap 的时候,容器可能会出现多条轴线,需要设置多条轴线之间的对齐方式
1
2
3
4
5
6
7
8
9
.container {
align-content:
stretch(默认值,多条轴线平分容器的交叉轴方向上的空间) |
flex-start(轴线全部在交叉轴的起点对齐) |
flex-end(轴线全部在交叉轴的终点对齐) |
center(轴线全部在交叉轴的中点对齐) |
space-between(轴线两端对齐) |
space-around(每个轴线两侧的间隔相等);
}
  • align-self:允许单个项目有与其他项目不一样的对齐方式,与 align-items 属性类似
1
2
3
4
5
6
7
8
9
.item {
align-self:
auto(默认值,表示继承父元素的 align-items 属性,如果没有父元素,则等同于 stretch) |
flex-start(交叉轴的起点对齐) |
flex-end(交叉轴的终点对齐) |
center(交叉轴的中点对齐) |
baseline(项目的第一行文字的基线,即文字的底部对齐) |
stretch(如果项目未设置高度或者设为 auto,将占满整个容器的高度);
}

flex 实现三栏布局

  • container 中的 left、center、right 依次排布即可
  • 给 container 设置弹性布局 display: flex;
  • left 和 right 区域定宽,center 设置 flex: 1; 即可

flex 实现一个三点的骰子

1
2
3
4
5
<div class="container">
<span class="items"></span>
<span class="items"></span>
<span class="items"></span>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
.container {
display: flex;
justify-content: space-between; /* 项目在主轴上两端对齐 */
width: 150px;
height: 150px;
border: 5px solid #ccc;
padding: 20px;
-webkit-border-radius: 20px;
-moz-border-radius: 20px;
border-radius: 20px;
}
.items {
display: inline-block;
width: 40px;
height: 40px;
background-color: #cd1426;
-webkit-border-radius: 50%;
-moz-border-radius: 50%;
border-radius: 50%;
}
.items:nth-child(2) {
align-self: center;
}
.items:nth-child(3) {
align-self: flex-end;
}

232505

flex 实现一个五点的骰子

1
2
3
4
5
6
7
8
9
10
11
12
13
<div class="container">
<div class="items-wrap">
<span class="items"></span>
<span class="items"></span>
</div>
<div class="items-wrap">
<span class="items"></span>
</div>
<div class="items-wrap">
<span class="items"></span>
<span class="items"></span>
</div>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
.container {
display: flex;
flex-direction: column; /* 主轴为垂直方向 */
justify-content: space-between; /* 项目在主轴上两端对齐 */
width: 150px;
height: 150px;
border: 5px solid #ccc;
padding: 20px;
-webkit-border-radius: 20px;
-moz-border-radius: 20px;
border-radius: 20px;
}
.items-wrap {
display: flex;
justify-content: space-between;
}
.items-wrap:nth-child(2) {
justify-content: center;
}
.items {
display: inline-block;
width: 40px;
height: 40px;
background-color: #cd1426;
-webkit-border-radius: 50%;
-moz-border-radius: 50%;
border-radius: 50%;
}

232538