Vue CSS Modules

CSS Modules: Local scope & modularity

CSS Modules gives each local class a globally unique class name so that component styles don’t affect each other. Such as:

/* button.css */
.button {
  font-size: 16px;
}
.mini {
  font-size: 12px;
}
Copy the code

It will be converted to something like this:

/* button.css */
.button__button--d8fj3 {
  font-size: 16px;
}
.button__mini--f90jc {
  font-size: 12px;
}
Copy the code

When importing a CSS module file, it gives us a mapping object from local class names to global class names. Something like this:

import styles from './button.css'
// styles = {
// button: 'button__button--d8fj3',
// mini: 'button__mini--f90jc'
// }

element.innerHTML = '<button class="' + styles.button + ' ' + styles.mini + '" / >'
Copy the code

vue-css-modules: Simplified class name mapping

Here is a button component that uses CSS Modules:

<template>
  <button :class="{ 'global-button-class-name': true, [styles.button]: true, [styles.mini]: mini }">Am I</button>
</template>

<script>
  import styles from './button.css'

  export default {
    props: { mini: Boolean },
    data: (a)= > ({ styles })
  }
</script>
Copy the code

Indeed, CSS Modules are a good choice for Vue components. However, there are also the following shortcomings:

  • You must be indataThe incomingstyles
  • You have to usestyles.localClassNameImport the global class name
  • If there are other global class names, you must put them together
  • If you want to bind to a component’s property value, specify it explicitly, even if the local class name is the same as the property name

For the button component above, use vue-CSS-modules:

<template>
  <button
    class="global-button-class-name"
    styleName="button :mini">Am I</button>
</template>

<script>
  import CSSModules from 'vue-css-modules'
  import styles from './button.css'

  export default {
    mixins: [CSSModules(styles)],
    props: { mini: Boolean}}</script>
Copy the code

Now:

  • You don’t have to be indataThe incomingstyles, but have to be inmixinsThe incomingstyles 🌝
  • You can tellstyles.localClassNameSay goodbye
  • Place the local class name instyleNameProperty, the global class name is placed inclassProperties, a lot of neat
  • The local class name binds to the component’s property of the same name and is simply preceded by it:The modifier

The modifier

@button

<button styleName="@button">button</button>
Copy the code

This is equivalent to:

<button styleName="button" data-component-button="true">button</button>
Copy the code

This allows you to restyle components externally:

.form [data-component-button] {
  font-size: 20px;
}
Copy the code

$type

<button styleName="$type">button</button>
Copy the code

This is equivalent to:

<button :styleName="type">button</button>
Copy the code

:mini

<button styleName=":mini">button</button>
Copy the code

This is equivalent to:

<button :styleName="mini ? 'mini' : ''">button</button>
Copy the code

disabled=isDisabled

<button styleName="disabled=isDisabled">button</button>
Copy the code

This is equivalent to:

<button :styleName="isDisabled ? 'disabled' : ''">button</button>
Copy the code

Method of use

Used in Vue templates

Import CSS modules outside the template

<template>
  <button
    class="global-button-class-name"
    styleName="button :mini">Am I</button>
</template>

<script>
  import CSSModules from 'vue-css-modules'
  import styles from './button.css'

  export default {
    mixins: [CSSModules(styles)],
    props: { mini: Boolean}}</script>
Copy the code

Use the CSS module inside the template

<template>
  <button
    class="global-button-class-name"
    styleName="button :mini">Am I</button>
</template>

<script>
  import CSSModules from 'vue-css-modules'

  export default {
    mixins: [CSSModules()],
    props: { mini: Boolean}}</script>

<style module>
  .button {
    font-size: 16px;
  }
  .mini {
    font-size: 12px;
  }
</style>
Copy the code

Used in Vue JSX

import CSSModules from 'vue-css-modules'
import styles from './button.css'

export default {
  mixins: [CSSModules(styles)],
  props: { mini: Boolean },
  render() {
    return (
      <button styleName="@button :mini">Am I</button>)}}Copy the code

Used in Vue rendering functions

import CSSModules from 'vue-css-modules'
import styles from './button.css'

export default {
  mixins: [CSSModules(styles)],
  props: { mini: Boolean },
  render(h) {
    return h('button', {
      styleName: '@button :mini'
    }, 'am I')}}Copy the code

Realize the principle of

Vue-css-modules registers the beforeCreate hook in which it hijacks the component’s rendering function. For parameters passed to the render function, the styleName property in its data or data.attrs is parsed to generate a global class name string that is attached to the value of data.staticClass.

Making: vue – CSS – modules