继上篇《CSS魔法堂:稍稍深刻伪类选择器》记录完伪类后,我天然而然要向伪元素伸出“魔掌”的啦^_^。本文讲讲述伪元素以及功能强大的Contet属性,让咱们能够经过伪元素更好地实现更多的可能!javascript
提及伪元素我第一想到的莫过于::before
和::after
这两个了,它俩其实就是在其附属的选择器命中的元素上插入第一个子节点和追加最后一个子节点。那这时我不由地想问:“直接添加两个class为.before和.after不是同样的吗?”
其实使用伪元素::before
和::after
如下两个好处:css
除了::before
和::after
外,别漏了如下的哦!html
:first-line
:只能用于块级元素。用于设置附属元素的第一个行内容的样式。可用的CSS属性为font,color,background,word-spacing,letter-spacing,text-decoration,vertical-align,text-transform,line-height,clear
。:first-letter
:只能用于块级元素。用于设置附属元素的第一个字母的样式。可用的CSS属性为font,color,background,marin,padding,border,text-decoration,vertical-align,text-transform,line-height,float,clear
。::selection
:匹配选中部分的内容。可用的CSS属性为background,color
。有没有发现有的伪元素前缀是:
有的倒是::
呢?::
是CSS3的写法,其实除了::selection
外,其余伪元素既两种前缀都是能够的,为兼容性可选择使用:
,为容易区分伪元素和伪类则使用::
,但我仍是建议使用::
来提升可读性,兼容性就让postcss等工具帮咱们处理就行了。java
::before
和::after
的注意事项display: inline
;user-select: none
,就是::before
和::after
的内容没法被用户选中的;.target:hover::after
。 上文提到因为伪元素仅位于CSSOM中,所以咱们仅能经过操做CSSOM API——window.getComputedStyle
来读取伪元素的样式信息,注意:咱们能作的就是读取,没法设置的哦!编程
{- window.getComputedStyle的类型 -} data PseudoElement = ":before" | "::before" | ":after" | "::after" | ":first-line" | "::first-line" | ":first-letter" | "::first-letter" | "::selection" | ":backdrop" | "::backdrop" | Null window.getComputedStyle :: HTMLElement -> PesudoElement -> CSSStyleDeclaration {- 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 = window.getComputedStyle(elTarget, "::after") const content = computedStyle.getPropertyValue("content") const bg = computedStyle.getAttribute("backgroundColor") const txtDecoration = computedStyle["text-decoration"] console.log(content) // "hello world" console.log(bg) // red console.log(txtDecoration) // underline
到这里咱们已经能够利用::before
和::after
实现tooltip等效果了,但其实更为强大的且更需花时间研究的才刚要开始呢!那就是Content属性,不只仅能够简单直接地设置一个字符串做为伪元素的内容,它还具有必定限度的编程能力,就如上面attr(title)
那样,以其附属元素的title特性做为content值。下面请容许我为你们介绍吧!app
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
。ide
能够看到Content接受6种类型,和一种组合方式。其中最后两种比较复杂,咱们后面逐一说明。工具
HTML为咱们提供ul
或ol
和li
来实现列表,但若是咱们但愿实现更为可性化的列表,那么该如何处理呢?content属性的counter类型值就能帮到咱们。post
<!-- 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) " "; } } & .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 = document.createElement("span") elAsBefore.textContent = counter("dt", "lower-roman") + " " mount.insertBefore(mount.firstChild) } else if (clz == "dd"){ incrementCounter("dd", 1) const elAsBefore = document.createElement("span") elAsBefore.textContent = counter("dd", "lower-roman") + " " 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, "."); } }
:before,:after
内使用;"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]>q.no-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); }
尊重原创,转载请注明来自:http://www.javashuo.com/article/p-wyduhtkj-g.html 肥仔John^_^
http://www.wozhuye.com/compatible/297.html
https://dev.opera.com/articles/css-generated-content-techniques/