Skip to content

joshwnj/cmz

Repository files navigation

cmz

Greenkeeper badge

Build Status

CSS Modules Zero: A low-sugar variant of CSS Modules that runs in node and in the browser.

Example

There is some more background context in the wiki.

How to get started

First add it to your project with npm install cmz

In your component widget.js you want to style with a CSS Module. Add this to the top:

const cmz = require('cmz')

// Define a single class.
const myAmazingClass = cmz(`
  font-style: italic
  color: magenta
`)

// This is the equivalent of
//
//  .myAmazingClass {
//    font-style: italic;
//    color: magenta;
//  }

// Now you can use that class:
document.body.innerHTML = `<h1 class="${myAmazingclass}">cmz demo</h1>`

// The css is automatically added to the document's stylesheet.

Pseudoselectors

If you want a class with a pseudoselector, we can use the & placeholder (which is replaced with the class's unique name):

const classWithPseudos = cmz(`
& {
  color: magenta
}

&:hover {
  color: cyan
}
`)

Composition

A useful pattern with CSS Modules is to define a library of common styles, and then compose them together.

// typography.js

import cmz from 'cmz'

export const bigText = cmz(`
  font-size: 48px
  letter-spacing: .1rem
  text-transform: uppercase
`)

export const highlight = cmz(`
  color: cyan
  font-weight: bold
`)

To compose, pass an array of classes. It's fine to mix new classes with existing ones:

// heading.js

import cmz from 'cmz'
import typo from './typography'

const heading = cmz(`
  padding: 16px
  border-bottom: 1px solid #000
`,
  typo.bigText,
  typo.highlight
)

export default function () {
  return `<h1 class="${heading}">cmz demo</h1>`
}

Can cmz generate a .css file?

Yes!

By default cmz adds all css to the page at runtime via a <style> tag. In a lot of cases this is fine, and will save you a network request as it's all bundled in the one .js file.

To extract css to a separate .css file (and result in a smaller .js bundle) there are 3 steps:

  • create the js bundle as usual, with the cmz-names babel plugin
  • server-side-render your frontend, so that cmz can collect all of the necessary styles and write a .css file
  • run the cmz-min script to trim the extracted css rules from your js bundle

To see this in action take a look at the example.

Are animations automatically scoped?

By default, animations are left untouched. But you can create unique animation names by using the ? placeholder. The animation will be created with the same base-name as the class:

const fadeAnim = cmz(`
  & {
    animation: ? 1s infinite
  }

  @keyframes ? {
    0% { opacity: 1 }
    50% { opacity: 0 }
  }
`)

Because the animation is coupled with a class, they can be applied as compositions, eg:

const myFadingThing = cmz(
  'width: 50%',
  fadeAnim
)

Does cmz add vendor-prefixes?

Not yet, but it will soon :) If this is important to you I'd love to help you make a PR :)

Thanks

to the CSS Modules team

License

MIT