本节会接着上一节的内容继续聊聊这两个问题。
我们还是先来看看清除浮动与这两个伪元素的关系吧。
首先,我们设想这样一个情景:此时的你要设计一个自适应高度的网站(当然也可以自适应宽度啦)。我们拟定一个布局,这里面有两个盒子,我让他们都左浮动。效果如下:
好了,这时候我们要给它加一个边框,将它们俩框起来,作为一个区块内容展示。
因此我加入了下列代码:
.box {
height: auto;
width: 800px;
border: 1px solid black;
}
这样应该 OK 了。可是。。。
我们的高度变成了一条线!也就是上边框 + 下边框 = 2px 宽的线。
我们前面说到,浮动会脱离文档流,因此,这个高度就不会被撑开,而是占据了这两个盒子曾经占据的地方。与上节中的盒子4 是一个意思。那么?我们应该如何解决这个麻烦呢?
这时候,就需要我们的 :: before
和 :: after
上场啦。当然,这两个根据实际需要可使用一个,也可以都使用。
因此我们添加下列代码:
.box::after {
content: '';
display: table;
}
.box::after {
clear: both;
}
此时我们再来看效果:
嗯 ~ 非常的完美。解决了我们的问题。但是我们需要思考的是,这背后的原理是什么呢?
这里有一个概念,叫做 BFC。我不在这里展开讲述这个东西,它很简单也很复杂,感兴趣的同学可以去搜索一下。
简单来说,我们使用了伪元素后,实际上在 DOM 中并没有添加东西,而是由一个 display: table
解决了问题,就是因为 table 是一个块级元素。相当于我们将伪元素中的空内容给撑开来了(详情可见 BFC 的内容)。
这就是第一个例子,用于解决自适应高度塌陷的问题。
提示框
提示框想必我们都看过吧,以前呢,我们从来没有在意过。而现如今,可以说没有哪个网站不在使用如下的提示框。我现在拿知乎来举例子吧:
我在这里随便找了个人截图。我们可以看到使用户体验更好的小三角出现了。那么这是怎么做到的呢?
这时候,我们就可以使用到我们的这两个伪元素。
那么首先我们需要清楚它的原理究竟是什么。
我先创建一个 div
,它只由边框组成,宽高都为 0 的时候,它是什么样的。
.arrow {
width: 0;
height: 0;
font-size: 0;
border: solid 10px #000;
}
显示的结果如下:
这时,我们就得到了一个由边框组成的小黑方块。相信大家不是很能明白为什么。那么我们再给它的是个边加上不同的颜色试试看:
现在你的脑海中是不是有一些小小的想法啦? 它的整个边框其实是由四个三角形组成的,每一边为一个三角形,那么我们就可以利用这个特点,来做可爱的小尖角了。
那么它的实现原理是什么呢?让两个不同颜色的三角形图标叠加,并且位置错开1px,这样底层三角形 top border 被遮盖,只露出左右 border 部分,叠加在一起我们就得到一个看似带边框的三角形图标。
那么首先我们先创建一个 box 提示框吧。
.box {
width: 200px;
height: 80px;
border: 1px solid #000;
border-radius: 5px;
position: relative;
}
CSS 代码如上所示,其中的 position: relative;
是为了使我们的小三角形能根据父级(box)进行绝对定位。效果如下:
我们这时候呢,再 box 中创建一个 arrow1,再进行如下的 CSS 设置:
首先的两个箭头公共的 CSS 样式:
.arrow1,.arrow2 {
position: absolute;
width: 0;
height: 0;}
接着是 arrow1 的:
.arrow1 {
border: 10px solid #000;
border-right: 10px solid transparent;
border-bottom: 10px solid transparent;
border-left: 10px solid transparent;
left: 50%;
margin-left: -10px;
bottom: -20px;}
这时候就初具效果啦:
额。。虽然看起来怪怪的吧,但没有关系,我们离成功很近啦!这里的
transparent
就是使其边框变透明的意思。
这时候我们再创建一个 arrow2 覆盖在 arrow1 上面就可以啦:
.arrow2 {
border: 10px solid #ffffff;
border-right: 10px solid transparent;
border-bottom: 10px solid transparent;
border-left: 10px solid transparent;
left: 50%;
margin-left: -10px;
bottom: -19px;
}
注意:arrow2 的代码与 arrow1 的不同只在于:1.背景颜色为白色;2.bottom 减少了 1px。
最终效果图如下!
补充:在评论区有人问我关于这个 margin-left: -10px;
和 botrom: -20px
这两行代码是怎么来的呢?我这就好好的解释一下吧:
首先是 margin-left: -10px;
。这个其实很好理解,我们在前面进行了 left: 50%
的操作,但由于本身的小方块的 width
还有 20px,因此 50% 就变成了 left: 100px;
,这显然不是居中的位置。
因此,我用了一个计算公式:200(box的宽)- 20(小方块的宽) / 2 = 90
而我们此时的位置却在 left: 100px;
,所以我们加上 margin-left: -10px;
后计算结果如下:
100 - 10 = 90
这样就显示居中了,我们当然也可以直接使用 left: 90px;
以达到效果啦。这算是我的一个失误,没有取得最优化的代码。抱歉。
下一个是关于 botrom:-20px
这行代码。我们前面说,我们使用了 transparent
使小方块的左、右、下都显示透明以隐藏起来,这样就只显示上面的小方块了。但是我们不要忘了,这里仅仅是“透明”,而不是“消失”!
因此,我为了让大家看得更清楚,所以我将 transparent
先去掉,显示出整个小方块来;再将我们原先的 botrom: -20px
代码改为 botrom: 0;
,显示结果如下:
此时,我们再将 botrom: 0
代码改为 botrom: -20px;
看看吧:
为什么是 -20,也同样是因为我们原先的 border-width
设置的是 10px
。此时,我们再将 transparent
添加上,就能得到我们想要的效果啦。
这里要感谢 @小菜鸟2017 在评论中提出的问题。如果在未来我写出的代码中有什么疑问,欢迎留言。我会回复的,谢谢~
很简单吧?当然,我知道你要问什么,这个和这两个伪元素有什么关系呢?
我给你们一个解释吧:这里我使用的是嵌套的关系:box => arrow1 & arrow2。当然在代码差不多的情况下,你也可以使用 :: before
或者 :: after
对其进行定位。嵌套关系就变成了:box & box::after {arrow1} & box::after {arrow2}。也就是说,基本的中心思想是没有变化的。仅仅是写法的不同而已。
大家可以将这里的代码复制下来,到时候在需要的时候进行修改即可。当然,我这里的写法不是最好的,是按照知乎上来的,其实也有更好的写法哦。不过需要大家对 CSS 非常熟练才能掌握。
我建议呢,大家在平时的练习过程中将代码都单独保存起来,作为自己的 UI 库。在需要的时候,只需要复制过来进行修改即可。
总结
这第一节的内容比较的多,但是都是我们最常用到的 2 个示例,因此我讲的比较的详细。后面的知识点,为了粒度划分,所以我还是尽可能地单独成一节。因为很多属性确实比较简单一些,不需要大幅篇章的去表达。因此,后面的内容可能就比较轻松一些啦。