Gee*_*tra 4 javascript dom css-selectors css-specificity
如何在JS函数中基于CSS特异性对一组CSS选择器进行排序?
function SortByCssSpecificity(input_array_of_css_selectors) {
...
return sorted_array_of_css_selectors;
}
Run Code Online (Sandbox Code Playgroud)
从选择器规范:
选择器的特异性计算如下:
- 计算选择器中ID选择器的数量(= a)
- 计算选择器中的类选择器,属性选择器和伪类的数量(= b)
- 计算选择器中类型选择器和伪元素的数量(= c)
- 忽略通用选择器
否定伪类[
:not()]中的选择器与其他选择器一样,但是否定本身不算作伪类.连接三个数字abc(在具有大基数的数字系统中)给出了特异性.
例子:
Run Code Online (Sandbox Code Playgroud)* /* a=0 b=0 c=0 -> specificity = 0 */ LI /* a=0 b=0 c=1 -> specificity = 1 */ UL LI /* a=0 b=0 c=2 -> specificity = 2 */ UL OL+LI /* a=0 b=0 c=3 -> specificity = 3 */ H1 + *[REL=up] /* a=0 b=1 c=1 -> specificity = 11 */ UL OL LI.red /* a=0 b=1 c=3 -> specificity = 13 */ LI.red.level /* a=0 b=2 c=1 -> specificity = 21 */ #x34y /* a=1 b=0 c=0 -> specificity = 100 */ #s12:not(FOO) /* a=1 b=0 c=1 -> specificity = 101 */
这是一个伪代码实现,可以帮助您入门,它远非完美,但我希望它是一个合理的起点:
function SortByCssSpecificity(selectors) {
simple_selectors = [][]
for selector in selectors {
simple_selectors[selector] = parse_selector(selector)
simple_selectors[selector] = simple_selectors[selector].filter(x | x != '*')
// This assumes pseudo-elements are denoted with double colons per CSS3
// A conforming implementation must interpret
// :first-line, :first-letter, :before and :after as pseudo-elements
a = simple_selectors[selector].filter(x | x ^= '#').length
b = simple_selectors[selector].filter(x | x ^= '.' or x.match(/^:[^:]+/) or x.match(/^\[.+\]$/)).length
c = simple_selectors[selector].length - (a + b)
simple_selectors[selector][count] = parseInt('' + a + b + c)
}
return simple_selectors.sort(x, y | x[count] < y[count])
}
function parse_selector(selector) {
simple_selectors = []
// Split by the group operator ','
// Split each selector group by combinators ' ', '+', '~', '>'
// :not() is a special case, do not include it as a pseudo-class
// For the selector div > p:not(.foo) ~ span.bar,
// sample output is ['div', 'p', '.foo', 'span', '.bar']
return simple_selectors
}
Run Code Online (Sandbox Code Playgroud)