0
# CSS Selectors
1
2
Parse, validate, and manipulate CSS selectors with support for CSS3 selector syntax, pseudo-classes, pseudo-elements, and specificity calculations.
3
4
## Capabilities
5
6
### Selector Class
7
8
Individual CSS selector with parsing, validation, and specificity calculation.
9
10
```python { .api }
11
class Selector:
12
"""
13
Individual CSS selector implementing cssutils selector interface.
14
"""
15
16
# Properties
17
selectorText: str # Complete selector text
18
specificity: tuple # Specificity as (a, b, c, d) tuple
19
20
# Methods
21
@property
22
def selectorText():
23
"""Get/set selector text"""
24
25
@selectorText.setter
26
def selectorText(selectorText):
27
"""
28
Set selector text with parsing and validation.
29
30
Parameters:
31
- selectorText (str): CSS selector text
32
"""
33
34
@property
35
def specificity():
36
"""
37
Get selector specificity as (a, b, c, d) tuple.
38
39
Returns:
40
tuple: Specificity where:
41
- a: inline styles (always 0 for selectors)
42
- b: IDs
43
- c: classes, attributes, pseudo-classes
44
- d: elements, pseudo-elements
45
"""
46
47
def __str__():
48
"""String representation of selector"""
49
50
def __repr__():
51
"""Debug representation of selector"""
52
```
53
54
### SelectorList Class
55
56
Collection of CSS selectors (comma-separated selector group).
57
58
```python { .api }
59
class SelectorList:
60
"""
61
List of CSS selectors implementing cssutils SelectorList interface.
62
"""
63
64
# Properties
65
selectorText: str # Complete selector list text (comma-separated)
66
length: int # Number of selectors in list
67
68
# Access Methods
69
def item(index):
70
"""
71
Get selector at specified index.
72
73
Parameters:
74
- index (int): Selector index (0-based)
75
76
Returns:
77
Selector: Selector at index, or None if out of bounds
78
"""
79
80
def __getitem__(index):
81
"""Get selector by index using bracket notation"""
82
83
def __len__():
84
"""Get number of selectors"""
85
86
def __iter__():
87
"""Iterator over selectors"""
88
89
# Modification Methods
90
def appendSelector(selector):
91
"""
92
Add selector to end of list.
93
94
Parameters:
95
- selector (str/Selector): Selector to add
96
"""
97
98
def insertSelector(selector, index):
99
"""
100
Insert selector at specified index.
101
102
Parameters:
103
- selector (str/Selector): Selector to insert
104
- index (int): Position to insert
105
"""
106
107
def removeSelector(selector):
108
"""
109
Remove selector from list.
110
111
Parameters:
112
- selector (str/Selector): Selector to remove
113
"""
114
115
# Properties
116
@property
117
def selectorText():
118
"""Get/set complete selector list text"""
119
120
@selectorText.setter
121
def selectorText(selectorText):
122
"""
123
Set selector list text with parsing.
124
125
Parameters:
126
- selectorText (str): Comma-separated selector list
127
"""
128
```
129
130
## Usage Examples
131
132
### Basic Selector Operations
133
134
```python
135
import cssutils
136
from cssutils.css import Selector, SelectorList
137
138
# Parse individual selector
139
selector = Selector()
140
selector.selectorText = 'div.container > p:first-child'
141
print(f"Selector: {selector.selectorText}")
142
print(f"Specificity: {selector.specificity}")
143
144
# Parse selector list
145
selector_list = SelectorList()
146
selector_list.selectorText = 'h1, h2, h3.important'
147
print(f"Number of selectors: {len(selector_list)}")
148
149
# Access individual selectors
150
for i, sel in enumerate(selector_list):
151
print(f"Selector {i}: {sel.selectorText} (specificity: {sel.specificity})")
152
```
153
154
### Working with CSS Rules and Selectors
155
156
```python
157
import cssutils
158
159
# Parse CSS with various selectors
160
css = """
161
body { margin: 0; }
162
#header { background: blue; }
163
.nav li a:hover { color: red; }
164
div > p:first-child { font-weight: bold; }
165
h1, h2, h3 { font-family: Arial; }
166
"""
167
168
sheet = cssutils.parseString(css)
169
170
# Examine selectors in style rules
171
for rule in sheet:
172
if rule.type == rule.STYLE_RULE:
173
print(f"Rule: {rule.selectorText}")
174
175
# Access selector list
176
selector_list = rule.selectorList
177
print(f" Number of selectors: {len(selector_list)}")
178
179
# Access individual selectors
180
for selector in selector_list:
181
print(f" Selector: {selector.selectorText}")
182
print(f" Specificity: {selector.specificity}")
183
```
184
185
### Specificity Calculations
186
187
```python
188
import cssutils
189
from cssutils.css import Selector
190
191
# Test different selector specificities
192
selectors = [
193
'*', # (0,0,0,1) - universal
194
'div', # (0,0,0,1) - element
195
'div p', # (0,0,0,2) - elements
196
'.class', # (0,0,1,0) - class
197
'div.class', # (0,0,1,1) - element + class
198
'#id', # (0,1,0,0) - ID
199
'#id.class', # (0,1,1,0) - ID + class
200
'div#id.class', # (0,1,1,1) - element + ID + class
201
'div > p.highlight', # (0,0,1,2) - elements + class
202
'a:hover', # (0,0,1,1) - element + pseudo-class
203
'a::before', # (0,0,0,2) - element + pseudo-element
204
'[type="text"]', # (0,0,1,0) - attribute
205
'div[class~="nav"]', # (0,0,1,1) - element + attribute
206
]
207
208
for sel_text in selectors:
209
selector = Selector()
210
selector.selectorText = sel_text
211
print(f"{sel_text:20} -> {selector.specificity}")
212
```
213
214
### Modifying Selectors
215
216
```python
217
import cssutils
218
219
# Parse stylesheet
220
css = """
221
.old-class { color: red; }
222
div.container { margin: 20px; }
223
"""
224
225
sheet = cssutils.parseString(css)
226
227
# Modify selectors
228
for rule in sheet:
229
if rule.type == rule.STYLE_RULE:
230
old_selector = rule.selectorText
231
232
# Replace class name
233
if '.old-class' in rule.selectorText:
234
rule.selectorText = rule.selectorText.replace('.old-class', '.new-class')
235
print(f"Changed: {old_selector} -> {rule.selectorText}")
236
237
# Add additional selector
238
elif rule.selectorText == 'div.container':
239
rule.selectorText = 'div.container, section.container'
240
print(f"Extended: {old_selector} -> {rule.selectorText}")
241
242
print(sheet.cssText)
243
```
244
245
### Complex Selector Parsing
246
247
```python
248
import cssutils
249
from cssutils.css import SelectorList
250
251
# Complex selectors with various CSS3 features
252
complex_selectors = [
253
'input[type="email"]:valid',
254
'article > section:nth-child(2n+1)',
255
'nav ul li:not(.active)',
256
'div.content ~ aside',
257
'h2 + p::first-line',
258
'table tbody tr:nth-last-child(-n+3)',
259
'.sidebar a:matches([href^="http"],[href^="mailto"])',
260
]
261
262
for sel_text in complex_selectors:
263
try:
264
selector_list = SelectorList()
265
selector_list.selectorText = sel_text
266
267
print(f"Parsed: {sel_text}")
268
for selector in selector_list:
269
print(f" Specificity: {selector.specificity}")
270
except Exception as e:
271
print(f"Error parsing '{sel_text}': {e}")
272
```
273
274
### Selector List Manipulation
275
276
```python
277
import cssutils
278
from cssutils.css import SelectorList, Selector
279
280
# Create and manipulate selector list
281
selector_list = SelectorList()
282
283
# Add selectors
284
selector_list.appendSelector('h1')
285
selector_list.appendSelector('.title')
286
selector_list.appendSelector('#main-title')
287
288
print(f"Selector list: {selector_list.selectorText}")
289
print(f"Count: {len(selector_list)}")
290
291
# Insert selector
292
selector_list.insertSelector('h2', 1)
293
print(f"After insert: {selector_list.selectorText}")
294
295
# Remove selector
296
selector_list.removeSelector('.title')
297
print(f"After remove: {selector_list.selectorText}")
298
299
# Set entire list at once
300
selector_list.selectorText = 'article h1, article h2, article h3'
301
print(f"New list: {selector_list.selectorText}")
302
303
# Access specific selectors
304
for i, selector in enumerate(selector_list):
305
print(f"Selector {i}: {selector.selectorText} (specificity: {selector.specificity})")
306
```
307
308
### Pseudo-class and Pseudo-element Handling
309
310
```python
311
import cssutils
312
313
# CSS with various pseudo-classes and pseudo-elements
314
css = """
315
a:link { color: blue; }
316
a:visited { color: purple; }
317
a:hover, a:focus { color: red; }
318
input:required { border: 1px solid red; }
319
li:nth-child(odd) { background: #f0f0f0; }
320
p::first-letter { font-size: 2em; }
321
p::before { content: "→ "; }
322
::selection { background: yellow; }
323
"""
324
325
sheet = cssutils.parseString(css)
326
327
# Analyze pseudo-classes and pseudo-elements
328
for rule in sheet:
329
if rule.type == rule.STYLE_RULE:
330
selector_text = rule.selectorText
331
print(f"Selector: {selector_text}")
332
333
for selector in rule.selectorList:
334
specificity = selector.specificity
335
print(f" Specificity: {specificity}")
336
337
# Identify pseudo-classes vs pseudo-elements
338
if '::' in selector_text:
339
print(" Contains pseudo-elements")
340
elif ':' in selector_text:
341
print(" Contains pseudo-classes")
342
```