【前端基础】1 - 6 浮动与弹性布局
§1-6 浮动与弹性布局
1-6.1 标准文档流
标准文档流(normal flow)指的是元素在页面中的默认排布规则。块级元素独占一行,行内元素行内显示多个,并列的内联元素间以空格分隔。
然而绝大多数网页的布局千变万化,一个网页中的不同元素可能具有多种不同的布局,标准文档流此时无法满足需求,出现了多种不同的布局规则,以适应不同的需要。
1-6.2 浮动
浮动是通过属性 float
实现的。是早期实现块级元素同行并列显示的一种实现方式,可用于实现图文混排。
float
属性指定一个元素沿其容器的左侧或右侧放置,允许文本和内联元素环绕它。一旦设置了浮动属性,该元素就会从标准文档流中剔除。
float
支持以下关键字值:
关键字 | 说明 |
---|---|
left |
元素浮动在容器左侧 |
right |
元素浮动在容器右侧 |
none |
默认值,元素不浮动 |
inline-start |
元素必须浮动在所在块容器的开始一侧(受文字方向影响) |
inline-end |
元素必须浮动在所在块容器的结束一侧(受文字方向影响) |
浮动的元素将会具备行内块的特点,父级宽度不够时,浮动子元素会换行显示,且浮动元素会发生元素脱标。
1-6.2.1 元素两侧浮动
我们使用 <div>
包裹三个具有浮动属性的块级元素 <div>
,并让他们分布在一段文字的两边。
<section class="block">
<div class="left">左一</div>
<div class="left">左二</div>
<div class="right">右</div>
<p>
愿中国青年都摆脱冷气,只是向上走,不必听自暴自弃者流的话。能做事的做事,能发声的发声。有一分热,发一分光,就令萤火一般,也可以在黑暗里发一点光,不必等候炬火。此后如竟没有炬火:我便是唯一的光。倘若有了炬火,出了太阳,我们自然心悦诚服的消失,不但毫无不平,而且还要随喜赞美这炬火或太阳:因为他照了人类,连我都在内。
</p>
</section>
.block {
border: 1px solid black;
border-radius: 5px;
margin: 10px;
padding: 10px;
width: 40em;
}
.left {
float: left;
background-color: pink;
margin: 5px;
width: 50px;
height: 130px;
}
.right {
float: right;
background-color: cornflowerblue;
margin: 5px;
width: 50px;
height: 130px;
}
效果:
浮动的元素沿其所在块级元素浮动排列。但是,由于浮动元素高度明显高于父级元素,发生了越界的现象。浮动元素至少要与其最高的嵌套浮动子元素一样高。这里将父级元素同样修改为浮动元素,使其高度足以包含全部子元素。
.block {
float: left;
border: 1px solid black;
border-radius: 5px;
margin: 10px;
padding: 10px;
width: 40em;
}
修改后:
1-6.2.2 浮动元素脱标
浮动的元素会从标准文档流中剔除(元素脱标),脱标的元素可能会影响其他元素排布。
下面两个示例展示了浮动元素对其他元素的影响。
示例一:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>脱标现象</title>
<link rel="stylesheet" href="css/outOfFlow.css">
</head>
<body>
<div class="float">浮动元素</div>
<div class="normal"></div>
</body>
</html>
.float {
float: left;
width: 100px;
height: 100px;
background-color: red;
}
.normal {
width: 200px;
height: 200px;
background-color: orange;
}
效果:
浮动元素脱标后,不受标准文档流影响,浮动在了其他处于标准流中的元素之上。因此十分建议使用浮动元素时,应当使用一个块级元素(容器)包装。
示例二:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>清除浮动</title>
<link rel="stylesheet" href="css/clear.css">
</head>
<body>
<div class="top">
<div class="left"></div>
<div class="right"></div>
</div>
<div class="bottom"></div>
</body>
</html>
.top {
margin: 10px auto;
width: 1200px;
/*height: 300px;*/
background-color: pink;
}
.left {
float: left;
width: 200px;
height: 300px;
background-color: violet;
}
.right {
float: right;
width: 900px;
height: 300px;
background-color: #c0341d;
}
.bottom {
height: 100px;
background-color: #FFCC70;
}
效果:
父级高度不足以撑开页面,或父级本身为浮动元素,这都可能会以不同的方式影响页面中其他元素的布局。
1-6.2.3 清除浮动
为了防止浮动元素影响页面中其他元素的布局,我们需要清除浮动。清除浮动的方法有三种。
下面的修改都基于示例二修改。
方法一:在浮动元素的父级元素中添加一个块级元素,并赋予 CSS 属性 clear: both
。
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>清除浮动</title>
<link rel="stylesheet" href="css/clear.css">
</head>
<body>
<div class="top">
<div class="left"></div>
<div class="right"></div>
<div class="clearfix"></div>
</div>
<div class="bottom"></div>
</body>
</html>
.top {
margin: 10px auto;
width: 1200px;
/*height: 300px;*/
background-color: pink;
}
.left {
float: left;
width: 200px;
height: 300px;
background-color: violet;
}
.right {
float: right;
width: 900px;
height: 300px;
background-color: #c0341d;
}
.clearfix {
/* 在浮动元素的父元素中添加一个空的块元素(建议使用 clearfix 类名标识) */
/* 使用 clear: both 清除所有方向上(左右)的影响 */
clear: both;
}
.bottom {
height: 100px;
background-color: #FFCC70;
}
方法二:在不更改 HTML 文档的前提,使用伪元素 ::after
清除影响。
/* ::after 表明在该元素的最后添加一个内联子元素 */
.top::after {
content: ""; /* 必需字段, */
display: block; /* 修改为块级 */
clear: both;
}
方法三(推荐):同时使用 ::before
和 ::after
清除影响。
/* ::before 表明在该元素的最前面添加一个内联子元素 */
/* 使用 ::before 防止塌陷现象 */
.top::before, .top::after {
content: "";
display: table;
}
.top::after {
clear: both;
}
方法四:父级元素赋予 CSS 属性 overflow: hidden
效果:
1-6.3 弹性布局
现如今,越来越多的王爷使用的不再是浮动,而是使用弹性布局,这也是浏览器所提倡使用的一种布局。弹性布局适合结构化布局,提供了强大的空间分布和对齐能力。
弹性布局,即 flex
布局,不会产生浮动布局中的脱标现象,网页布局更为简单灵活。
弹性布局将元素是做一个个弹性盒子处理:(图源 MDN)
设置方式:给父元素设置 CSS 属性 display: flex
,子元素可以自动挤压或拉伸。
组成部分:弹性容器、弹性盒子(弹性项目)、主轴(默认水平)、交叉轴(始终正交于主轴)。
弹性容器中的元素称为弹性盒子。默认情况下,弹性容器的主轴为水平方向,弹性盒子按照主轴方向排列,若弹性盒子过多,这些弹性盒子的尺寸就会被压缩。
1-6.3.1 按主轴或交叉轴对齐
弹性项目按主轴对齐可使用属性 justify-content
控制。该属性应当施加于弹性容器上。
属性具有以下值(节选):
值 | 说明 |
---|---|
flex-start |
默认值,元素紧密地排列在弹性容器的主轴起始侧 |
flex-end |
元素紧密地排列在弹性容器的结束侧 |
center |
元素沿主轴居中排列(伸缩元素项每行中点排列) |
space-between |
在每行均匀分配元素,元素间隔均分在每两个元素之间 |
space-around |
在每行均匀分配元素,每行首/末元素到行首/行尾的距离是相邻元素间距的一半 |
space-evenly |
在每行均匀分配元素,元素间距和元素与容器间距相等 |
浏览器在渲染时,会将父级元素(弹性容器)剩余的尺寸分配成间距。
弹性容器内所有弹性项目的交叉轴对齐方式由属性 align-items
控制,该属性应当施加于弹性容器上。
而单独控制弹性容器中某个弹性项目的交叉轴对齐方式由属性 align-self
控制,施加于弹性项目上。
两个属性都接受以下值(节选):
值 | 说明 |
---|---|
stretch |
弹性盒子沿交叉轴被拉伸至铺满容器(弹性项目未设置交叉轴向尺寸则默认拉伸) |
center |
沿交叉轴居中排列 |
flex-start |
从起点开始排列 |
flex-end |
从终点开始排列 |
默认情况下,元素主轴方向的尺寸靠内容撑开,交叉轴默认拉伸。
1-6.3.2 修改主轴方向
弹性项目在弹性容器中按照主轴方向排列,默认情况下主轴方向水平。在一些情况下,我们希望主轴方向是垂直的,可以使用属性 flex-direction
修改主轴方向:
值 | 说明 |
---|---|
row |
默认,水平方向(从左到右) |
column |
垂直方向(从上到下) |
row-reverse |
水平逆向(从右到左) |
column-reverse |
垂直逆向(从下到上) |
主轴方向始终正交于交叉轴。因此,一旦修改了主轴方向,交叉轴的方向也会随之改变。
1-6.3.3 弹性伸缩比
使用弹性伸缩比可以很好地控制弹性项目在弹性容器中的尺寸占比,由属性 flex
控制,施加在弹性元素上。
flex
属性接受的是整数值,表示元素在主轴方向上占容器剩余尺寸的比例。
主轴方向不同,调整的就是在不同方向上元素所占容器剩余尺寸的比例。
示例:主轴水平,控制五个弹性项目等宽分布。
<div class="container">
<div class="item">item</div>
<div class="item">item</div>
<div class="item">item</div>
<div class="item">item</div>
</div>
.container {
display: flex;
border: 1px solid black;
width: inherit;
}
.item {
flex: 1;
height: 100px;
margin-right: 1px;
background-color: pink;
text-align: center;
line-height: 100px;
font-size: 1.25em;
color: #c0341d;
}
.container .item:last-child {
margin: 0;
}
这样,容器中五个元素在主轴方向上的尺寸被均分为五份,每一份都占 1/5。
类似地,调整元素的 flex
取值可让其沿主轴方向具有不同比例的尺寸。
1-6.3.4 弹性换行与行对齐
默认情况下,弹性容器中的元素即便过多,也会被压缩显示,不会换行。这个行为由属性 flex-wrap
控制,默认为 nowrap
,即不换行,元素过多时压缩处理。可设为 wrap
使得元素在空间不足时换行显示。
弹性容器中的元素一旦换行显示,行对齐方式就具有实际意义。行对齐方式由 align-content
属性控制,接受与 justify-content
一样的值,效果相同,此处不再赘述。
<div class="container">
<div class="item">item</div>
<div class="item">item</div>
<div class="item">item</div>
<div class="item">item</div>
<div class="item">item</div>
<div class="item">item</div>
<div class="item">item</div>
<div class="item">item</div>
<div class="item">item</div>
<div class="item">item</div>
</div>
.container {
display: flex;
flex-wrap: wrap;
justify-content: space-evenly;
align-content: space-evenly;
overflow: hidden;
border: 1px solid black;
width: inherit;
height: 320px;
}
.item {
width: 150px;
height: 150px;
margin-right: 2px;
background-color: pink;
text-align: center;
line-height: 100px;
font-size: 1.25em;
color: #c0341d;
}
.container .item:last-child {
margin: 0;
}