Калькулятор специфичности CSS

Вычисляет и сравнивает специфичность CSS-селекторов.

Попробовать пример:

Часто задаваемые вопросы

Реализация кода

import re

def parse_specificity(selector: str) -> tuple[int, int, int, int]:
    """
    Returns (inline, ids, classes, elements) specificity tuple.
    Inline styles are not detectable from a selector string,
    so 'a' is always 0 here.
    """
    # Remove :not() contents but count what's inside
    not_contents = re.findall(r':not\(([^)]+)\)', selector)
    selector_no_not = re.sub(r':not\([^)]*\)', '', selector)

    ids = len(re.findall(r'#[\w-]+', selector_no_not))
    classes = len(re.findall(r'\.[\w-]+', selector_no_not))
    attrs = len(re.findall(r'\[[^\]]*\]', selector_no_not))
    pseudo_classes = len(re.findall(r':[\w-]+', selector_no_not))
    pseudo_elements = len(re.findall(r'::[\w-]+', selector_no_not))
    elements = len(re.findall(r'(?<![#.\[\]:*])[a-zA-Z][\w-]*', selector_no_not))

    # Count inside :not()
    for inner in not_contents:
        inner_spec = parse_specificity(inner)
        ids += inner_spec[1]
        classes += inner_spec[2]
        elements += inner_spec[3]

    c = classes + attrs + pseudo_classes - pseudo_elements
    d = elements + pseudo_elements

    return (0, ids, max(c, 0), max(d, 0))

selectors = [
    "#header .nav a",      # (0,1,1,1)
    "div#main .content p", # (0,1,1,2)
    ":not(#id)",           # (0,1,0,0)
    ".btn.active",         # (0,0,2,0)
    "h1",                  # (0,0,0,1)
]

for sel in selectors:
    spec = parse_specificity(sel)
    print(f"{sel!r:35} => {spec}")

Comments & Feedback

Comments are powered by Giscus. Sign in with GitHub to leave a comment.