All Projects → matvp91 → stylemug

matvp91 / stylemug

Licence: MIT license
CSS in JS with support for static / atomic CSS extraction.

Programming Languages

javascript
184084 projects - #8 most used programming language
HTML
75241 projects

Projects that are alternatives of or similar to stylemug

Fela
State-Driven Styling in JavaScript
Stars: ✭ 2,097 (+3712.73%)
Mutual labels:  atomic-css
Basscss
Low-level CSS Toolkit – the original Functional/Utility/Atomic CSS library
Stars: ✭ 5,669 (+10207.27%)
Mutual labels:  atomic-css
Styletron
⚡ Toolkit for component-oriented styling
Stars: ✭ 3,217 (+5749.09%)
Mutual labels:  atomic-css
brevis
CSS at scale
Stars: ✭ 62 (+12.73%)
Mutual labels:  atomic-css
quantum-css
Atomic CSS library written in SCSS.
Stars: ✭ 27 (-50.91%)
Mutual labels:  atomic-css
atomize
A library of atomic CSS classes.
Stars: ✭ 51 (-7.27%)
Mutual labels:  atomic-css
tachyons-cheatsheet
Interactive cheat sheet for Tachyons 📝
Stars: ✭ 52 (-5.45%)
Mutual labels:  atomic-css
uniformcss
A fully configurable utility class generator and CSS framework built for Sass projects.
Stars: ✭ 133 (+141.82%)
Mutual labels:  atomic-css
steller-css
⛰️ A utility-first CSS framework that serves as the foundation of your design system
Stars: ✭ 14 (-74.55%)
Mutual labels:  atomic-css
adorable-css
Rapid On-Demand Atomic CSS Framework
Stars: ✭ 131 (+138.18%)
Mutual labels:  atomic-css
hydrogencss
Atomic CSS for CSS Modules
Stars: ✭ 13 (-76.36%)
Mutual labels:  atomic-css
ekzo
💫 Functional Sass framework for rapid and painless development
Stars: ✭ 32 (-41.82%)
Mutual labels:  atomic-css
unocss
The instant on-demand atomic CSS engine.
Stars: ✭ 7,866 (+14201.82%)
Mutual labels:  atomic-css
svbstrate
A functional/atomic/utility css library.
Stars: ✭ 51 (-7.27%)
Mutual labels:  atomic-css

stylemug ⚛️

A fast css-in-js library that extracts atomic CSS rules to a .css file.

We try to limit the functionality of this package in order to do the following key features really well:

  • It generates Atomic CSS from the static stylesheets defined in your component.
  • The compiled rules are extracted to a .css file.
  • The stylesheet code in your bundle is replaced (no CSS in your JS) with a hash map for classnames lookup at runtime.

Heavily inspired by Facebook's internal stylex and the "Building the new Facebook" presentation, at ~28:00.

Getting started

Add the package as a dependency.

npm i stylemug

The example below uses stylemug.create to define your stylesheet and will provide a styles function used to resolve your class names.

import React from 'react';
import stylemug from 'stylemug';

const styles = stylemug.create({
  default: {
    backgroundColor: 'red',
    color: 'black',
  },
  large: {
    fontSize: '32px',
  },
});

function App() {
  const [large, toggleLarge] = useToggle(true);

  return (
    <div className={styles('default', large && 'large')}>
      <button onClick={toggleLarge}>Toggle me</button>
    </div>
  );
}

Add stylemug/compiler's babel and webpack plugin in your webpack.config.js config file.

const stylemugCompiler = require('stylemug/compiler');

module.exports = {
  ...
  module: {
    rules: [
      {
        test: /\.m?js$/,
        exclude: /(node_modules|bower_components)/,
        use: {
          loader: 'babel-loader',
          options: {
            // The babel plugin will collect each schematic from `stylemug.create`
            // and rewrite the schema to a lookup table.
            plugins: [stylemugCompiler.babel],
          },
        },
      },
    ],
  },
  plugins: [
    new stylemugCompiler.webpack({
      // The CSS rules extracted by babel will be written to
      // this file.
      name: 'bundle.css',
    }),
  ],
};

Features

Generic rules

A style rule can be shared from one file to another, aslong as the stylesheet itself remains static.

// foo.js
export default stylemug.create({
  container: {
    width: '720px',
  },
});

// bar.js
import foo from './foo';

const styles = stylemug.create({
  default: {
    color: 'green',
  },
});

const classNames = styles('default', foo.container);

Pseudo classes & media queries

const styles = stylemug.create({
  button: {
    ...

    // pseudo classes
    '&:hover': {
      color: 'green',
    },

    // media queries
    '@media (min-width: 720px)': {
      width: '100px',
    },
  },
});

How it works

When webpack bundles your code, babel-loader is used to parse your JS files through Babel and perform a variety of transformations (one of the most common ones is converting ES6 to ES5). One of these transformations is part of the Babel plugin in stylemug/compiler.

The plugin looks for the import statement:

import stylemug from 'stylemug';

and searches for occurances of stylemug.create.

const styles = stylemug.create({
  className1: {
    color: 'red',
    backgroundColor: 'blue',
  },
  className2: {
    color: 'yellow';
  },
});

Afterwards, it compiles the stylesheet by generating a classname for each rule. This concept is called atomic CSS, offering single-purpose units of style, but applied via classes.

.c8938 { color: 'red'; }
.e79cd { color: 'blue'; }
.aaddb { color: 'yellow'; }

Finally, the stylesheet is replaced with a hash map in your code. At this point, the stylesheet is gone from your JS bundle.

const styles = stylemug.create({
  className1: {
    color: 'c8938',
    backgroundColor: 'e79cd',
  },
  className2: {
    color: 'aaddb',
  },
});

Internally, the styles function uses Object.assign to avoid duplication of rules.

// 1.
const classes = styles('className1', 'className2');

// 2.
const classes = Object.assign(
  {},
  {
    color: 'c8938',
    backgroundColor: 'e79cd',
  },
  {
    color: 'aaddb',
  }
);

// 3.
const classes = ['e79cd', 'aaddb'];
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].