详解CSS伪元素及Content属性
初识伪元素
 说起伪元素我第⼀想到的莫过于::before和::after这两个了,它俩其实就是在其附属的选择器命中的元素上插⼊第⼀个⼦节点和追加最后⼀个⼦节点。那这时我不禁地想问:“直接添加两个class为.before和.after不是⼀样的吗?”  其实使⽤伪元素::before和::after以下两个好处:
1.HTML的代码量减少,对SEO有帮助;
2.提⾼JavaScript查询元素的效率。
 那为什么会这两好处呢?原因就是伪元素并不存在于DOM中,⽽是位于CSSOM,HTML代码和DOM Tree中均没有它的⾝影,量少了⾃然效率有所提升。但这也引⼊⼀个问题——我们没办法通过JavaScript完全操控伪元素(我将在下⾯⼀节为⼤家讲述)
⼀⼤波伪元素来了
除了::before和::after外,别漏了以下的哦!
1.:first-line:只能⽤于块级元素。⽤于设置附属元素的第⼀个⾏内容的样式。可⽤的CSS属性为font,color,background,word-spacing,letter-spacing,text-decoration,vertical-align,text-transform,line-height,clear。
2.:first-letter:只能⽤于块级元素。⽤于设置附属元素的第⼀个字母的样式。可⽤的CSS属性为font,color,background,marin,padding,border,text-decoration,vertical-align,text-transform,line-height,float,clear。
3.::selection:匹配选中部分的内容。可⽤的CSS属性为background,color。
有没有发现有的伪元素前缀是:有的却是::呢?::是CSS3的写法,其实除了::selection外,其他伪元素既两种前缀都是可以的,为兼容性可选择使⽤:,为容易区分伪元素和伪类则使⽤::,但我还是建议使⽤::来提⾼可读性,兼容性就让postcss等⼯具帮我们处理就好了。
::before和::after的注意事项
1.默认display: inline;
2.必须设置content属性,否则⼀切都是⽆⽤功;
3.默认user-select: none,就是::before和::after的内容⽆法被⽤户选中的;
4.伪元素和伪类结合使⽤形如:.target:hover::after。
JavaScript操作伪元素
 上⽂提到由于伪元素仅位于CSSOM中,因此我们仅能通过操作CSSOM API——ComputedStyle来读取伪元素的样式信息,注意:我们能做的就是读取,⽆法设置的哦!
{- ComputedStyle的类型 -}
data PseudoElement = ":before" | "::before" | ":after" | "::after" | ":first-line" | "::first-line" | ":first-letter" | "::first-letter" | "::selection" | ":backdrop" | "::backdrop" | Null
{- CSSStyleDeclaration实例的⽅法 -}
data CSSPropertyName = "float" | "backround-color" | ......
data DOMPropertyName = "cssFloat" | "styleFloat" | "backgroundColor" | ......
-- IE9+的⽅法
CSSStyleDeclaration#getPropertyValue :: CSSPropertyName -> *
-- IE6~8的⽅法
CSSStyleDeclaration#getAttribute :: CSSPropertyName -> *
-- 键值对⽅式获取
CSSStyleDeclaration#[DOMPropertyName] -> *
⽰例:
.target[title="hello world"]::after{
display: inline-block;
content: attr(title);
background: red;
text-decoration: underline;
}
const elTarget = document.querySelector(".target")
const computedStyle = ComputedStyle(elTarget, "::after")
const content = PropertyValue("content")
const bg = Attribute("backgroundColor")
const txtDecoration = computedStyle["text-decoration"]
console.log(content) // "hello world"
console.log(bg)      // red
console.log(txtDecoration) // underline
玩透Content属性
 到这⾥我们已经可以利⽤::before和::after实现tooltip等效果了,但其实更为强⼤的且更需花时间研究
的才刚要开始呢!那就是Content属性,不仅仅可以简单直接地设置⼀个字符串作为伪元素的内容,它还具备⼀定限度的编程能⼒,就如上⾯attr(title)那样,以其附属元素的title特性作为content值。下⾯请允许我为⼤家介绍吧!
div::after{
content: "普通字符串";
content: attr(⽗元素的html属性名称);
content: url(图⽚、⾳频、视频等资源的url);
/* 使⽤unicode字符集,采⽤4位16进制编码
* 但不同的浏览器显⽰存在差异,⽽且移动端识别度更差
*/
content: "\21e0";
/* content的多个值可以任意组合,各部分通过空格分隔 */
content: "'" attr(title) "'";
/* ⾃增计数器,⽤于插⼊数字/字母/罗马数字编号
* counter-reset: [<identifier> <integer>?]+,必选,⽤于标识⾃增计数器的作⽤范围,<identifier>为⾃定义名称,<integer>为起始编号默认为0。
* counter-increment: [<identifier> <integer>?]+,⽤于标识计数器与实际关联的范围,<identifier>为counter-reset中的⾃定义名称,<integer>为步长默认为1。
* <list-style-type>: disc | circle | square | decimal | decimal-leading-zero | lower-roman | upper-roman | lower-greek | lower-latin | upper-latin | armenian | georgian | lower-alpha | upper-alpha      */
content: counter(<identifier>, <list-style-type>);
/* 以⽗附属元素的qutoes值作为content的值
*/
content: open-quote | close-quote | no-open-quote | no-close-quote;
}
换⾏符:HTML实体为 ,CSS为\A,JS为\uA。
 可以看到Content接受6种类型,和⼀种组合⽅式。其中最后两种⽐较复杂,我们后⾯逐⼀说明。
