Minify selectors with PostCSS.
npx @tessl/cli install tessl/npm-postcss-minify-selectors@7.0.00
# PostCSS Minify Selectors
1
2
PostCSS Minify Selectors is a PostCSS plugin that optimizes CSS selectors by removing unnecessary parts, normalizing whitespace, and applying various minification rules. It helps reduce CSS bundle sizes by cleaning up selector syntax while maintaining functionality.
3
4
## Package Information
5
6
- **Package Name**: postcss-minify-selectors
7
- **Package Type**: npm
8
- **Language**: JavaScript (with TypeScript definitions)
9
- **Installation**: `npm install postcss-minify-selectors`
10
11
## Core Imports
12
13
```javascript
14
const postcssMinifySelectors = require("postcss-minify-selectors");
15
```
16
17
For ESM:
18
19
```javascript
20
import postcssMinifySelectors from "postcss-minify-selectors";
21
```
22
23
## Basic Usage
24
25
```javascript
26
const postcss = require("postcss");
27
const postcssMinifySelectors = require("postcss-minify-selectors");
28
29
// Basic usage with default options
30
const result = await postcss([
31
postcssMinifySelectors()
32
]).process(css, { from: undefined });
33
34
// With custom options
35
const result = await postcss([
36
postcssMinifySelectors({ sort: false })
37
]).process(css, { from: undefined });
38
```
39
40
Input CSS:
41
```css
42
h1 + p, h2, h3, h2{color:blue}
43
*#id, *.class, *[href]{background:red}
44
::before, ::after{content:""}
45
:nth-child(1), :nth-child(2n+1){font-weight:bold}
46
[ class= "test" ], [title="*.js"]{border:1px solid red}
47
```
48
49
Output CSS:
50
```css
51
h1+p,h2,h3{color:blue}
52
#id,.class,[href]{background:red}
53
:before,:after{content:""}
54
:first-child,:nth-child(odd){font-weight:bold}
55
[class=test],[title="*.js"]{border:1px solid red}
56
```
57
58
## Capabilities
59
60
### Plugin Creator Function
61
62
Creates a PostCSS plugin instance with optional configuration.
63
64
```javascript { .api }
65
/**
66
* Creates a PostCSS plugin for minifying selectors
67
* @param {Options} opts - Optional configuration object
68
* @returns {Plugin} PostCSS plugin instance
69
*/
70
function postcssMinifySelectors(opts?: Options): Plugin;
71
```
72
73
**Parameters:**
74
- `opts` (optional): Configuration options object
75
76
**Returns:**
77
- PostCSS plugin object with `postcssPlugin` property and `OnceExit` method
78
79
### Plugin Options
80
81
Configuration options for controlling selector minification behavior.
82
83
```javascript { .api }
84
interface Options {
85
/** Whether to sort selectors alphabetically (default: true) */
86
sort?: boolean;
87
}
88
```
89
90
**Properties:**
91
- `sort` (optional): Boolean flag to enable/disable selector sorting. Default: `true`
92
93
### Plugin Properties
94
95
The plugin function includes PostCSS compatibility indicators.
96
97
```javascript { .api }
98
/** Indicates PostCSS plugin compatibility */
99
postcssMinifySelectors.postcss: true;
100
```
101
102
## Selector Optimizations
103
104
The plugin applies the following optimizations:
105
106
### Universal Selector Removal
107
Removes qualified universal selectors where they are redundant:
108
- `*#id` → `#id`
109
- `*.class` → `.class`
110
- `*[href]` → `[href]`
111
- `*:not(.green)` → `:not(.green)`
112
113
### Whitespace Normalization
114
Normalizes whitespace around selectors and combinators:
115
- `h1, h2, h3` → `h1,h2,h3`
116
- `h1 + p` → `h1+p`
117
- `h1 p` → `h1 p`
118
119
### Attribute Selector Optimization
120
Optimizes attribute selectors by:
121
122
**Quote removal and normalization:**
123
- Removing unnecessary quotes when safe: `[class="woop_woop_woop"]` → `[class=woop_woop_woop]`
124
- Preserving quotes for complex values: `[class*=" icon-"]` (spaces), `[data-attr~="key1=1"]` (equals signs)
125
- Preserving quotes for empty values: `[title=""]` and single hyphens: `[title="-"]`
126
127
**Space and formatting normalization:**
128
- Trimming excess whitespace: `[ color= "blue" ]` → `[color=blue]`
129
- Normalizing line breaks: `[class="woop \\
130
woop woop"]` → `[class="woop woop woop"]`
131
- Operator spacing: removes spaces around `=`, `~=`, `|=`, `^=`, `$=`, `*=`
132
133
**Case-insensitive flag handling:**
134
- Proper spacing: `[color="blue" i ]` → `[color=blue i]`
135
- Preserves the case-insensitive flag with correct spacing
136
137
**Attribute name trimming:**
138
- Normalizes attribute names: removes leading/trailing spaces
139
140
### Pseudo-selector Optimization
141
Optimizes pseudo-selectors by:
142
143
**nth-child/nth-of-type conversions:**
144
- Converting `nth-child(1)` → `:first-child`
145
- Converting `nth-last-child(1)` → `:last-child`
146
- Converting `nth-of-type(1)` → `:first-of-type`
147
- Converting `nth-last-of-type(1)` → `:last-of-type`
148
- Converting `even` → `2n` in nth-child expressions
149
- Converting `2n+1` → `odd` in nth-child expressions
150
- Case insensitive: `:NTH-CHILD(1)` → `:first-child`
151
- Space normalization: `:nth-last-of-type(2n + 2)` → `:nth-last-of-type(2n+2)`
152
153
**Double-colon to single-colon conversion for backward compatibility:**
154
- `::before` → `:before`
155
- `::after` → `:after`
156
- `::first-letter` → `:first-letter`
157
- `::first-line` → `:first-line`
158
- Case preservation: `::BEFORE` → `:BEFORE`
159
160
**:not() pseudo-class optimizations:**
161
- Whitespace trimming: `:not(.article, .comments)` → `:not(.article,.comments)`
162
- Deduplication inside :not(): `:not(h2, h3, h4, h5, h5, h6)` → `:not(h2,h3,h4,h5,h6)`
163
- Universal selector removal: `:not( *[href="foo"] )` → `:not([href=foo])`
164
165
### Keyframe Selector Optimization
166
Optimizes keyframe selectors:
167
- `from` → `0%`
168
- `100%` → `to` (when used alone)
169
- Case insensitive: `FROM` → `0%`
170
- Preserves complex keyframe selectors like `entry 100%` (won't convert to `entry to`)
171
172
### Duplicate Removal
173
Removes duplicate selectors within the same rule.
174
175
### Selector Sorting
176
When enabled (default), sorts selectors alphabetically for consistency.
177
178
### Safety Features and Edge Cases
179
The plugin includes comprehensive safety measures to ensure optimizations don't break functionality:
180
181
**String boundary preservation:**
182
- Never modifies content within quoted strings in attribute values
183
- Preserves complex attribute values containing CSS selectors, keywords, or special characters
184
- Handles both single and double quoted strings properly
185
186
**Comment handling:**
187
- Maintains CSS comments while optimizing around them
188
- Preserves the universal selector between comments: `/*comment*/*/*comment*/`
189
190
**Framework compatibility:**
191
- **Polymer mixins**: Handles CSS custom property mixins like `--my-toolbar-theme:{color:blue};`
192
- **Escaped sequences**: Preserves escaped zero plus sequences like `.\\31 0\\+`
193
- **Namespace selectors**: Properly handles `[foo|bar]`, `[*|att]`, `[|att]`
194
- **Unicode characters**: Preserves special characters like `½`
195
196
**Context-aware optimization:**
197
- Distinguishes between actual duplicates and similar-looking but semantically different selectors
198
- Preserves meaningful universal selectors in specific contexts (combinators, etc.)
199
- Smart handling of file glob patterns: `[glob="/**/*.js"]` (preserved)
200
- Preserves qualified universals in attribute values: `[class=" *.js "]`
201
202
**Mixin compatibility:**
203
- Skips selectors ending with `:` (likely custom mixins)
204
- Compatible with other PostCSS plugins and their generated selectors
205
206
## Usage Examples
207
208
### Disable Sorting
209
210
```javascript
211
const postcss = require("postcss");
212
const postcssMinifySelectors = require("postcss-minify-selectors");
213
214
const result = await postcss([
215
postcssMinifySelectors({ sort: false })
216
]).process(css, { from: undefined });
217
```
218
219
### Integration with PostCSS Config
220
221
```javascript
222
// postcss.config.js
223
module.exports = {
224
plugins: [
225
require("postcss-minify-selectors")({
226
sort: true
227
})
228
]
229
};
230
```
231
232
### Use with cssnano
233
234
This plugin is part of the cssnano preset but can be used independently:
235
236
```javascript
237
const postcss = require("postcss");
238
const postcssMinifySelectors = require("postcss-minify-selectors");
239
240
const result = await postcss([
241
postcssMinifySelectors(),
242
// other plugins...
243
]).process(css, { from: undefined });
244
```
245
246
## Types
247
248
```typescript { .api }
249
interface Options {
250
/** Whether to sort selectors alphabetically (default: true) */
251
sort?: boolean;
252
}
253
254
interface Plugin {
255
/** PostCSS plugin identifier */
256
postcssPlugin: string;
257
/** Main processing method called once after all rules are processed */
258
OnceExit(css: Root): void;
259
}
260
261
interface Root {
262
/** Walk through all rules in the CSS */
263
walkRules(callback: (rule: Rule) => void): void;
264
}
265
266
interface Rule {
267
/** The selector string */
268
selector: string;
269
/** Raw selector information */
270
raws: {
271
selector?: {
272
value: string;
273
raw: string;
274
};
275
};
276
}
277
```
278
279
## Dependencies
280
281
The plugin relies on these external packages:
282
- `postcss-selector-parser`: For parsing and manipulating CSS selectors
283
- `cssesc`: For CSS string escaping utilities