CSS 特异性计数器

CSS Specificity Counter

所以 CSS 特异性 rules 决定了 id 是最强大的,然后是 类,然后是标签名称,然后是 *.

所以 #id > .class > div > *.

如果我提供一串 CSS 选择器,我想做的是为每个选择器获得一个 'rating'。

假设我有一个特异性数组 = [#id, .class, tagname]

span 应该 return [0, 0, 1]

body p 应该 return [0, 0, 2]

.red .orange 应该 return [0, 2, 0]

menu .item #checkout.active 应该 return [1, 2, 1]

我试过这段代码,但肯定有问题:

function compare(a) {
    const comparisonOperators = ["#", ".", " "];
    const aRating = [];

    for (let x = 0; x < comparisonOperators.length; x++) {
        aRating[x] = a.includes(comparisonOperators[x])
            ? a.split(comparisonOperators[x]).filter((x) => x).length
            : 0;
    }

    console.log(aRating);
}

compare("menu .item #checkout.active");
// returns [2,3,3]

对此有什么想法吗?

我采用了与您不同的方法来解决这个问题。

function compare(a) {
    var items = a.split([' ']);
    var aRating = [0,0,0];
    items.forEach(function(i) {
        //case 1
        if(i.split('#').length > 1) {
            aRating[0] = aRating[0] + (i.split('#').length - 1)
        }
        //case 2
        if(i.split('.').length > 1) {
            aRating[1] = aRating[1] + (i.split('.').length - 1)
        }
        //case 3
        if(!i.startsWith('#') && !i.startsWith('.')) { 
            aRating[2] = aRating[2] + 1
        }
        
    });
    console.log(aRating);
}

最初,我根据空格拆分字符串。这给出了要检查的元素总数。然后我循环遍历该数组中的每个项目以确定和计算选择器的数量。

在情况 1 中,如果项目包含 ID,则其长度将大于 1。例如,#myId。如果我根据 # 拆分它,那么我将在一个数组中得到 2 个项目。我用它来确定它是否包含 ID 或不。在这种情况下,这是真的,所以我将 aRating 数组递增 1。如果它不是 ID,那么它的长度将始终为 1,因为它无法拆分。

相同的逻辑适用于 css class 的情况 2。

情况 3 略有不同。如果字符串不是以 # 或 '.' 开头,则它必须是标记名。