布局介绍
1.浮动布局
本例中,body就是外层容器,因为它默认就是100%的网页宽度,所以不用给它添加新的样式。在body内部,整个网页的内容放在了container容器里面,也就是内层容器。对于内层容器,需要设置一个max-width,并将外边距设置为auto,使内容居中,如下代码
.container {
max- 1080px;
margin: 0 auto;
}
这里使用了max-width,而不是width。因此如果视口宽度小于1080px的话,内层容器就能缩小到1080px以下。换句话说,在小视口上,内层容器会填满屏幕,在大视口下,它会扩展到1080px。这种方式能有效避免在小屏幕上出现水平滚动条。
浮动元素不同于普通文档流的元素,它们的高度不会加到父元素上。这可能看起来很奇怪,但是恰好体现了浮动的设计初衷。
浮动是为了实现文字围绕浮动元素排列的效果。在段落里浮动图片时,段落的高度并不会增长到能够容纳该图片。也就是说,如果图片比段落文字高,下一段会直接从上一段的文字下面开始,两段文字都会围绕浮动的图片排列。
1.1 理解容器 折叠
例子中,除了页面标题,其他元素都设置了浮动,所以容器的高度只包含页面标题的高度,浮动的媒体元素则扩展到主元素的白色背景下面。这不是我们想要的,主元素应该向下扩展到灰色的盒子。
解决的办法是使用跟浮动配套的clear属性。将一个元素放在主容器的末尾,并对它使用clear,这会让容器扩展到浮动元素下面。
<div style="clear:both"></div>
<!-- 在main容器的末尾增加一个带有clear属性的空div -->
clear:both声明让该元素移动到浮动元素的下面,而不是侧面。clear的值还可以设置为left或者right,这样只会相应地清除向左或向右浮动的元素。因为空div本身没有浮动,所以容器就会扩展,直到包含它,因此也会包含该div上面的浮动元素。
但是这种方式不雅。要在HTML里面添加不必要的标记,用纯css方案来实现相同的而效果
1.2 理解清除浮动
不用额外的div标签,我们还可以用伪元素来实现。使用::after伪元素选择器,就可以快速地在DOM中在容器尾部添加一个元素,而不用在HTML里添加标记。
如下所示:
.clearfix::after {
/* 选中容器尾部的伪元素 */
display: block;
/* 将伪元素的display设置为非inline,并给定一个content值, */
/* 以便让为元素出现在文档中, */
content: " ";
clear: both;
/* 让伪元素清除容器的所有浮动 */
}
请注意,要给包含浮动的元素清除浮动,而不是给别的元素,比如浮动元素本身,或包含浮动元素的后面的兄弟元素。
这个清除浮动还有个问题没解决:浮动元素的外边距不会折叠到清除浮动容器的外部,非浮动元素的外边距则会正常折叠。比如在前面的页面里,标题“Running tips”紧挨着main元素的顶部,它的外边距在容器外面折叠了。
一些开发人员跟喜欢使用清除浮动的一个修改版,它能包含所有的外边距。这样更符合预期。使用这个修改版,能防止标题外部的外边距在main元素的外部折叠。
.clearfix::before,
.clearfix::after {
/* 防止伪元素的外边距折叠 */
display: table;
content: " ";
}
.clearfix::after {
/* 只有after伪元素需要清除浮动 */
clear: both;
}
这个版本使用display:table而不是display:block。给::before和::after伪元素都加上这一属性,所有子元素的外边距都会包含在容器的顶部和底部之间。
清除浮动和display:table
在清除浮动时使用display:table能够包含外边距,是因为利用了CSS的一些特性。创建一个display:table元素,也就是在元素内隐式创建了一个表格行和一个单元格。而且clear属性只能对块级元素生效。表格是块级元素。
1.3 出乎意料的"浮动陷阱"
页面里面的白色容器已经能够包含浮动的媒体元素了,但是出现了另外一个问题:4个盒子没有如预期那样均匀地占据2行。虽然前2个盒子符合预期,但是第3个盒子出现在了右边,也就是第2个盒子的下面,导致第1个盒子下面出现了一片空白。
众多的元素浮动到同一侧,如果每个浮动盒子的高度不一样,最后的布局可能 千变万化。同理,改变浏览器的宽度也会造成相同的结果,因为它会导致换行,从而改变元素高度。而我们真正想要的是每行有2个浮动盒子。
要想修复这个问题很简单:清除第三个浮动元素上面的浮动。更 通用的做法是,清除每行的第一个元素上面的浮动。由于每行有2个盒子,所以只需要清除每行的第奇数个元素上面那行的浮动即可。你可以用:nth-child()伪类选择器来选中这些目标元素。
.media:nth-child(odd) {
/* 每个新行清除了上面一行的浮动 */
clear: left;
}
接下来给媒体元素加上外边距来拉开距离。
1.4 BFC
例子中,每个media块里面,发现它的盒子扩展到了最左边,因为它会包围浮动的 图片。现在文字围绕着图片,但是只要清除了图片底部的浮动,正文就会立刻移动到媒体盒子的左边。而我们真正想要的是将正文的左侧靠着浮动图片的右侧排列。
为了实现这种布局,需要为正文建立一个块级格式化上下文(BFC)。BFC是网页的一块区域,元素基于这块区域布局。虽然BFC本身是环绕文档流的一部分,但它将内部的内容与外部的上下文 隔离开。这种隔离为创建BFC的元素做出了以下3件事情:
- 包含了内部所有元素的上下外边距
- 包含了内部所有的浮动元素
- 不会跟BFC外面的浮动元素重叠。
简而言之,BFC里的内容不会跟外部的元素重叠或者相互影响。如果给元素增加clear属性,它只会清除自身所在BFC内的浮动。如果强制给一个元素生成一个新的BFC,他不会跟其他BFC重叠。
给元素添加以下的任意属性值都会创建BFC.
float:left或者right,不为none即可。
overflow:hidden、auto或scroll,不为visible即可。
display:inline-block、table-cell、table-caption、flex、inline-flex、grid或inline-grid。拥有这些属性的元素称为块级容器。
position:absolute或position:fixed。
网页的根元素也创建了一个顶级的BFC
例子中只要给媒体正文创建BFC,网页的布局就会符合预期。通常是给元素设置overflow值-hidden或者auto。
使用overflow:auto通常是创建BFC最简单的一种方式。也可以前面提到的其他方式:但是有些问题需要注意,比如,使用浮动或inline-block方式创建BFC的元素宽度变成100%,因此需要限制一下元素的宽度,防止因为过宽而换行,导致内容移动到浮动图片的下面,相反,使用table-cell方式显示的元素,其宽度只会刚好容纳其中的内容,因此需要设置一个较大的宽度,强制使其填满剩余空间。
说明:某些情况下,BFC中的内容可能还会与别的BFC的内容重叠。比如,内容溢出了容器或者因为负外边距导致内容被拉到容器下面。
如下代码,为例子中的代码
html代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link href="./4-1.css" rel="stylesheet" type="text/css">
</head>
<body>
<div class="container">
<header>
<h1>Franklin Runnint Club</h1>
</header>
<main class="main clearfix">
<h2>Running tips</h2>
<div>
<div class="media">
<img class="media-image" src="./runner.png">
<div class="media-body">
<h4>Strength</h4>
<p>Strenth training is an important part of injury prevention.Focus on your core--especially your abs and glutes.</p>
</div>
</div>
<div class="media">
<img class="media-image" src="./shoes.png">
<div class="media-body">
<h4>Strength</h4>
<p>Strenth training is an important part of injury prevention.Focus on your core--especially your abs and
glutes.</p>
</div>
</div>
<div class="media">
<img class="media-image" src="./shoes.png">
<div class="media-body">
<h4>Strength</h4>
<p>Strenth training is an important part of injury prevention.Focus on your core--especially your abs and
glutes.</p>
</div>
</div>
<div class="media">
<img src="./runner.png">
<div>
Strength
<p>Strenth training is an important part of injury prevention.Focus on your core--especially your abs and
glutes.</p>
</div>
</div>
<!-- <div style="clear:both"></div>
在main容器的末尾增加一个带有clear属性的空div -->
</div>
</main>
</div>
</body>
</html>
css代码如下:
:root {
box-sizing: border-box;
}
*,
::before,
::after {
box-sizing: inherit;
}
body {
background-color: #eee;
font-family: Arial, Helvetica, sans-serif;
}
body *+* {
margin-top: 1.5em;
}
header {
padding: 1em 1.5em;
color: #fff;
background-color: #0072b0;
border-radius: 0.5em;
margin-bottom: 1.5em;
border: 1px solid;
}
.container {
max- 1080px;
margin: 0 auto;
}
.main {
background-color: #fff;
padding: 0 1.5em;
}
.media {
background-color: peru;
float: left;
calc(50% - 1.5em);
padding: 1.5em;
border-radius: 0.5em;
margin: 0 1.5em 1.5em 0;
}
.media-image {
float: left;
padding-right: 1.5em;
}
.media-body {
margin-top: 0;
/* 创建一个新的BFC,这样正文就不会跟浮动的图片重叠 */
overflow: hidden;
}
.media-body h4{
margin-top: 0;
}
.clearfix::before,
.clearfix::after {
/* 防止伪元素的外边距折叠 */
display: table;
content: " ";
}
.clearfix::after {
/* 只有after伪元素需要清除浮动 */
clear: both;
}
.media:nth-child(odd) {
/* 每个新行清除了上面一行的浮动 */
clear: left;
}