浅谈css的伪元素::after和::before给伪元素添加点击事件
css中的::after和::before已经被⼤量地使⽤在我们⽇常开发中了,使⽤他们可以使我们的⽂档结构更加简洁。但是很多⼈对::after和::before仍不是特别了解,究竟他们是做什么的?如何使⽤他们?什么时候应该使⽤他们?笔者总结了⼀些对伪元素的理解和使⽤经验。
⼀、概念:
1.定义
The CSS ::before(::after)  matches a virtual first(last) child of the selected element. It is typically used to add cosmetic content to an element by using the  CSS property. This element is inline by default.
input标签placeholder属性从定义我们知道::before和::after匹配⼀个虚拟元素,主要被⽤于为当前元素增加装饰性内容的。他显⽰的内容是其⾃⾝的“content”属性,默认是内联元素。
其实::after和::before被引⼊css中,最核⼼的⽬的,还是为了实现语义化。在我们实际开发时候经常有这样的经历,为了实现⼀些效果,在⽂档中创建了⼀些没有实际内容的节点,或者加⼊辅助样式的⽂本,如:
<style>
ul{
list-style: none;
}
li{
display: inline;
}
</style>
<nav>
<ul>
<li>HTML 5</li>
<li>|</li>
<li>CSS3</li>
<li>|</li>
<li>JavaScript</li>
</ul>
</nav>
显⽰的时候是这样⼦的:
很明显,例⼦中的“|”仅是显⽰时候⽤的间隔符,没有实际的意义,⽽他所在的li元素仅是为了装饰才被创建的,本是不应该被创建在⽂档内的。那么能不能由样式(css)去创建出节点把他们代替掉呢?
出于这样的需求,就诞⽣了::after和::before,这两个伪元素相当于是对当前元素的装潢,他们并不是
节点,不会出现在dom树中,但是在显⽰上具备节点的效果。我们使⽤::after和::before重构⼀下上边的代码:
<style>
ul{
list-style: none;
}
li{
display: inline;
}
li:not(:last-child)::after{
content: "|";
}
</style>
<nav>
<ul>
<li>HTML 5</li>
<li>CSS3</li>
<li>JavaScript</li>
</ul>
</nav>
显⽰效果没有变化,但是⽂档结构变得清晰了多了。
2.使⽤
::after和::before的使⽤很简单,可以认为其所在元素上存在⼀前⼀后的两个的元素,这两个元素默认是内联元素,但我们可以为其增添样式。::after 和::before使⽤的时候⼀定要注意,必须设置content,否则这两个伪元素是⽆法显⽰出来的。⽽content属性,会作为这两个伪元素的内容嵌⼊他们中。如果不需要伪元素的内容,可以将content设置为'',但是不设置的话,伪元素就会⽆效。如:
<style>
p:before{
content: "H";
p:after{
content: "d";
}
</style>
<p>ello Worl</p>
显⽰为完整的Hello World。
::after和::before是虚拟元素,不会影响真正元素的所在⽂档的位置,对:first-child或者:last-child这种伪类选择不会造成影响。
3.操作
::after和::before是虚拟节点,⽽不是正在的节点,不在documont⾥⾯到对应Node对象,在之前的例⼦中,我们执⾏下列js代码:
console.log( document.querySelector("ul").childNodes);
得到的是⼀个只有3个节点的NodeList对象,⽽两个伪元素并不在对象中。因为::after和::before不是真正的节点,所以我们取不到他们,也不发设置点击等⽤户事件。::after和::before虽然是不能设置事件,但还会捕获⽤户事件,并把事件“冒泡”到伪元素所在的元素上。之所以“冒泡”⼆字加了引号,是因为他不是真的冒泡,更准确的说::after和::before帮所在元素去捕获去事件,事件的srcElement对象是伪元素所在的元素,⽽不是伪元素本⾝。
document不能获取到::after和::before所对应的节点对象,但是可以通过css的接⼝获取其样式属性,如:
document.querySelector('li'), ':before'
)
返回是个CSSStyleDeclaration对象,可以获取当前的style值。
另外,content属性京城配合attr()函数使⽤,attr()函数⽤来获取html元素指定属性的值,eg:
.wcs:before{
content:attr(title);
color:red;
}
<div class="wcs" title="第五部分">
王船⼭的美学思想
</div>
⼆、分享⼀些::after和::before使⽤的经验
以下例⼦多数是在特定平台上使⽤过的,未做兼容处理,建议在chrome下浏览
1.间隔符⽤法
如⽂章最开始的例⼦,使⽤::after伪元素做间隔符,并使⽤伪类:not排除掉最后⼀个元素。
2.做border三⾓图标
很多开发者都⽤过border做的三⾓图标,本⾝三⾓符号就不属于⽂档,使⽤伪元素做三⾓符最合适了。
3.字符图标
最近笔者在开发⼩程序,因为⼩程序不⽀持svg和背景图,于是笔者⼤量使⽤字符图标,感觉字符图标⾮常⽅便,就是受设备系统字体库限制。
4.webfont的图标
现在webfont图标的最佳实践就是使⽤i标签和::after或者::before,实现这种图标最佳实践的⼯具⾮常多,⽐如,从这个⽹站我们可以下载svg的图标库。这种例⼦太多了,这⾥就不再列举。
5.做单位、标签、表单必填标准
笔者⼀直认为表单输⼊框的必填标记(往往是红⾊的“*”字符),不应该放到⽂档当中,使⽤::before可以很优雅地解决这个问题(其实就是字符图标的进⼀步应⽤)。
对于单位和前(后)置标签,也可以这样做。但是多数情况下不推荐这种做法,因为单位和标签应该是⽂档的⼀部分。
6.做⼀些效果
可以参考这篇⽂章的效果,笔者曾经在实际项⽬中使⽤过“迷⼈的阴影”效果,也曾在微场景开发中实现过⼀些类似的动画。
7.实现⼀些标签对placeholder的⽀持
只有⼏个标签⽀持placeholder,⽽且如<input type='date' />虽然是input但是也不⽀持。使⽤::before可以让⼀部分标签也实现对placeholder属性的⽀持。
8.实现⽂字图⽚居中对齐
优雅地实现,使⽤⼀个⾼度为100%的::before将⾃⾝的对齐线移动到⾃⼰的中线,这样⾥⾯的所有内联元素都居中对齐了。
9.清除浮动
即对浮动盒⼦的⽗元素设置:after产⽣⼀个伪元素,⽤这个伪元素清除浮动,这样就不需要在浮动元素后⾯新增⼀个空元素了。这个很常
⽤,bootstrap的clearfix类就是使⽤这个⽅法。
10.使⽤pointer-events消除伪元素事件
之前提到过,伪元素::after和::before会替所在元素捕获⽤户事件,有时候这并⾮我们想要的,因为这样会影响被::after和::before覆盖的⼦节点或者兄弟节点捕获⽤户事件。
那么如何给伪元素添加点击事件?
经过思考及查相应的资料后,整理初2种⽅式,记录⼀下:
⼀、给元素设置pointer-events:none.然后给伪元素的pointer-events:auto;此时我们把点击元素的事件就取消了。点击伪元素的时候,就可以绑定相应的事件了。
⼆、第⼆种是:通过⼦元素的事件冒泡原理,在⼦元素事件处理结束后return false,告知⽗元素事件处理完毕。这样只就屏蔽了⽗元素接收事件,然后:after伪元素是悬浮在⼦元素上⾯的,故点击伪元素的时候触发⽗元素事件。
所有例⼦的源码在
简单就分享这么多,总之使⽤伪元素的核⼼是更利于语义化,这是我们活⽤::after和::before的前提,否则就是胡乱使⽤了。总体可以分为四种⽤法:
1.⽤css创建装饰性元素
2.⽤css创建⽤于布局的元素,实现特殊布局的特殊需要
3.做显⽰图标的实现⼿段
4.配合attr显⽰属性值
三、:before和::before是什么区别
解答要点
相同点
1. 都可以⽤来表⽰伪类对象,⽤来设置对象前的内容
2. :befor和::before写法是等效的
不同点
1. :befor是Css2的写法,::before是Css3的写法
2. :before的兼容性要⽐::before好,不过在H5开发中建议使⽤::before⽐较好
加分项
1. 伪类对象要配合content属性⼀起使⽤
2. 伪类对象不会出现在DOM中,所以不能通过js来操作,仅仅是在 CSS 渲染层加⼊
3. 伪类对象的特效通常要使⽤:hover伪类样式来激活
test:hover::before { /* 这时animation和transition才⽣效 */ }
参考:
--------------------- 本⽂来⾃马⼤头的CSDN 博客,全⽂地址请点击:blog.csdn/w405722907/article/details/79446038?utm_source=copy

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。