0
# Encoding and Optimization
1
2
PostCSS URL provides advanced encoding capabilities with automatic MIME type detection, SVG optimization, and multiple encoding strategies for optimal file size and browser compatibility.
3
4
## Capabilities
5
6
### Automatic MIME Type Detection
7
8
The plugin automatically detects file types using the `mime` package and selects appropriate encoding strategies.
9
10
```javascript { .api }
11
/**
12
* File interface with MIME type detection
13
*/
14
interface File {
15
/** Absolute path to the asset file */
16
path: string;
17
/** File contents as Buffer */
18
contents: Buffer;
19
/** MIME type detected from file extension */
20
mimeType: string;
21
}
22
23
interface MimeTypeHandling {
24
/** Automatically detected MIME types */
25
detection: 'mime.getType(filePath)';
26
/** Default encoding per type */
27
defaults: {
28
'image/svg+xml': 'encodeURIComponent';
29
'image/png': 'base64';
30
'image/jpeg': 'base64';
31
'image/gif': 'base64';
32
'image/webp': 'base64';
33
[key: string]: 'base64' | 'encodeURI' | 'encodeURIComponent';
34
};
35
}
36
```
37
38
**Usage Example:**
39
40
```javascript
41
const postcss = require('postcss');
42
const postcssUrl = require('postcss-url');
43
44
// MIME type automatically detected from file extension
45
const result = await postcss()
46
.use(postcssUrl({
47
url: 'inline'
48
// SVG files: encodeURIComponent (default)
49
// PNG/JPG/GIF: base64 (default)
50
// Override with encodeType option if needed
51
}))
52
.process(css, { from: 'src/main.css', to: 'dist/main.css' });
53
```
54
55
### Encoding Types
56
57
Three encoding strategies available for converting files to data URIs with different characteristics.
58
59
```javascript { .api }
60
/**
61
* Available encoding types for inline mode
62
*/
63
type EncodeType = 'base64' | 'encodeURI' | 'encodeURIComponent';
64
65
interface EncodingCharacteristics {
66
base64: {
67
/** Universal browser support */
68
compatibility: 'all browsers';
69
/** ~33% larger than original file */
70
sizeIncrease: '33%';
71
/** Best for binary files (images, fonts) */
72
useCases: 'binary files';
73
};
74
encodeURI: {
75
/** Good browser support */
76
compatibility: 'modern browsers';
77
/** Smaller than base64 for text files */
78
sizeIncrease: 'varies';
79
/** Best for text-based files */
80
useCases: 'text files like SVG';
81
};
82
encodeURIComponent: {
83
/** Good browser support */
84
compatibility: 'modern browsers';
85
/** More encoding than encodeURI */
86
sizeIncrease: 'varies';
87
/** Safest for complex content */
88
useCases: 'complex SVG files';
89
};
90
}
91
```
92
93
**Encoding Comparison Example:**
94
95
```javascript
96
// Base64 encoding (default for images)
97
const base64Result = await postcss()
98
.use(postcssUrl({
99
url: 'inline',
100
encodeType: 'base64'
101
}))
102
.process(css, { from: 'src/main.css', to: 'dist/main.css' });
103
// Result: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...
104
105
// URI Component encoding (default for SVG)
106
const uriResult = await postcss()
107
.use(postcssUrl({
108
url: 'inline',
109
encodeType: 'encodeURIComponent'
110
}))
111
.process(css, { from: 'src/main.css', to: 'dist/main.css' });
112
// Result: data:image/svg+xml,%3Csvg xmlns%3D%22http%3A//www.w3.org...
113
114
// URI encoding (less aggressive than encodeURIComponent)
115
const simpleUriResult = await postcss()
116
.use(postcssUrl({
117
url: 'inline',
118
encodeType: 'encodeURI'
119
}))
120
.process(css, { from: 'src/main.css', to: 'dist/main.css' });
121
// Result: data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org...
122
```
123
124
### SVG Optimization
125
126
Advanced SVG encoding optimization reduces file size while maintaining compatibility with IE9+ and Android 3+.
127
128
```javascript { .api }
129
/**
130
* SVG optimization configuration
131
*/
132
interface SvgOptimization {
133
/** Enable optimized SVG encoding */
134
optimizeSvgEncode: boolean;
135
/** Optimization techniques applied */
136
techniques: {
137
/** Replace common encoded characters with literals */
138
literalReplacement: '%3D → =, %3A → :, %2F → /, etc.';
139
/** Convert hex escapes to lowercase for better gzip */
140
lowercaseHex: '%2C → %2c';
141
/** Remove newlines from SVG content */
142
newlineRemoval: 'automatic';
143
/** Replace %20 with spaces */
144
spaceOptimization: '%20 → space';
145
/** Properly encode hash characters */
146
hashEncoding: '# → %23';
147
};
148
}
149
```
150
151
**SVG Optimization Example:**
152
153
```javascript
154
// Optimized SVG inlining
155
const optimizedResult = await postcss()
156
.use(postcssUrl({
157
url: 'inline',
158
encodeType: 'encodeURIComponent',
159
optimizeSvgEncode: true // Enable SVG optimizations
160
}))
161
.process(css, { from: 'src/main.css', to: 'dist/main.css' });
162
163
// Without optimization:
164
// data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E
165
166
// With optimization:
167
// data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg"%3E
168
```
169
170
**Optimization Algorithm Details:**
171
172
```javascript
173
// Internal optimization process (from encode.js)
174
const optimizationSteps = {
175
1: 'encodeURIComponent(svgContent)',
176
2: 'replace common encoded chars: %3D→=, %3A→:, %2F→/, %22→\', %2C→,, %3B→;',
177
3: 'lowercase hex escapes: %2C → %2c for better gzip compression',
178
4: 'remove newlines from content',
179
5: 'replace %20 with spaces',
180
6: 'encode # as %23 for URL safety'
181
};
182
```
183
184
### URI Fragment Handling
185
186
Special handling for SVG files with fragment identifiers (hash links) in URLs.
187
188
```javascript { .api }
189
/**
190
* URI fragment handling options
191
*/
192
interface FragmentHandling {
193
/** Include fragment in inlined data URI */
194
includeUriFragment: boolean;
195
/** Suppress warnings about SVG fragments */
196
ignoreFragmentWarning: boolean;
197
/** Fragment behavior */
198
behavior: {
199
/** With includeUriFragment: true */
200
included: 'data:image/svg+xml,...#fragment';
201
/** With includeUriFragment: false (default) */
202
excluded: 'data:image/svg+xml,...';
203
/** Warning message for SVG fragments */
204
warning: 'Image type is svg and link contains #. Postcss-url cant handle svg fragments. SVG file fully inlined.';
205
};
206
}
207
```
208
209
**Fragment Handling Examples:**
210
211
```javascript
212
// Default behavior - fragments ignored with warning
213
const defaultResult = await postcss()
214
.use(postcssUrl({
215
url: 'inline'
216
// includeUriFragment: false (default)
217
// ignoreFragmentWarning: false (default)
218
}))
219
.process(`background: url('icon.svg#circle');`, {
220
from: 'src/main.css',
221
to: 'dist/main.css'
222
});
223
// Warning: "Image type is svg and link contains #..."
224
// Result: background: url('data:image/svg+xml,...'); // Fragment removed
225
226
// Include fragments in data URI
227
const fragmentResult = await postcss()
228
.use(postcssUrl({
229
url: 'inline',
230
includeUriFragment: true
231
}))
232
.process(`background: url('icon.svg#circle');`, {
233
from: 'src/main.css',
234
to: 'dist/main.css'
235
});
236
// Result: background: url('data:image/svg+xml,...#circle'); // Fragment preserved
237
238
// Suppress fragment warnings
239
const quietResult = await postcss()
240
.use(postcssUrl({
241
url: 'inline',
242
ignoreFragmentWarning: true
243
}))
244
.process(`background: url('icon.svg#circle');`, {
245
from: 'src/main.css',
246
to: 'dist/main.css'
247
});
248
// No warning issued, fragment still removed
249
```
250
251
### Quote Handling
252
253
Automatic quote management for percent-encoded SVG URIs to ensure proper CSS syntax.
254
255
```javascript { .api }
256
/**
257
* Automatic quote handling for encoded URIs
258
*/
259
interface QuoteHandling {
260
/** Automatic quote detection and wrapping */
261
behavior: {
262
/** SVG with encodeURIComponent gets wrapped in quotes */
263
svgEncoded: '"data:image/svg+xml,%3Csvg..."';
264
/** Base64 encoded files don't get quotes */
265
base64: 'data:image/png;base64,iVBORw0...';
266
/** Quote preservation from original URL */
267
preservation: 'maintains existing quote style when possible';
268
};
269
}
270
```
271
272
**Quote Handling Example:**
273
274
```javascript
275
// Automatic quote wrapping for encoded SVG
276
const result = await postcss()
277
.use(postcssUrl({
278
url: 'inline',
279
encodeType: 'encodeURIComponent'
280
}))
281
.process(`background: url(icon.svg);`, { // No quotes in source
282
from: 'src/main.css',
283
to: 'dist/main.css'
284
});
285
// Result: background: url("data:image/svg+xml,%3Csvg..."); // Quotes added
286
287
// Base64 doesn't get automatic quotes
288
const base64Result = await postcss()
289
.use(postcssUrl({
290
url: 'inline',
291
encodeType: 'base64'
292
}))
293
.process(`background: url(image.png);`, { // No quotes in source
294
from: 'src/main.css',
295
to: 'dist/main.css'
296
});
297
// Result: background: url(data:image/png;base64,iVBOR...); // No quotes added
298
```
299
300
## Error Handling
301
302
Encoding process includes comprehensive error handling for missing files, invalid MIME types, and encoding failures.
303
304
```javascript { .api }
305
/**
306
* Encoding error handling
307
*/
308
interface EncodingErrors {
309
/** Missing file handling */
310
missingFile: 'warn and skip processing';
311
/** Invalid MIME type handling */
312
invalidMimeType: 'warn and skip processing';
313
/** Encoding failure handling */
314
encodingFailure: 'fallback to specified fallback mode';
315
/** Size limit exceeded */
316
sizeExceeded: 'fallback to specified fallback mode';
317
}
318
```
319
320
**Error Handling Examples:**
321
322
```javascript
323
// Missing file with fallback
324
const result = await postcss()
325
.use(postcssUrl({
326
url: 'inline',
327
fallback: 'rebase' // Fallback when file not found
328
}))
329
.process(`background: url('missing.png');`, {
330
from: 'src/main.css',
331
to: 'dist/main.css'
332
});
333
// Warning: "Can't read file 'missing.png', ignoring"
334
// Falls back to rebase mode
335
336
// Size limit with fallback
337
const sizeResult = await postcss()
338
.use(postcssUrl({
339
url: 'inline',
340
maxSize: 1, // 1KB limit
341
fallback: 'copy'
342
}))
343
.process(`background: url('large-image.png');`, {
344
from: 'src/main.css',
345
to: 'dist/main.css'
346
});
347
// Large file automatically uses copy mode instead of inline
348
```