Reducing your bundle size with

Functional CSS

Ed Moore

@_edmoore eddiemoore

CSS is hard

In [the monolith] model, you will never stop writing css. Refactoring css is hard and time consuming. Deleting unused css is hard and time consuming. And more often than not - it’s not work people are excited to do. So what happens? People keep writing more and more css

Adam Morse - CSS and Scalability

Specificity Wars

😭


      body > #main > ul.list > li.list-item:first-child > div
      > span {
        color: hotpink;
      }
    

      body > #main > ul.list > li.list-item:first-child > div
      > span {
        color: hotpink !important;
      }
    
Tricky CSS inheritance issue β€” challenge accepted (@mathias)

OOCSS / SMACSS / BEM

πŸ˜„


      .ListItem__span {
        color: hotpink;
      }
    

Functional CSS

Atomic CSS / Immutable CSS

Do One Thing and Do It Well

CSS is Functional


      const capitalise = x => x.toUpperCase()
      const shout = x => x + '!'
      const reverse = x => x.split('').reverse().join('')

      const reversedShout = compose(shout, capitalise, reverse)

      console.log(reversedShout('hey')) // YEH!
    

      .grid { display: grid; }
      .gg1 { grid-gap: 1rem; }
      .gtc3 { grid-template-columns: repeat(3, 1fr); }
    

    <div class="grid gg1 gtc3"></div>

Libraries

Tachyons

tachyons.io


      .bg-gold { background-color: var(--gold); }
      .f4 { font-size: 1.25rem; }
      .b { font-weight: bold; }
      .baskerville { font-family: baskerville, serif; }
      .flex { display: flex; }
      .justify-between { justify-content: space-between; }
    

Atomic CSS

acss.io


      <div class="Bgc(#0280ae.5) C(#fff) P(20px)">
        Lorem ipsum
      </div>
    

Tailwind CSS

tailwindcss.com


      <button
        class="bg-blue hover:bg-blue-dark text-white font-bold py-2 px-4 rounded"
      >
        Button
      </button>
    

/* colours.css */
.hotpink {
  color: hotpink;
}

/* component-style.css */
.container {
  composes: hotpink from './colours.css';
  display: flex;
}

  <div class={styles.container} />

/* bundle.css */
.hotpink {
  color: hotpink;
}

.container {
  display: flex;
}

    <div class="container hotpink"></div>

Hydrogen CSS

Atomic CSS for CSS Modules

https://github.com/eddiemoore/hydrogencss


npm i -S hydrogencss
yarn add hydrogencss

What is it?

Use MDN data

Builds a a suite of files based on the property and uses the values as the class names.


.container {
  composes: flex from 'hydrogencss/display.css';
  composes: column from 'hydrogencss/flex-direction.css';
  colour: hotpink;
}

.box {
  composes: flex from 'hydrogencss/display.css';
  margin: 1rem;
}

.flex {
  display: flex;
}

.column {
  flex-direction: column;
}

.container {
  colour: hotpink;
}

.box {
  margin: 1rem;
}

<div class="flex column container"></div>

Problem

🀯


    .container {
      composes: flex from 'hydrogencss/display.css';
      composes: center from 'hydrogencss/justify-content.css';
      composes: center from 'hydrogencss/text-align.css';
    }

    .flex {
      display: flex;
    }
    .center {
      justify-content: center;
    }
    .center {
      text-align: center;
    }
      {
        test: /\.css$/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              modules: true,
              importLoaders: 1,
              minimize: true,
              localIdentName: '[name]__[local]', // prod: _[hash:base64:5]
            },
          },
          'postcss-loader',
        ],
      }
    

    .display__flex {
      display: flex;
    }
    .justify-content__center {
      justify-content: center;
    }
    .text-align__center {
      text-align: center;
    }

<div class="display__flex justify-content__center text-align__center">
</div>

._3KnPL {
  display: flex;
}
._10bHm {
  justify-content: center;
}
._1rToO {
  text-align: center;
}

  <div class="_3KnPL _10bHm _1rToO">
  </div>

Production Testing

postcss-hydrogencss-cssmodules

Extreme alpha

https://github.com/eddiemoore/postcss-hydrogencss-cssmodules


    npm i -S postcss-hydrogencss-cssmodules
    yarn add postcss-hydrogencss-cssmodules

    .MyComponent {
      display: flex;
      flex-direction: column;
      background-color: white;
      color: #222;
      border-radius: 3px;
    }

    /* Each class in own file */
    .display-flex { display: flex; }
    .flex-direction-column { flex-direction: column; }
    .background-color-white { background-color: white; }
    .color-222 { color: #222; }
    .border-radius-3px { border-radius: 3px; }


    .MyComponent {
      composes: display-flex from
        'postcss-hydrogencss-cssmodules/display-flex.css';
      composes: flex-direction-column from
        'postcss-hydrogencss-cssmodules/flex-direction-column.css';
      composes: background-color-white from
        'postcss-hydrogencss-cssmodules/background-color-white.css';
      composes: color-222 from
        'postcss-hydrogencss-cssmodules/color-222.css';
      composes: border-radius-3px from
        'postcss-hydrogencss-cssmodules/border-radius-3px.css';
    }
    

      <div
        class="display-flex flex-direction background-color-white color-222 border-radius-3px"
      />
    

Final size

In the real world?

Questions?

πŸ€”

Ed Moore

@_edmoore eddiemoore

Slides

https://eddie-moore.com/talks/functionalcss