大家好我们一起重温CSS与HTML,这样将成为一个系列,会一直写下去。
为什么有必要巩固和学习CSS与HTML的知识呢?(将是几段废话,以后就不会有了。。。) 1.引言因为我在开发中,要么常常遇到一些样式的bug,解一个样式bug就要好长时间,网搜各种方法,试来试去,降低了工作的效率;要么就是当一些UI框架不满足业务需求的时候,自己写布局和样式很是费劲。归结原因就是基础知识掌握的不好,不熟练,应用的不灵活。在一次年终技术面谈中,我的领导也对我说过:虽然现在前端新技术层出不穷,但是基础很重要,我们做前端的不能单单JavaScript玩的很溜,别的不怎会,要把CSS也学好用好。所以对我来说很有必要学习和总结一CSS和HTML的相关内容,以期能够灵活运用。如果连基本的知识点都不知道,灵活运用就谈不上了 。所以我打算重新来学习CSS以及HTML的知识,你愿意和我一起搞起这个多人运动不? 我打算每一篇总结都和实际开发以及面试相关,由一个问题引出相关知识,不求频繁更新(毕竟我没那么多读者,也不恰饭 ),只求每篇都是精品(精品的标准是我自己定的 ),给自己写的,也给需要帮助或者懂得欣赏的人写的。 2.使用浮动实现三栏布局今天就先从如何实现三栏布局开始, 实现三栏布局是一个开发中常遇见的场景,也是面试中面试官喜欢问的问题,所以学习一下真是一箭双雕。实现三栏布局的方案比较多,比如使用浮动、定位、flex等等。我们将会逐一学习,今天要来学习使用浮动实现三栏布局。例如我们对三栏布局的要求是:高度任意,左右宽度固定300px,中间区域自适应。首先来看一下HTML布局:
注意在写页面结构的时候,先写右侧部分再写中间部分,因为我们是让右侧部分右浮动了,右侧部分会脱离文档流向右偏移,后面的中间部分就会补充到其位置。我们再来看一下样式: 第一块的样式 .layout_float::after是为了清除浮动,禁止其他的元素围绕浮动的元素显示,我们在下文中会详细介绍。第二块样式.layout_float .float 给左中右三块都设置了一个最小的高度。第三块样式.left为左侧设置了左浮动、宽度、背景色。第四块样式.right为右侧设置了右浮动、 宽度、背景色。第五块样式.center为中间区块设置了背景颜色。 代码运行效果如图所示:缩小浏览器视口
继续缩小浏览器视口
以上就是使用浮动实现三栏布局的一种方案。下面我详细看一下有关浮动的知识:
3.关于浮动 浮动的本质是为了实现文字环绕效果的,让文字绕着图片显示。浮动设计的初衷并不是为了布局。所以在布局的时候,浮动用的不好就会导致问题,所以还是少用为好,但是也有必要了解一下。 3.1 浮动属性 在CSS中,浮动是通过float属性实现。float属性可以取值:left, right, none。left是把目标元素移动到左边,随后的内容围绕在该元素的右侧。right是把元素移动到右边。默认是none,也就是不浮动。 3.2 float的规则与特性 对元素使用浮动要注意:不管元素是什么类型(无论是行内元素还是块级元素),浮动后得到的都是块级框。浮动块级元素时要设定元素的width属性。(其实,根据CSS的规则,除了图像之外,所有浮动元素都要设置宽度。)我们接着来看一下浮动的规则:
3.2.1 规则(了解即可)
因为在规则的介绍里涉及到容纳块的概念,我们就先看一下容纳块的含义。
容纳块(containing block)(也有的书把它叫包含块): 每个元素的框体都是都是相对容纳块放置的,容纳块是元素框体的“布局上下文”。容纳块由离元素最近的那个生成列表项目或块级框的祖先元素的边界构成。(摘自《CSS权威指南》)概念有点晦涩,我们看例子:
在上图所示的例子中,p元素的容纳块是div元素的块级框,因为这是祖辈元素的框体中离p元素最近的,而且div是块级框。与此类似,div元素的容纳块是body元素的框体。
在理解了容纳块概念的基础上,我们来具体看看浮动的规则:
温馨提示:为了理解这些规则,我们可以画相关的图示。不理解也不耽误学习后续的内容。
第一,浮动元素的左外边界或者右外边界不能超过容纳块的左内边界或者右内边界。
第二,前面的元素向左浮动,后面浮动元素的左外边界一定在前一个元素右外边界的右侧,除非后一个元素的顶边在前一个元素的底边以下,这种情况下,后一个元素将会直达父元素的左内边界。
与之相仿,如果文档中处于前面的元素向右浮动,后面的浮动元素的右外边界必定在前一个元素左外边界的左侧,除非后一个元素的顶边在前一元素的底边以下。
第三,左浮动元素的右外边界不能在右浮动元素左外边界的右侧。与之相仿,右浮动元素的左外边界不能在左浮动元素右外边界的左侧。
第四,浮动元素的顶边不能比父元素的内顶边高。如果浮动元素位于两个折叠的外边距之间,在两个元素之间放置它的位置时,将认为它有个块级父元素。
对后半句稍作说明:例如,有三个段落,中间那个段落是浮动的。此时中间那个段落好像有一个块级父元素。这样能够避免浮动的块级元素一直向上移动,超出三个段落共有的父元素。
第五,浮动元素的顶边不能比前方任何一个浮动元素或块级元素的顶边高。
第六,浮动元素的顶边不能高于出现在浮动元素之前的元素生成的框体所在的行框的顶边。
第七,左浮动元素的左边如果还有一个向左浮动的元素,那么它的右外边界不能在容纳块右外边界的右侧。右浮动元素类似。
第八,浮动元素必须放在尽可能高的位置上。
第九,左浮动元素必须尽量向左移动,右浮动元素必须尽量向右移动。位置越高,向左或向右移动的距离越远。
以上这些规则规定了浮动元素和容纳框之间的位置关系以及浮动元素彼此之间的位置关系。如第二条规则是为了避免相互遮盖的情况;第三条规则避免元素的重叠;第四条规则的前半部分避免浮动元素一直向文档顶端浮动,后半部分进一步规定某些情况的对齐方式;第五条规则也是避免浮动的元素一直向上移动,超出父元素的顶边;第六条规则类似,限制浮动元素上移的幅度。关于这些规则详细的解释,可以参考《CSS权威指南》。
3.2.2 特性
在《CSS世界》这本书中,张鑫旭老师总结了float如下四个特性:
第一,包裹性;
第二,自适应性;
第三,破坏文档流;
第四,没有任何的margin合并。
所谓浮动的包裹性是指浮动元素的宽度表现为浮动元素所包裹元素的宽度,我们看例子:
<style> .wrapper { width: 200px; } .float { float: left; } .float img { width: 100px; }style>head><body> <div class="wrapper"> <div class="float"> <img src="./src/images/css禅意花园.png" alt=""> div> div>body>
我
们可以看到设为
flo
a
t
的元素
宽度和
里面
的
图片设置的宽度一样。
再来看一下自适应性的例子:如果浮动元素的子元素不只是一张100px宽度的图片,还有段普通文字,则此时浮动元素的的宽度就是自适应父元素的200px的宽度,最终的宽度也是200px。代码如下:
<style> .wrapper { width: 200px; } .float { float: left; } .float img { width: 100px; }style>head><body> <div class="wrapper"> <div class="float"> <img src="./src/images/css禅意花园.png" alt=""> css禅意花园是一本非常经典的CSS书籍,你也能够学好CSS div> div>body>
运行效果如下图所示:
关于脱离文档流我看如下的例子:
<style> .wrapper { width: 200px; } .float { float: left; } img { width: 100px; }style>head><body> <div class="wrapper"> <div > <img src="./src/images/css禅意花园.png" alt=""> div> <div class="float"> <img src="./src/images/css禅意花园.png" alt=""> div> <div> <img src="./src/images/css禅意花园.png" alt=""> div> div>body>
如果没有脱离文档流那么三张图片应该竖直排列,个个都是独占一行,如下图所示:
可是由于浮动元素会脱离文档流,后面的元素就会位置移动,这样第二张图片和第三张图片就会在同一行显示:
第四,我们解释一下浮动没有任何的margin合并。所谓margin合并是指块级元素的上外边距(margin-top)和下外边距(margin-bottom)有时候会合并为单个外边距。我们看如下代码:
<style> .wrapper { width: 200px; } .float { float: left; margin-bottom: 10px; margin-top: 10px; } img { width: 120px; }style>head><body> <div class="wrapper"> <div class="float"> <img src="./src/images/css禅意花园.png" alt=""> div> <div class="float"> <img src="./src/images/css禅意花园.png" alt=""> div> <div class="float"> <img src="./src/images/css禅意花园.png" alt=""> div> div>body>
3.3 浮动的影响
1.浮动元素的后代元素也会浮动。如果想让子元素随父元素一起浮动,可以浮动父元素。
2.浮动元素脱离文档流,所以父元素的高度可能变小,叫做父元素的高度塌陷。我们看代码:
<style> .wrapper { width: 200px; } img { width: 120px; }style>head><body> <div class="wrapper"> <div > <img src="./src/images/css禅意花园.png" alt=""> div> <p>这是一大段文字,这是一大段文字,这是一大段文字,这是一大段文字,这是一大段文字p> div>body>
这段代码的效果如图:
如果我们给img的父元素加上浮动,如下代码所示:
<style> .wrapper { width: 200px; } .wrapper > div { float: left; } img { width: 120px; }style> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js">script>head><body> <div class="wrapper"> <div > <img src="./src/images/css禅意花园.png" alt=""> div> <p>这是一大段文字,这是一大段文字,这是一大段文字,这是一大段文字,这是一大段文字p> div>body>
则代码的执行效果如下图所示:
以上代码简单演示了高度塌陷的问题,有时候我们在写布局的时候不想要高度塌陷的效果,css专门提供了clear属性来解决这个问题,下面我们来详细介绍。
3.3 清除浮动
清除浮动是为了清除浮动元素对其他元素(包括浮动元素)的影响。例如有多个浮动元素,每一个都不是特别宽,它们会一个个靠在一起,如果高度不同,就会出现混乱的局面。为了解决如上这些问题,CSS提供了clear属性。 clear属性告诉元素不要围着浮动元素显示 。官方解释是: 元素盒子的边不能和前面的浮动元素相邻 。或者说让元素显示在浮动元素的下面。clear属性可选值有left, right, both,none。下面列表说明它们的含义:left | 让元素显示在左浮动元素的下面,简称左侧抗浮动。不过仍然围绕着右浮动元素。 |
right | 让元素显示在右浮动元素的下面,简称右侧抗浮动。不多仍然围绕左浮动的元素。 |
both | 让元素显示在左浮动和右浮动元素的下面,简称两侧抗浮动。 |
none | 不清除浮动。也就是说,元素会围着左右浮动的元素显示,左右浮动想来就来。也是默认值。 |
<style> li { list-style-type: none; margin: 5px; width: 20px; height: 20px; float: left; background-color: #000000; } li:nth-of-type(3) { clear: both; }style>head><body> <ul> <li>li> <li>li> <li>li> <li>li> <li>li> <li>li> <li>li> <li>li> <li>li> <li>li> ul>body>
在如上的代码中,我们给第三个li设置了左右都清浮动,那么这些元素会显示成3行吗?我们看运行结果的截图:
我们看到会显示成2行。这是因为清浮动是清前面的。也就是某个元素不和它前面的左浮动或者右浮动元素一起在同一行显示,但是对后面的元素置若罔闻。我们在实际开发中还会借助伪元素(如after)来清浮动,但是要
注意:clear属性只有块级元素才有效,而::after等元素默认都是内联
水平的,也是为什么借助伪元素清浮动的时候要设置display属性为block、table或者list-item的原因。我们来一个例子,加深理解:
<style> li { list-style-type: none; margin: 5px; width: 20px; height: 20px; float: left; background-color: #000000; } .test::before{ content: ""; display: block; clear: left; } .test::after{ content: ""; display: block; clear: left; }style>head><body> <div class="wrapper"> <ul> <li>li> <li>li> <span class="test">测试文本span> <li>li> <li>li> <li>li> <li>li> <li>li> <li>li> <li>li> ul> div>body>
在上面代码中,所有的li元素都是浮动的,而内联元素span介于它们之间。如果不给span加上伪元素对应的样式,则结果是这个样子:
加上before伪元素对应的样式,结果是这样:
加上after伪元素对应的样式,结果是这样的:
需要注意的是:clear:both的作用本质就是让元素自己不和float显示在一行,并不是真正的清除浮动,因此float带来的副作用依然存在。我们看如下的例子:
<style> .wrapper { width: 200px; border: 1px solid #000000; } .wrapper::after { content: ""; display: table; clear: both; } .wrapper img { float: left; width: 60px; height: 74px; } .wrapper + div { margin-top: -2px; }style>head><body> <div class="wrapper"> <img src="./src/images/css禅意花园.png" alt=""> css很有趣,让我们一起好好学习,推荐一本不错的书啊 div> <div>真是醉了,css你都能学进去,你咋想的啊,拿你没办法,行不行了啊div>body>
代码执行效果如下图所示:
我们看到,虽然父元素设置了clear:both来清除浮动,阻止浮动对后续元素的影响,可是还是发生了错误。那么到底如何解决浮动带来的副作用呢?那就是BFC,我们将在后续文章中详细介绍,敬请关注~