1 | # @erickmerchant/css
|
2 |
|
3 | When I write CSS, I like to write it as if each element will have just one class, and no other styles will apply to that element, except via inheritance. It's nice to look at a rule and see all the declarations that will be applied. I feel like this makes authoring easier, at least for me. To avoid copy-pasting, concatenation can be used.
|
4 |
|
5 | In contrast to authoring, the most ideal way to ship CSS to browsers is with little to no duplication. Something as close to atomic or functional as possible. Without this optimization, compression will help, but my CSS is still bigger than it needs to be.
|
6 |
|
7 | This project aims to combine those two ideals. The CLI takes a single ES module entry point, and outputs a single CSS file and a generated ES module that has a map of keys to the generated class names in the css file.
|
8 |
|
9 | ## Example
|
10 |
|
11 | ```javascript
|
12 | // input.js
|
13 | const desktop = '@media (min-width: 100px)'
|
14 |
|
15 | // some styles for reuse. font-weight normal is removed because it's overridden
|
16 | const emphasis = `
|
17 | font-weight: normal;
|
18 | font-weight: bold;
|
19 | `
|
20 |
|
21 | // these styles are tacked onto the beginning of output.css unmodified
|
22 | export const _start = `
|
23 | p {
|
24 | margin-top: var(--spacing)
|
25 | }
|
26 | `
|
27 |
|
28 | // these are the identifiers (class like) that we'll use later in app.js
|
29 | export const styles = {
|
30 | loud: `
|
31 | ${emphasis}
|
32 |
|
33 | ${desktop} {
|
34 | font-size: 5em;
|
35 |
|
36 | ::after {
|
37 | content: '!!'
|
38 | }
|
39 | }
|
40 | ::after {
|
41 | content: '!'
|
42 | }
|
43 | `,
|
44 | button: `
|
45 | ${emphasis}
|
46 |
|
47 | background: #ff8000;
|
48 | color: #111;
|
49 | `
|
50 | }
|
51 | ```
|
52 |
|
53 | ```css
|
54 | /* output.css */
|
55 | p {
|
56 | margin-top: var(--spacing);
|
57 | }
|
58 |
|
59 | .a {
|
60 | font-weight: bold;
|
61 | }
|
62 | .b {
|
63 | background: #ff8000;
|
64 | color: #111;
|
65 | }
|
66 | .c::after {
|
67 | content: '!';
|
68 | }
|
69 | @media (min-width: 100px) {
|
70 | .c {
|
71 | font-size: 5em;
|
72 | }
|
73 | .c::after {
|
74 | content: '!!';
|
75 | }
|
76 | }
|
77 | ```
|
78 |
|
79 | ```javascript
|
80 | // output.js
|
81 | export const classes = {
|
82 | loud: 'a c',
|
83 | button: 'a b'
|
84 | }
|
85 | ```
|
86 |
|
87 | ```javascript
|
88 | // app.js
|
89 | import {classes} from './output.js'
|
90 |
|
91 | classes.loud // 'a c'
|
92 |
|
93 | classes.button // 'a b'
|
94 | ```
|
95 |
|
96 | ## Usage
|
97 |
|
98 | build once
|
99 |
|
100 | ```
|
101 | npx @erickmerchant/css input.js -o output
|
102 | ```
|
103 |
|
104 | watch for changes
|
105 |
|
106 | ```
|
107 | npx @erickmerchant/css -w input.js -o output
|
108 | ```
|
109 |
|
110 | > ⚠️ As your CSS grows this will likely not scale at the moment, but since there is no browser runtime except for the map of classes this may not be a big deal to you.
|