⾃定义计数器
 HTML为我们提供ul或ol和li来实现列表,但如果我们希望实现更为可性化的列表,那么该如何处理呢?content属性的counter类型值就能帮到我们。
<!-- HTML 部分-->
.dl
.dt{chapter1}
.dd{text11}
.dd{text12}
.dt{chapter2}
.dd{text21}
/* CSS部分 */
.dl {
counter-reset: dt 0; /* 表⽰解析到.dl时,重置dt计数器为0 */
& .dt {
counter-reset: dd 0; /* 表⽰解析到.dt时,重置dd计数器为0 */
&::before{
counter-increment: dt 1; /* 表⽰解析到.dt时,dt计数器⾃增1 */
content: counter(dt, lower-roman) " ";
}
}
cssclass属性& .dd::before {
counter-increment: dd 1; /* 表⽰解析到.dd时,dd计数器⾃增1 */
content: counter(dd) " ";
}
}
通过counter-reset来定义和重置计数器,通过counter-increment来增加计数器的值,然后通过counter来决定使⽤哪个计数器,并指定使⽤哪种样式。
 如果⽤JavaScript来表⽰应该是这样的
const globalCounters = {"__temp":{}}
function resetCounter(name, value){
globalCounters[name] = value
}
function incrementCounter(name, step){
const oVal = globalCounters[name]
if (oVal){
globalCounters[name] = oVal + step
}
else{
globalCounters.__temp[name] = step
}
}
function counter(name, style){
return globalCounters[name] || globalCounters.__temp[name]
}
function applyCSS(mount){
const clz = mount.className
if (clz == "dl"){
resetCounter("dt", 0)
const children = mount.children
for (let i = 0; i < children.length; ++i){
applyCSS(children[i])
}
}
else if (clz == "dt"){
resetCounter("dd", 0)
incrementCounter("dt", 1)
const elAsBefore = ateElement("span")
mount.insertBefore(mount.firstChild)
}
else if (clz == "dd"){
incrementCounter("dd", 1)
const elAsBefore = ateElement("span")
mount.insertBefore(mount.firstChild)
}
}
嵌套计数器
 对于多层嵌套计数器我们可以使⽤counters(<identifier>, <separator>, <list-style-type>?)
.ol
.li
.ol
.li{a}
.li{b}
.li
.ol
.
li{c}
.ol {
counter-reset: ol;
& .li::before {
counter-increment: ol;
content: counters(ol, ".");
}
}
Content的限制
1.IE8+才⽀持Content属性;
2.除了Opera9.5+中所有元素均⽀持外,其他浏览器仅能⽤于:before,:after内使⽤;
3.⽆法通过JS获取Counter和Counters的运算结果。得到的就只能是"counter(mycouonter) \" \""。
⾃定义引号
 引号这个平时很少在意的符号,其实在不同的⽂化中使⽤的引号将不尽相同,如简体中⽂地区使⽤的"",⽽⽇本则使⽤「」。那我们根据需求⾃定义引号呢?答案是肯定的。
 通过open-quote,close-quote,no-open-quote和no-close-quote即可实现,下⾯我们通过例⼦来理解。
 <q>会根据⽗元素的lang属性⾃动创建::before和::after来实现插⼊quotation marks。
p[lang=en]>q{英语}
p[lang=no]>q{挪威语}
p[lang=zh]>q{汉语}
p[lang=en]&-quote{英语2}
div[lang=no]>.quote{挪威语2}
CSS⽚段:
p[lang=en] > q{
quotes: "<!--" "-->"; /* 定义引号 */
}
p[lang=en] > q.no-quote::before{
content: no-open-quote;
/*或者 content: none;*/
}
div[lang=no] > .quote {
quotes: "<<-" "->>";
}
div[lang=no] > .quote::before {
content: open-quote;
}
div[lang=no] > .quote::after {
content: close-quote;
}
⽰例
分割线
p.sep{or}
.sep {
position: relative;
text-align: center;
&::before,
&::after {
content: "";
box-sizing: border-box;
height: 1px;
width: 50%;
border-left: 3em solid transparent;
border-right: 3em solid transparent;
position: absolute;
top: 50%;
}
&::before {
left: 0;
}
&::after {
right: 0;
}
}
只读效果(通过遮罩原来的元素实现)
.input-group {
position: relative;
&.readonly::before {
content: "";
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
}
}
计数器
.selections>input[type=checkbox]{option1}+input[type=checkbox]{option2}
.
selection-count
.selections{
counter-reset: selection-count;
& input:checked {
counter-increment: selection-count;
}
}
.selection-count::before {
content: counter(selection-count);
}
参考
总结
以上所述是⼩编给⼤家介绍的CSS 伪元素及Content 属性,希望对⼤家有所帮助,如果⼤家有任何疑问请给我留⾔,⼩编会及时回复⼤家的。在此也⾮常感谢⼤家对⽹站的⽀持!

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