本文由 Rhyme、Captain 发表在 ScalaCool 团队博客。css
若是让我用一句话来总结浮动布局,就是浮动布局是一种排队的艺术。你能够向左排队、向右排队,关键在于你如何去组织他们。若是你去看float
的属性值就会发现它最为重要的无非就是left
和right
,而他们顾名思义就是向左或向右进行浮动。在咱们的网页布局中,凡是涉及到水平布局的,大都会涉及到浮动,例如咱们的导航栏,水平方向的网页布局,他们都或多或少的在水平方向进行向左或向右的排队。所以,若是说网页的布局是摆放一个个盒子的艺术,那么浮动布局就是在水平方向摆放盒子的艺术。html
那么咱们为何要在水平方向进行布局呢?这就犹如多一个游戏规则与少一个游戏规则的区别。咱们能够用咱们小时候玩过的堆积木游戏来作一个形象的比喻。普通的布局就如同一个盒子叠着一个盒子的游戏规则,咱们在同一个水平方向只能放一个盒子,所以只能达到下图中的效果前端
而浮动布局容许你在同一个水平方向能够放置多个盒子,共同组成一个大盒子,也就是说原来的一个盒子再也不是一个简单的盒子,它的内部能够由各类复杂的布局组成, 所以你就能够很轻易得实现下图中的效果,虽然你乍一看下方的布局好像有违游戏规则,可是只要你细心一点进行下图中的划分,就能够发现其实它的最终的规则没有变,依旧是普通布局中的一个盒子叠一个盒子的游戏规则,只不过是它的盒子结构变得更丰富,功能更增强大了了而已。所以明白了这一点,你也就能明白了为何要有浮动布局,由于,它能够实现更多样的布局来实现各类各样的需求。浏览器
好,如今你对这个积木游戏有个必定的了解,也对浮动布局有了一个整体的认识,可是咱们知道一个厉害的游戏玩家,并非由于他比其余人要有天赋,大部分缘由是由于他对游戏规则更为了解。所以要想成为一个厉害的前端玩手,你就须要对前端的游戏规则更为了解。因此,接下来就让咱们正式走近这个积木游戏的大门,尽情得探索和玩耍吧!微信
首先做为积木游戏的入门,咱们须要对最基础的游戏规则作个了解,而这个最基础的游戏规则在网页设计中被称做「文档流」。你能够把积木游戏中的一个个盒子看作是咱们页面中的一个个标签,例如<div></div>
标签就能够看作是一个盒子。可是有一点不一样的是,在咱们的网页中,有两种类型的盒子,一种是被称为块元素的盒子,相似div
,另外一种是被称为内联元素的盒子,例如span
。这两种类型的盒子在文档流中或脱离文档流的时候会表现出不一样的性质,直接影响了咱们的网页布局。因此接下来咱们将介绍这两种类型的盒子在文档流中具备什么特色?至于脱离文档流以后的特色,会在后面「元素的变性」那一节中讲述。布局
首先咱们须要了解什么是文档流?测试
若是说把一个复杂的网页想象成一栋漂亮的楼房,那么这栋楼的地基就是文档流。上面的楼房就是各类定位和浮动的综合体。(定位顾名思义就是负责元素在网页中的位置,具体会在后面的系列中作详细地介绍)spa
咱们所建立的元素默认都在文档流中。例如如下代码中的div
和h2
标签都处于文档流中scala
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>float layout</title>
</head>
<body>
<div>
<h2>我处在文档流中</h2>
</div>
</body>
</html>
复制代码
了解了文档流,接下来咱们将介绍两种类型的盒子(块元素与内联元素)在文档流中具备什么特色设计
div
,p
等标签被称为块元素
100px
,可是它仍是独占一行,且自上而下排列示例代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>霸道的盒子-块元素</title>
<style> .box { width: 100px; height: 100px; } .box1 { background-color: aqua; } .box2 { background-color: aquamarine; } .box3 { background-color: bisque; } </style>
</head>
<body>
<div class="box box1"></div>
<div class="box box2"></div>
<div class="box box3"></div>
</body>
</html>
复制代码
width
属性值默认为auto
,当元素的width
属性值为auto
时,此时修改元素左右内边距不会修改该元素自己的宽度大小,而是会自动修改该元素的宽度,来适应内边距,下图中绿色的块元素就添加了一个左100px
的内边距,你会发现绿色的块元素的宽度大小并无改变,而是自动调整了宽度来适应内边距的改变示例代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>霸道的盒子-块元素</title>
<style> .box1 { height: 100px; background-color: aqua; } .box2 { /*添加左内边距不会影响该元素的宽度大小*/ padding-left: 100px; height: 100px; background-color: aquamarine; } .box2-child { width: 100px; height: 100px; background-color: bisque; } </style>
</head>
<body>
<div class="box1"></div>
<div class="box2">
<div class="box2-child">
</div>
</div>
</body>
</html>
复制代码
示例代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>霸道的盒子-块元素</title>
<style> .box1 { background-color: aqua; } </style>
</head>
<body>
<div class="box1">a</div>
</body>
</html>
复制代码
最后总结一下块元素在文档流中的特色:
100px
,它也会独占一行Tips: 必定要注意是在文档流中,这点对于以后理解浮动布局特别重要。
span
、a
等标签属于内联元素
示例代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>最环保的盒子-内联元素</title>
<style> .box1 { background-color: aqua; } .box2 { background-color: aquamarine; } .box3 { background-color: yellow; } </style>
</head>
<body>
<span class="box1">a</span>
<span class="box2">a</span>
<span class="box3">a</span>
</body>
</html>
复制代码
width
或者height
属性是没有用的,你看它们是有多节约,给它们它们都不要一点多的。注意观察示例中的代码,设置了宽和高是失效的示例代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>最环保的盒子-内联元素</title>
<style> .box1 { /*不能给内联元素设置宽和高*/ width: 100px; height: 100px; background-color: aqua; } </style>
</head>
<body>
<span class="box1">a</span>
</body>
</html>
复制代码
最后咱们一块儿来总结一下内联元素在文档流中的特色
Tips: 这里再强调一遍,以上都是在文档流中的特色,这点对于以后理解浮动布局特别重要。由于,元素浮动以后会脱离文档流,以上这些约束也就不存在了
咱们已经解读了文档流的游戏规则,所以咱们能够很轻易得用三个块元素实现如下的效果
可是在咱们网页设计中常常会有这样的需求,三个div
在同一行的布局效果。咱们能够清晰得分析出如下图片是三个div
布局的水平排列。由于在网页设计的时候咱们大都采用div
来进行网页的布局。
所以咱们就要解决这个问题,如何让3个div
块元素水平排列?
这个时候咱们就要思考既然块状元素在文档流中独占一行,达不到我想要的效果,那若是我让块状元素脱离文档流,是否是就没有这个限制了呢?答案确实如此,以上的效果,就是经过为div
块元素设置浮动属性float:left
来使得这些块元素脱离文档流向左浮动。
补充:脱离文档流能够理解为在原有的地基上新建一层楼进行设计,新建的楼层不彻底遵照地基中的游戏规则,可使得块状元素再也不独占一行,具体的会在以后进行介绍
以上实例的代码以下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>测试浮动布局</title>
<style> .box{ width: 100px; height: 100px; } .box1{ background-color: aqua; } .box2{ background-color: red; } .box3{ background-color: black; } </style>
</head>
<body>
<div class="box box1" style="float: left"></div>
<div class="box box2" style="float: left"></div>
<div class="box box3" style="float: left"></div>
</body>
</html>
复制代码
到这里你已经了解了最基础的游戏规则-文档流,也对浮动布局有了一个初步的认识,可是咱们要想在地基之上搭建出漂亮的房子,还须要进一步的解读浮动的游戏规则
浮动使得元素脱离了文档流,能够理解元素是在文档流(地基)之上进行的活动。明白了这一点,你就能够明白接下来的这句话:浮动的元素对文档流(地基)中的元素是不可见的,由于它脱离了地基,位于地基之上。
浮动是在地基之上进行的活动,那么它不免会带来一个问题,就是若是浮动元素与地基上原有的元素或者别的脱离文档流的元素重叠了,这个时候应该怎么办呢?究竟是谁说了算呢?别急,你想到的,他们也都想到了,而且定好了一系列的游戏规则。而咱们做为玩家,只要知道这些规则的存在,而且学以至用就能够了。咱们这一节所讲的「元素的层级」讲的就是这些规则。
首先在网页中元素的归属能够大体分为两种,一种是在文档流中,另外一种是不在文档流中,也就是脱离文档流。在文档流中的元素属于低层级,脱离文档流的元素属于高层级。那顾名思义,高层级的元素会盖住低层级的元素,那展示在视觉效果上就是盖住的那一部分我只能看见高层级元素,看不见低层级元素。而浮动布局是一种脱离文档流的艺术,所以浮动元素属于高层级。可是这也只解决了一个问题,就是文档流与非文档流的元素层级的问题,那非文档流的元素之间呢,若是它们覆盖了,又是什么样的游戏规则呢?
首先全部非文档流的元素也就是脱离文档流的元素在层级上的地位都是相同的。具体的覆盖规则有两条
z-index
属性值大的覆盖属性值小的z-index
属性值同样的状况下,后面的元素盖住前面的元素接下来是一些示例,能够加深你对以上这些结论的理解
结论1:浮动元素处于高层级,会覆盖处于低层级的文档流元素
示例代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>元素层级</title>
<style> .box1{ float: left; // 注意这里设置了浮动属性 width: 100px; height: 100px; background-color: aqua; } .box2{ width: 200px; height: 200px; background-color: red; } </style>
</head>
<body>
<div class="box1"></div>
<div class="box2"></div>
</body>
</html>
复制代码
结论2:脱离文档流的元素都处于高层级,它们地位是相等的,覆盖规则为:后面的元素会覆盖前面的元素
示例代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>测试浮动布局</title>
<style> .box1 { float: left; // 开启浮动定位,元素处于高层级2 width: 100px; height: 100px; background-color: aqua; } .box2 { position: absolute; // 开启绝对定位,元素处于高层级2 top: 50px; left: 50px; width: 100px; height: 100px; background-color: red; } .box3 { position: relative; // 开启相对定位,元素处于高层级2 left: 100px; top: 100px; width: 100px; height: 100px; background-color: black; } </style>
</head>
<body>
<div class="box1"></div>
<div class="box2"></div>
<div class="box3"></div>
</body>
</html>
复制代码
结论3:脱离文档流的元素能够设定
z-index
属性来提高本身的层级,z-index
属性值越大的越优先显示,默认为0
示例代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>测试浮动布局</title>
<style> .box1 { float: left; // 开启了浮动定位,元素处于层级2 z-index: 1; // 设置z-index 优先级为1 width: 100px; height: 100px; background-color: aqua; } .box2 { position: absolute; // 开启了绝对定位,元素处于层级2 z-index: 2; // 设置z-index 优先级为2 top: 50px; left: 50px; width: 100px; height: 100px; background-color: red; } .box3 { position: relative; // 开启了相对定位,元素处于层级2 z-index: 1; // 设置z-index 优先级为1 left: 100px; top: 100px; width: 100px; height: 100px; background-color: black; } </style>
</head>
<body>
<div class="box1"></div>
<div class="box2"></div>
<div class="box3"></div>
</body>
</html>
复制代码
补充:
z-index
属性的设置只对开启浮动或定位的元素有效- 绝对定位:元素相对于最近的定位祖先元素进行定位
- 相对定位:元素相对于元素原先在文档流中的位置进行定位
最后,咱们来总结一下元素的层级关系:
z-index
相同时,后面的元素覆盖前面的元素z-index
不一样时,优先显示z-index
属性值大的元素浮动会使得元素脱离文档流,尽量地向左上(float:left
)或右上(float:right
)浮动,然而你浮动归浮动,那你何时才会中止浮动呢?这个就是咱们接下来要讨论的话题
浮动元素不会超过它的父元素的边界,下图中红色的浮动元素不会超过
body
父元素的边界,蓝色的浮动元素不会超过黄色的父元素
示例代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>浮动的边界</title>
<style> body { background-color: antiquewhite; } .father { width: 200px; height: 200px; background-color: yellow; margin: 0 auto; } .box1 { float: left; width: 100px; height: 100px; background-color: red; } .box2 { float: right; width: 100px; height: 100px; background-color: aqua; } </style>
</head>
<body>
<div class="box1">
</div>
<div class="father">
<div class="box2">
</div>
</div>
</body>
</html>
复制代码
浮动元素在浮动过程当中遇到其余浮动元素就要中止浮动,这个时候的队伍就像在排队同样
示例代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>测试浮动布局</title>
<style> .box1 { float: left; width: 100px; height: 100px; background-color: aqua; } .box2 { float: left; width: 100px; height: 100px; background-color: red; } .box3 { float: left; width: 100px; height: 100px; background-color: black; } </style>
</head>
<body>
<div class="box1"></div>
<div class="box2"></div>
<div class="box3"></div>
</body>
</html>
复制代码
如下是一行浮动元素的溢出状况,能够看到它们在一行装不下的时候会进行换行浮动
示例代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>不能超队</title>
<style> .box { float: left; width: 100px; height: 100px; background-color: aqua; border: 1px solid black; } </style>
</head>
<body>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</body>
</html>
复制代码
在如下示例中,三块元素都是浮动元素,前两块向左浮动,黑色的向右浮动,你会发现即便第一行有足够的空间,可是第三块黑色的浮动元素就是上不去,缘由仍是那句话不能插队,也就是不能超过兄弟元素
示例代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>不能超队</title>
<style> .box1 { float: left; width: 600px; height: 100px; background-color: aqua; } .box2 { float: left; width: 600px; height: 100px; background-color: yellow; } .box3 { float: right; width: 100px; height: 100px; background-color: black; } </style>
</head>
<body>
<div class="box1"></div>
<div class="box2"></div>
<div class="box3"></div>
</body>
</html>
复制代码
浮动元素不能超过前面的文档流块状元素,咱们查看示例代码,能够发现浮动元素在源代码中的结构位于文档流块状元素以后,解决办法能够将它们在代码结构上交换位置便可
示例代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>被墙了</title>
<style> .box1 { height: 100px; background-color: yellow; } .box2 { float: left; width: 100px; height: 100px; background-color: aqua; } </style>
</head>
<body>
<div class="box1"> // 文档流块状元素
</div>
<div class="box2"> // 浮动元素
</div>
</body>
</html>
复制代码
交换位置以后的效果以下
示例代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>交换位置</title>
<style> .box1 { height: 100px; background-color: yellow; } .box2 { float: left; width: 100px; height: 100px; background-color: aqua; } </style>
</head>
<body>
<div class="box2"> // 浮动元素
</div>
<div class="box1"> // 文档流块状元素
</div>
</body>
</html>
复制代码
最后让咱们来总结一下浮动的边界:
在以前咱们有详细介绍过元素在文档流中的性质,而后,元素在脱离文档流以后性质会发生很大的改变,接下来就让咱们来看看元素都发生了哪些改变,咱们将分别从块元素和内联元素提及
块状元素在文档流中的特色:独占一行,宽度为父元素的100%,高度被内容撑开
块状元素浮动以后的特色:宽度和高度都被内容撑开,可是能够设置宽和高
示例代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>元素变性</title>
<style> .box1 { background-color: aqua; } .box2 { float: left; background-color: yellow; } </style>
</head>
<body>
<div class="box1">a</div>
<div class="box2">a</div>
</body>
</html>
复制代码
内联元素在文档流中的特色:不能设置宽度和高度,宽度和高度都被内容撑开
内联元素浮动以后的特色:能够设置宽度和高度,宽度和高度依旧是被内容撑开
示例代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>元素变性</title>
<style> .span1 { width: 100px; height: 100px; background-color: yellow; } .span2 { float: left; width: 100px; height: 100px; background-color: aqua; } </style>
</head>
<body>
<span class="span1">a</span>
<span class="span2">a</span>
</body>
</html>
复制代码
最后让咱们总结一下元素的变性:
浮动以后,会改变元素的在文档流中的性质,无论是块状元素仍是内联元素,最终都会变成一个块状元素和内联元素的综合体:不独占一行,能够设置宽和高,宽高默认被内容撑开
任何东西都有好与坏,咱们以前了解了那么多浮动元素的特色,也了解了由于浮动带来的种种变化,然而变化归变化,它也会带来一些问题,这些问题就是咱们接下来要解决的所谓的反作用,在这里咱们只讲一个最重要的反作用,解决了它在咱们的平常开发中就不会有太大问题了,至于其余反作用,我的建议,你只要慢慢从实践中体会积累就好了
浮动具备反作用-高度塌陷,通常咱们须要手动的消除浮动带来的反作用
举一个实际的例子,浮动常常用在导航栏的布局中,例如如下的水滴微信平台的导航栏,其中的导航选项很明显都采用了浮动布局。
咱们先使用浏览器的审查功能来看下清除浮动以后的,也就是正常的效果,咱们能够看到此时的header
占据的大小为下图中的阴影部分,将浮动元素(导航选项)包裹在里面,也就是没有由于浮动失调父元素的高度
而在咱们去掉浮动以后,咱们能够发现header
的高度变为了图中的那么一小块阴影,没有将浮动元素(导航选项)包裹在里面,浮动元素的父元素header
失去了原有的高度,这就是咱们如今讨论的高度塌陷问题
高度塌陷会带来不少问题,最明显的就是会影响页面的布局,例如以上例子中,当我发生在导航栏发生高度塌陷以后,就会致使下方的页面元素集体上移,甚至会覆盖导航栏
如下是正常的布局,能够发现下面阴影部分的布局没有影响导航栏
如下是发生高度塌陷的布局,能够发现导航栏被下面的布局影响
咱们管高度塌陷的解决方案称做清除浮动,也就是清除浮动带来的反作用
如下是未进行浮动以前,没有发生高度塌陷
示例代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>高度塌陷以前</title>
<style> .box { border: 5px solid black; } .float-child { width: 100px; height: 100px; background-color: aqua; } .others { height: 100px; background-color: yellow; } </style>
</head>
<body>
<div class="box">
<div class="float-child">
</div>
</div>
<div class="others">
</div>
</body>
</html>
复制代码
这是咱们进行浮动以后的状况,你能够看到在元素浮动以后对咱们的布局产生了反作用,浮动元素的父元素发生了高度塌陷,只留下黑色的边框,下方的布局往上偏移
示例代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>发生高度塌陷</title>
<style> .box { border: 5px solid black; } .float-child { float: left; // 浮动 width: 100px; height: 100px; background-color: aqua; } .others { height: 100px; background-color: yellow; } </style>
</head>
<body>
<div class="box">
<div class="float-child">
</div>
</div>
<div class="others">
</div>
</body>
</html>
复制代码
接下来是咱们成功清除浮动带来的反作用以后的例子,咱们能够发现父元素的高度塌陷没有了,仿佛父元素被里面的浮动元素撑开同样。
这个清除浮动方法的关键在于如下这个结论的应用:
一个元素的高度老是由最后一个非浮动子元素绝定的,至于其中原理,能够本身去实践一下,不少时候关于前端并无那么多为何,大部分时候咱们只要记住怎样作最好就能够了
为何说下面这个清除浮动的方法是最好的呢?首先咱们评判一个解决方法的好坏的标准是:能解决原有的问题,不会带来新的问题。如下这个方法既解决了高度塌陷的问题吗,又经过:after
伪类解决了语义化的问题,很好地符合以上的标准。而且在实际开发中,如下这种方法也是咱们用的最多的一种。
/*清除浮动*/
.float-father:after {
content: "";
display: block;
clear: both;
}
复制代码
示例代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>解决高度塌陷</title>
<style> .float-father { border: 5px solid black; } /*清除浮动*/ .float-father:after { content: ""; display: block; clear: both; } .float-child { float: left; width: 100px; height: 100px; background-color: aqua; } .others { height: 100px; background-color: yellow; } </style>
</head>
<body>
<div class="float-father">
<div class="float-child">
</div>
</div>
<div class="others">
</div>
</body>
</html>
复制代码
总结,在对元素实施浮动操做以后,必定要考虑清除浮动带来的反作用-高度塌陷
行之践,则无敌,接下来就让咱们动手实践一个简单的页面布局
示例代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>最佳实践</title>
<style> ul { /*取出列表的默认样式*/ list-style: none; } li { /*为导航项设置向左浮动*/ float: left; /*将行高设置成与父元素同样高,能够实现垂直居中的效果*/ line-height: 50px; } /*清除浮动*/ .fn-clear:after { content: ""; display: block; clear: both; } li span { /*设置选项元素的内边距*/ padding: 6px 13px; } #header { /*设置header的高度为50px*/ height: 50px; /*设置header的背景颜色*/ background-color: aqua; } #body-left { /*设置body-left向左浮动*/ float: left; /*设置宽度为父元素宽度的20%*/ width: 20%; /*设置高度*/ height: 500px; /*设置背景颜色*/ background-color: aquamarine; } #body-center { /*设置body-center向左浮动*/ float: left; /*设置宽度为父元素宽度的20%*/ width: 60%; /*设置高度*/ height: 500px; /*设置背景颜色*/ background-color: aliceblue; } #body-right { /*设置body-right向左浮动*/ float: left; /*设置宽度为父元素宽度的20%*/ width: 20%; /*设置高度*/ height: 500px; /*设置背景颜色*/ background-color: aquamarine; } #footer { /*设置footer的高度*/ height: 80px; /*设置footer的背景颜色*/ background-color: antiquewhite; } </style>
</head>
<body>
<div id="header" class="fn-clear">
<ul>
<li><span>导航</span></li>
<li><span>导航</span></li>
<li><span>导航</span></li>
<li><span>导航</span></li>
<li><span>导航</span></li>
<li><span>导航</span></li>
</ul>
</div>
<div id="body" class="fn-clear">
<div id="body-left"></div>
<div id="body-center"></div>
<div id="body-right"></div>
</div>
<div id="footer">
</div>
</body>
</html>
复制代码