Javascript 根据特定性对一组CSS选择器进行排序

Javascript 根据特定性对一组CSS选择器进行排序,javascript,dom,css-selectors,css-specificity,Javascript,Dom,Css Selectors,Css Specificity,在JS函数中,如何根据CSS的特殊性对一组CSS选择器进行排序 function SortByCssSpecificity(input_array_of_css_selectors) { ... return sorted_array_of_css_selectors; } 发件人: 选择器的特异性计算如下: 计算选择器中ID选择器的数量(=a) 计算选择器中的类选择器、属性选择器和伪类的数量(=b) 计算选择器中类型选择器和伪元素的数量(=c) 忽略通用选择器 否定伪类[:not

在JS函数中,如何根据CSS的特殊性对一组CSS选择器进行排序

function SortByCssSpecificity(input_array_of_css_selectors) {
  ...
  return sorted_array_of_css_selectors;
}
发件人:

选择器的特异性计算如下:

  • 计算选择器中ID选择器的数量(=a)
  • 计算选择器中的类选择器、属性选择器和伪类的数量(=b)
  • 计算选择器中类型选择器和伪元素的数量(=c)
  • 忽略通用选择器
否定伪类[
:not()
]中的选择器与其他选择器一样计数,但否定本身不作为伪类计数

将三个数字a-b-c(在一个基数较大的数字系统中)串联在一起,给出了特殊性

示例:

*/*a=0 b=0 c=0->特异性=0*/
LI/*a=0b=0c=1->特异性=1*/
UL LI/*a=0 b=0 c=2->特异性=2*/
UL OL+LI/*a=0 b=0 c=3->特异性=3*/
H1+*[REL=up]/*a=0 b=1 c=1->特异性=11*/
UL OL LI.red/*a=0 b=1 c=3->特异性=13*/
LI.red.level/*a=0 b=2 c=1->特异性=21*/
#x34y/*a=1 b=0 c=0->特异性=100*/
#s12:非(FOO)/*a=1b=0c=1->特异性=101*/
(,在本答案之后发布,由于引入了一些目前不在本答案范围内的新选择器,为特异性增加了另一层复杂性。)

下面是一个伪代码实现,可以让您开始使用,它远不是完美的,但我希望它是一个合理的起点:

函数SortByCSSpecification(选择器、元素){
简单选择器=[]
用于选择器中的选择器{
//(可选)传递元素以仅包含匹配的选择器
//MatchSelector()的实现不在范围内
//但是客户端JS可以使用元素#matches()来
// https://developer.mozilla.org/en-US/docs/Web/API/Element/matches
if(元素&!匹配选择器(选择器,元素)){
持续
}
简单选择器[选择器]=语法选择器(选择器)
简单选择器[selector]=简单选择器[selector]。过滤器(x | x!='*'))
//这假设伪元素按照CSS3用双冒号表示
//一致性实现必须解释
//:first-line、:first-letter、:before和:after作为伪元素
a=简单选择器[selector]。过滤器(x^='#')。长度
b=简单选择器[selector]。筛选器(x ^='.'或x.match(/^:[^:::+/)或x.match(/^\[.+\]$/).length
c=简单选择器[selector]。长度-(a+b)
简单选择器[selector][count]=parseInt(“”+a+b+c)
}
返回简单的选择器。排序(x,y | x[count]”拆分每个选择器组
//:not()是一个特例,请不要将其作为伪类包含
//对于选择器div>p:not(.foo)~span.bar,
//示例输出为['div','p','.foo','span','.bar']
返回简单的\u选择器
}

而且,我最喜欢的惊喜是,它在重复计数:
a.foo.foo
(21)比
a.foo
(11)更具体。@BoltClock我认为函数sortbycssspecification(选择器)需要用sortbycssspecification(选择器,节点)进行更正,因为某些CSS选择器文本可能与节点无关。例如,使用组运算符
。有些CSS选择器文本与节点无关,因此不应计算。@einstein:我不知道9年来我怎么会错过你的评论,但我现在已经添加了该功能,尽管它不在原始问题中。为了准确起见,我将节点重命名为元素-并非所有节点都是元素节点,选择器将只匹配元素节点。虽然计算特异性很容易,但首先解析简单的选择器将是一个相当大的挑战。稍后我将添加一个基本的伪代码解决方案。在此期间,我会留下我的答案,首先引用规范。边说边编辑。我在社区维基上做了回答。如果您或其他人提出了实际的JavaScript实现,我们很乐意看到它@BoltClock:在四处搜索时,我发现了一个PHP实现。如果可能的话,我将尝试创建JS实现并编辑wiki。