浮动设计初衷
类似报纸的布局栏,浮动是为了让图片嵌在文本流中,文本不会覆盖图片,但早期布局只有浮动,因此将浮动用于布局,后来才有了display:inline-block display: table flexbox和网格布局等
基本代码
<html>
<head>
<style>
:root {
box-sizing: border-box;}
*,
::before,
:;after {
box-sizing: inherit;}
body {
background-color: #eee;
font-family: Helvetica, Arial, sans-serif;}
body * + * {
margin-top: 1.5em;}
header {
padding: 1em 1.5em;
color: #fff;
background-color: #0072b0;
border-radius: .5em;
margin-bottom: 1.5em;}
.main {
padding: 0 1.5em;
background-color: #fff;
border-radius: .5em;}
</style>
</head>
<body>
<div class="container">
<header>
<h1>TJH Special 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>Strength train is important</p>
</div>
</div>
<div class="media">
<img class="media-image" src="shoes.png">
<div class="media-body">
<h4>Cadence</h4>
<p>cadence</p>
</div>
</div>
<div class="media">
<img class="media-image" src="shoes.png">
<div class="media-body">
<h4>Transform it</h4>
<p>I like running</p>
</div>
</div>
<div class="media">
<img class="media-image" src="runner.png">
<div class="media-body">
<h4>concentrate mind</h4>
<p>focus your mind</p>
</div>
</div>
</div>
</main>
</div>
</body>
</html>
双容器模式
将内容放入两个嵌套的容器总,通过设置内容器的外边距,让内容器左右居中
body是外层容器 container是内层容器,对内层容器按双容器模式设置样式。发现内容器宽度达到最大宽度,然后左右居中
.container {
max-width: 1080px;
margin: 0 auto;}
是否有必要学习浮动
有 贴近老代码,且让图片被文本环绕,浮动是少数能实现的方案
容器折叠和清除浮动
容器折叠
将四个media浮动到容器左侧。发现四个media好像跑到了容器外边,是因为浮动元素的高度不会加给父元素上,不过这恰恰符合浮动的初衷:浮动是为了让图片被文本环绕,所以图片高度不会加给父元素
.media {
float: left;
width: 50%;
padding: 1.5em;
background-color: #eee;
border-radius: .5em;}
这并不是我们想要的,我们想要四个媒体元素都被包含在容器元素中
方法1
使用clear属性。需要将一个元素放到容器元素内的末尾元素,这会让容器元素扩展到该元素的下方
通俗理解,一个浮动图片会被文字环绕,如果清除浮动,则该图片自成一行,不再被文字环绕
理解清除浮动
可以用伪元素取代额外增加的div元素,清除浮动可以叫clearfix
伪元素是一种特殊的选择器,以双冒号::开头,最常用的伪元素是::before ::after
.clearfix::after {
display: block;
content: " ";
clear: both;}
浮动元素外边距在容器内不会被折叠,而容器内非浮动元素外边距会被折叠(runnering tips紧贴最上边)
通过对容器内第一个和最后一个元素设置属性避免外边距折叠
.clearfix::before,
.clearfix::after {
display: table;
content: " ";}
clear清除浮动只对块元素有效,所以可以用display: table但不能display:table-cell
浮动陷阱
上一个页面的浮动比较奇怪,是因为跑步图片比较高,导致第一个media盒子高一些。为什么第三个盒子不在第一个盒子下面,因为有浮动。如果清除第三个元素之前的元素浮动,则第三个元素可以从新行开始,而不是跑到第二个元素下方,因为浏览器会处理浮动元素位置尽量靠上
.media:nth-child(odd) {
clear: left;
}
nth-child伪类选择器可以选取第奇数个元素。如果每行三个元素,则nth-child(3n+1)
这种布局方式局限性是需要知道每行有几个元素,然后根据每行元素数量设置清除浮动
因为有猫头鹰选择器,还需要考虑第一个媒体元素外边距。只给media元素设置下和右边距
.media {
float: left;
margin: 0 1.5em 1.5em 0;
width: calc(50% - 1.5em);
padding: 1.5em;
background-color: #eee;
border-radius: .5em;}
媒体对象和bfc
现在考虑media对象,希望想图片靠左文字靠右,这种布局可以叫媒体布局。媒体布局有不少实现方案,如flex和表格布局等,此处使用浮动布局
先考虑将图片浮动到左边,并清除猫头鹰选择器的上外边距,但文字会包围图片,不符合我们预期
.media-image {
float: left;
}
.media-body {
margin-top: 0;
}
.media-body h4 {
margin-top: 0;
}
bfc
bfc block formatting context 块级格式化上下文 可以将该元素内部上下文和外部的隔离开 bfc有如下特点:1 bfc内部外边距不会和bfc外部外边距折叠 2 包含内部所有浮动元素 3 bfc内部浮动元素不会和bfc外部浮动元素重叠 4 如果清除bfc的外边距,即加clear属性,则不会清除bfc外边元素的外边距
如果清除图片下方的浮动,问题即可解决
如下方式都可以创造bfc
1 float为left或right即可,只要不为none
2 overflow: hidden auto scroll即可,不为visible即可
3 display: inline-block, table-cell, table-caption, flex, inline-flex, grid, inline-grid,有这些属性的元素称块级元素
4 position: absolute 或 fixed
使用bfc进行布局
此处通过overflow进行bfc布局。给图片右边加外边距,将media-body设为bfc
.media-image {
float: left;
margin-right: 1.5em;
}
.media-body {
overflow: auto;
margin-top: 0;
}
网格系统
目前为止,较难复用之前的样式表,有什么好的方式
方案1:网格系统。大部分css框架包含自己的网格系统,css框架比如bootstrap,foundation,pure等
构建网格系统
给原代码的4个media外包裹容器元素,每两个media一行,每个column包裹一个列元素
.row::after {
content: "";
display: block;
clear: both;
}
[class*="column-"] {
float: left;
}
.column-1 {width: 8.33333%;}
.column-2 {width: 16.66667%;}
.column-3 {width: 25%;}
.column-4 {width: 33.33333%;}
.column-5 {width: 41.66667%;}
.column-6 {width: 50%;}
.column-7 {width: 58.33333%;}
.column-8 {width: 66.66667%;}
.column-9 {width: 75%;}
.column-10 {width: 83.33333%;}
.column-11 {width: 91.66667%;}
.column-12 {width: 100%;}
[]是一个属性选择器,*=可以匹配任意包含指定字符串的值
由于media和表格布局重复,处理media的布局。删除媒体元素的浮动和清除浮动,查看效果
.media {
/*float: left;*/
/*margin: 0 1.5em 1.5em 0;*/
/*width: calc(50% - 1.5em);*/
padding: 1.5em;
background-color: #eee;
border-radius: .5em;}
/*.media:nth-child(odd) {*/
/* clear: left;*/
/*}*/
底部添加内边距
.main {
/*padding: 0 1.5em;*/
padding: 0 1.5em 1.5em;
background-color: #fff;
border-radius: .5em;}