css-out-js icon indicating copy to clipboard operation
css-out-js copied to clipboard

Author styles collocated in JS, pull them out into static CSS on build. No runtime dependency.



Author styles collocated in JS, pull them out into static CSS on build. No runtime dependency.

 

the big idea:

I like to author styles collocated with component code, that's how I find them maintainable.

But before shipping them to users, I'd like to pull styles out of components and ship them in static CSS files. No runtime dependency.

animation showing code being pulled into dist.css

prior art: This idea is not entirely new, there have been other similar interpretations of this idea before like callstack/linaria and atlassian-labs/compiled

 

input

App.js

import { css } from 'css-out-js';

const Title = (props) => {
  return <h1 className={css({ fontSize: '2em' })}>Hello!</h1>;
};

output

The plugin extracts the styles into a css file
and replaces the function call with generated className string.
If there are any dynamic styles, it creates a css variable for them.
Finally, it removes the import for css-out-js, no runtime.

dist.css

+.Title-1bdbzov {
+  font-size: 2em;
+}

App.js

- import { css } from 'css-out-js';

const Title = (props) => {
- return <h1 className={css({ fontSize: '2em' })}>Hello!</h1>;
+ return <h1 className="Title-1bdbzov">Hello!</h1>;
};

 

works with dynamic styles as well:

input

App.js

import { css } from 'css-out-js';

const Home = (props) => {
  const className = css({ color: props.color });

  return (
    <section className={className}>
      <p>Home sweet home</p>
    </section>
  );
};

output

Dynamic styles based on props are made possible by setting a css variable.

dist.css

+.Home-2b9glr {
+  color: var(--props-color-1trdzir);
+}

App.js

- import { css } from 'css-out-js';

const Home = (props) => {
- const className = css({ color: props.color });
+ const className = "Home-2b9glr"
+ document.documentElement.style.setProperty('--props-color-1trdzir', props.color),

  return (
    <section className={className}>
      <p>Home sweet home</p>
    </section>
  );
}

setup

  1. install

    npm install css-out-js --save-dev
    
    # or
    
    yarn add css-out-js --dev
    
  2. Add plugin to babelrc, you can specify the location of your generated css file (hint: see examples directory)

    // .babelrc
    module.exports = {
      plugins: [['css-out-js/babel', { path: 'public/dist.css' }]]
    };
    
  3. add css import

    this may differ based on the framework of your choice. (hint: see examples directory)

    // App.js
    import './dist.css';