1 | English | [π¨π³δΈζ](./README_zh-CN.md)
|
2 |
|
3 | # Vue CSS Modules
|
4 |
|
5 | [![Travis](https://img.shields.io/travis/fjc0k/vue-css-modules.svg)](https://travis-ci.org/fjc0k/vue-css-modules)
|
6 | [![minified size](https://img.shields.io/badge/minified%20size-2.14%20KB-blue.svg?MIN)](https://github.com/fjc0k/vue-css-modules/blob/master/dist/vue-css-modules.min.js)
|
7 | [![minzipped size](https://img.shields.io/badge/minzipped%20size-1.05%20KB-blue.svg?MZIP)](https://github.com/fjc0k/vue-css-modules/blob/master/dist/vue-css-modules.min.js)
|
8 |
|
9 | Seamless mapping of class names to CSS modules inside of Vue components.
|
10 |
|
11 | ```shell
|
12 | yarn add vue-css-modules
|
13 | ```
|
14 |
|
15 | CDN: [jsDelivr](//www.jsdelivr.com/package/npm/vue-css-modules) | [UNPKG](//unpkg.com/vue-css-modules/) (Avaliable as `window.VueCSSModules`)
|
16 |
|
17 | <img src="./assets/logo.png" width="150" height="150" />
|
18 |
|
19 | ## CSS Modules: local scope & modular
|
20 |
|
21 | [`CSS Modules`](https://github.com/css-modules/css-modules) assigns a local class a global unique name, so a component styles will not affect other components. e.g.
|
22 |
|
23 | ```css
|
24 | /* button.css */
|
25 | .button {
|
26 | font-size: 16px;
|
27 | }
|
28 | .mini {
|
29 | font-size: 12px;
|
30 | }
|
31 | ```
|
32 |
|
33 | It's will transformed to something similar to:
|
34 |
|
35 | ```css
|
36 | /* button.css */
|
37 | .button__button--d8fj3 {
|
38 | font-size: 16px;
|
39 | }
|
40 | .button__mini--f90jc {
|
41 | font-size: 12px;
|
42 | }
|
43 | ```
|
44 |
|
45 | When importing the CSS Module from a JS Module, it exports an object with all mappings from local names to global names. Just like this:
|
46 |
|
47 | ```javascript
|
48 | import styles from './button.css'
|
49 | // styles = {
|
50 | // button: 'button__button--d8fj3',
|
51 | // mini: 'button__mini--f90jc'
|
52 | // }
|
53 |
|
54 | element.innerHTML = '<button class="' + styles.button + ' ' + styles.mini + '" />'
|
55 | ```
|
56 |
|
57 | ## `vue-css-modules`: simplify mapping name
|
58 |
|
59 | Here's a button component with CSS Modules:
|
60 |
|
61 | ```html
|
62 | <template>
|
63 | <button :class="{
|
64 | 'global-button-class-name': true,
|
65 | [styles.button]: true,
|
66 | [styles.mini]: mini
|
67 | }">Click me</button>
|
68 | </template>
|
69 |
|
70 | <script>
|
71 | import styles from './button.css'
|
72 |
|
73 | export default {
|
74 | props: { mini: Boolean },
|
75 | data: () => ({ styles })
|
76 | }
|
77 | </script>
|
78 | ```
|
79 |
|
80 | Surely, CSS Modules is a good choice for Vue components. But here are a few disadvantages:
|
81 |
|
82 | - You have to pass `styles` object into `data` function.
|
83 | - You have to use `styles.localClassName` importing a global class name.
|
84 | - If there are other global class names, you have to put them together.
|
85 | - If you want to bind a class name to a component property value, you have to explicitly specify the property name, even if the class name is equals the property name.
|
86 |
|
87 | Now, you can use `vue-css-modules` to remake it:
|
88 |
|
89 | ```html
|
90 | <template>
|
91 | <button
|
92 | class="global-button-class-name"
|
93 | styleName="button :mini">
|
94 | Click me
|
95 | </button>
|
96 | </template>
|
97 |
|
98 | <script>
|
99 | import CSSModules from 'vue-css-modules'
|
100 | import styles from './button.css'
|
101 |
|
102 | export default {
|
103 | mixins: [CSSModules(styles)],
|
104 | props: { mini: Boolean }
|
105 | }
|
106 | </script>
|
107 | ```
|
108 |
|
109 | Using `vue-css-modules`:
|
110 |
|
111 | - You don't need pass `styles` object into `data` function, but the `CSSModules` mixin. π
|
112 | - You can completely say byebye to `styles.localClassName`.
|
113 | - There is clear distinction between global CSS and CSS Modules.
|
114 | - You can use the `:` modifier to bind the property with the same name.
|
115 |
|
116 | ## Modifiers
|
117 |
|
118 | ### @button
|
119 |
|
120 | ```html
|
121 | <button styleName="@button">Button</button>
|
122 | ```
|
123 |
|
124 | This is the equivalent to:
|
125 |
|
126 | ```html
|
127 | <button styleName="button" data-component-button="true">Button</button>
|
128 | ```
|
129 |
|
130 | This allows you to override component styles in context:
|
131 |
|
132 | ```css
|
133 | .form [data-component-button] {
|
134 | font-size: 20px;
|
135 | }
|
136 | ```
|
137 |
|
138 | ### $type
|
139 |
|
140 | ```html
|
141 | <button styleName="$type">Button</button>
|
142 | ```
|
143 |
|
144 | This is the equivalent to:
|
145 |
|
146 | ```html
|
147 | <button :styleName="type">Button</button>
|
148 | ```
|
149 |
|
150 | ### :mini
|
151 |
|
152 | ```html
|
153 | <button styleName=":mini">Button</button>
|
154 | ```
|
155 |
|
156 | This is the equivalent to:
|
157 |
|
158 | ```html
|
159 | <button :styleName="mini ? 'mini' : ''">Button</button>
|
160 | ```
|
161 |
|
162 | ### disabled=isDisabled
|
163 |
|
164 | ```html
|
165 | <button styleName="disabled=isDisabled">Button</button>
|
166 | ```
|
167 |
|
168 | This is the equivalent to:
|
169 |
|
170 | ```html
|
171 | <button :styleName="isDisabled ? 'disabled' : ''">Button</button>
|
172 | ```
|
173 |
|
174 | ## Usage
|
175 |
|
176 | ### In templates
|
177 |
|
178 | #### CSS Modules outside the template
|
179 |
|
180 | ```html
|
181 | <template>
|
182 | <button
|
183 | class="global-button-class-name"
|
184 | styleName="button :mini">
|
185 | Click me
|
186 | </button>
|
187 | </template>
|
188 |
|
189 | <script>
|
190 | import CSSModules from 'vue-css-modules'
|
191 | import styles from './button.css'
|
192 |
|
193 | export default {
|
194 | mixins: [CSSModules(styles)],
|
195 | props: { mini: Boolean }
|
196 | }
|
197 | </script>
|
198 | ```
|
199 |
|
200 | #### CSS Modules inside the template
|
201 |
|
202 | ```html
|
203 | <template>
|
204 | <button
|
205 | class="global-button-class-name"
|
206 | styleName="button :mini">
|
207 | Click me
|
208 | </button>
|
209 | </template>
|
210 |
|
211 | <script>
|
212 | import CSSModules from 'vue-css-modules'
|
213 |
|
214 | export default {
|
215 | mixins: [CSSModules()],
|
216 | props: { mini: Boolean }
|
217 | }
|
218 | </script>
|
219 |
|
220 | <style module>
|
221 | .button {
|
222 | font-size: 16px;
|
223 | }
|
224 | .mini {
|
225 | font-size: 12px;
|
226 | }
|
227 | </style>
|
228 | ```
|
229 |
|
230 | ### In JSX
|
231 |
|
232 | ```javascript
|
233 | import CSSModules from 'vue-css-modules'
|
234 | import styles from './button.css'
|
235 |
|
236 | export default {
|
237 | mixins: [CSSModules(styles)],
|
238 | props: { mini: Boolean },
|
239 | render() {
|
240 | return (
|
241 | <button styleName="@button :mini">Click me</button>
|
242 | )
|
243 | }
|
244 | }
|
245 | ```
|
246 |
|
247 | ### In render functions
|
248 |
|
249 | ```javascript
|
250 | import CSSModules from 'vue-css-modules'
|
251 | import styles from './button.css'
|
252 |
|
253 | export default {
|
254 | mixins: [CSSModules(styles)],
|
255 | props: { mini: Boolean },
|
256 | render(h) {
|
257 | return h('button', {
|
258 | styleName: '@button :mini'
|
259 | }, 'Click me')
|
260 | }
|
261 | }
|
262 | ```
|
263 |
|
264 | ## The implementation
|
265 |
|
266 | `vue-css-modules` extends `$createElement` method of the current component. It will use the value of `styleName` in `data` or `data.attrs` to look for CSS Modules in the associated styles object and will append the matching unique CSS class names to the `data.staticClass` value.
|