A CSS Cascading Style Sheets library for Python implementing DOM Level 2 Style specifications
—
Parse, validate, and manipulate CSS selectors with support for CSS3 selector syntax, pseudo-classes, pseudo-elements, and specificity calculations.
Individual CSS selector with parsing, validation, and specificity calculation.
class Selector:
"""
Individual CSS selector implementing cssutils selector interface.
"""
# Properties
selectorText: str # Complete selector text
specificity: tuple # Specificity as (a, b, c, d) tuple
# Methods
@property
def selectorText():
"""Get/set selector text"""
@selectorText.setter
def selectorText(selectorText):
"""
Set selector text with parsing and validation.
Parameters:
- selectorText (str): CSS selector text
"""
@property
def specificity():
"""
Get selector specificity as (a, b, c, d) tuple.
Returns:
tuple: Specificity where:
- a: inline styles (always 0 for selectors)
- b: IDs
- c: classes, attributes, pseudo-classes
- d: elements, pseudo-elements
"""
def __str__():
"""String representation of selector"""
def __repr__():
"""Debug representation of selector"""Collection of CSS selectors (comma-separated selector group).
class SelectorList:
"""
List of CSS selectors implementing cssutils SelectorList interface.
"""
# Properties
selectorText: str # Complete selector list text (comma-separated)
length: int # Number of selectors in list
# Access Methods
def item(index):
"""
Get selector at specified index.
Parameters:
- index (int): Selector index (0-based)
Returns:
Selector: Selector at index, or None if out of bounds
"""
def __getitem__(index):
"""Get selector by index using bracket notation"""
def __len__():
"""Get number of selectors"""
def __iter__():
"""Iterator over selectors"""
# Modification Methods
def appendSelector(selector):
"""
Add selector to end of list.
Parameters:
- selector (str/Selector): Selector to add
"""
def insertSelector(selector, index):
"""
Insert selector at specified index.
Parameters:
- selector (str/Selector): Selector to insert
- index (int): Position to insert
"""
def removeSelector(selector):
"""
Remove selector from list.
Parameters:
- selector (str/Selector): Selector to remove
"""
# Properties
@property
def selectorText():
"""Get/set complete selector list text"""
@selectorText.setter
def selectorText(selectorText):
"""
Set selector list text with parsing.
Parameters:
- selectorText (str): Comma-separated selector list
"""import cssutils
from cssutils.css import Selector, SelectorList
# Parse individual selector
selector = Selector()
selector.selectorText = 'div.container > p:first-child'
print(f"Selector: {selector.selectorText}")
print(f"Specificity: {selector.specificity}")
# Parse selector list
selector_list = SelectorList()
selector_list.selectorText = 'h1, h2, h3.important'
print(f"Number of selectors: {len(selector_list)}")
# Access individual selectors
for i, sel in enumerate(selector_list):
print(f"Selector {i}: {sel.selectorText} (specificity: {sel.specificity})")import cssutils
# Parse CSS with various selectors
css = """
body { margin: 0; }
#header { background: blue; }
.nav li a:hover { color: red; }
div > p:first-child { font-weight: bold; }
h1, h2, h3 { font-family: Arial; }
"""
sheet = cssutils.parseString(css)
# Examine selectors in style rules
for rule in sheet:
if rule.type == rule.STYLE_RULE:
print(f"Rule: {rule.selectorText}")
# Access selector list
selector_list = rule.selectorList
print(f" Number of selectors: {len(selector_list)}")
# Access individual selectors
for selector in selector_list:
print(f" Selector: {selector.selectorText}")
print(f" Specificity: {selector.specificity}")import cssutils
from cssutils.css import Selector
# Test different selector specificities
selectors = [
'*', # (0,0,0,1) - universal
'div', # (0,0,0,1) - element
'div p', # (0,0,0,2) - elements
'.class', # (0,0,1,0) - class
'div.class', # (0,0,1,1) - element + class
'#id', # (0,1,0,0) - ID
'#id.class', # (0,1,1,0) - ID + class
'div#id.class', # (0,1,1,1) - element + ID + class
'div > p.highlight', # (0,0,1,2) - elements + class
'a:hover', # (0,0,1,1) - element + pseudo-class
'a::before', # (0,0,0,2) - element + pseudo-element
'[type="text"]', # (0,0,1,0) - attribute
'div[class~="nav"]', # (0,0,1,1) - element + attribute
]
for sel_text in selectors:
selector = Selector()
selector.selectorText = sel_text
print(f"{sel_text:20} -> {selector.specificity}")import cssutils
# Parse stylesheet
css = """
.old-class { color: red; }
div.container { margin: 20px; }
"""
sheet = cssutils.parseString(css)
# Modify selectors
for rule in sheet:
if rule.type == rule.STYLE_RULE:
old_selector = rule.selectorText
# Replace class name
if '.old-class' in rule.selectorText:
rule.selectorText = rule.selectorText.replace('.old-class', '.new-class')
print(f"Changed: {old_selector} -> {rule.selectorText}")
# Add additional selector
elif rule.selectorText == 'div.container':
rule.selectorText = 'div.container, section.container'
print(f"Extended: {old_selector} -> {rule.selectorText}")
print(sheet.cssText)import cssutils
from cssutils.css import SelectorList
# Complex selectors with various CSS3 features
complex_selectors = [
'input[type="email"]:valid',
'article > section:nth-child(2n+1)',
'nav ul li:not(.active)',
'div.content ~ aside',
'h2 + p::first-line',
'table tbody tr:nth-last-child(-n+3)',
'.sidebar a:matches([href^="http"],[href^="mailto"])',
]
for sel_text in complex_selectors:
try:
selector_list = SelectorList()
selector_list.selectorText = sel_text
print(f"Parsed: {sel_text}")
for selector in selector_list:
print(f" Specificity: {selector.specificity}")
except Exception as e:
print(f"Error parsing '{sel_text}': {e}")import cssutils
from cssutils.css import SelectorList, Selector
# Create and manipulate selector list
selector_list = SelectorList()
# Add selectors
selector_list.appendSelector('h1')
selector_list.appendSelector('.title')
selector_list.appendSelector('#main-title')
print(f"Selector list: {selector_list.selectorText}")
print(f"Count: {len(selector_list)}")
# Insert selector
selector_list.insertSelector('h2', 1)
print(f"After insert: {selector_list.selectorText}")
# Remove selector
selector_list.removeSelector('.title')
print(f"After remove: {selector_list.selectorText}")
# Set entire list at once
selector_list.selectorText = 'article h1, article h2, article h3'
print(f"New list: {selector_list.selectorText}")
# Access specific selectors
for i, selector in enumerate(selector_list):
print(f"Selector {i}: {selector.selectorText} (specificity: {selector.specificity})")import cssutils
# CSS with various pseudo-classes and pseudo-elements
css = """
a:link { color: blue; }
a:visited { color: purple; }
a:hover, a:focus { color: red; }
input:required { border: 1px solid red; }
li:nth-child(odd) { background: #f0f0f0; }
p::first-letter { font-size: 2em; }
p::before { content: "→ "; }
::selection { background: yellow; }
"""
sheet = cssutils.parseString(css)
# Analyze pseudo-classes and pseudo-elements
for rule in sheet:
if rule.type == rule.STYLE_RULE:
selector_text = rule.selectorText
print(f"Selector: {selector_text}")
for selector in rule.selectorList:
specificity = selector.specificity
print(f" Specificity: {specificity}")
# Identify pseudo-classes vs pseudo-elements
if '::' in selector_text:
print(" Contains pseudo-elements")
elif ':' in selector_text:
print(" Contains pseudo-classes")Install with Tessl CLI
npx tessl i tessl/pypi-cssutils