Let’s start at the beginning…

Creative HTML Design book cover

Documents

— vs. —

Web Apps

Global scope

— vs —

Maintenance

.Block__Element--Modifier { ... }
<div class="page my-page">

  <header class="header">
    <h1 class="heading header__heading">...</h1>
  </header>
  
  <article class="post">
    <header class="post__header">
      <h1 class="heading post__heading">Hello World</h1>
    </header>
    <section class="post__content">...</section>
  </article>
  
  <footer class="footer">...</footer>
  
</div>

The Age

— of —

Components

React

Components are nothing new

<select>
  <option>...</option>
  <option>...</option>
  <option>...</option>
</select>

<input type="date" />

CSS and images

— are —

private to a component

Unless you use third-party components…

jQuery UI Date Picker

Our tools reflected this

gulp.task('js', function() {
  return gulp.src('src/js/index.js')
    .pipe(browserify());
});

gulp.task('css', function() {
  return gulp.src('src/styles/index.scss')
    .pipe(sass());
});

gulp.task('images', function() { ... });
@import "vendor/normalize";

@import "config/colors";
@import "config/media_queries";

@import "modules/btn";
@import "modules/dropdown";
@import "modules/header";

@import "utilities/align";
@import "utilities/clearfix";

Tooling

— for the —

component age?

Webpack

require('./MyComponent.css');

export default () => (
  <div className="MyComponent">
    <div className="MyComponent__Icon">Icon</div>
    ...
  </div>
);

Simple interface

import MyComponent from 'MyComponent';

export default () => <MyComponent />;

Progressive

Single Page Apps

Checkbox hacks

.menu {
  transform: translateX(-100%);
  transition: all .3s ease;
}

.toggle:checked ~ .menu {
  transform: none
}

Late 2014…

“CSS has fundamental flaws at scale that can be solved by writing styles in JS.”

@vjeux — November 2014

MicheleBertoli/css-in-js

react-style

— by @andreypopp —

import StyleSheet from 'react-style';

const styles = StyleSheet.create({
    foo: {
      color: 'red',
      backgroundColor: 'white'
    }
});

export default () => (
  <div style={styles.foo}>
    Hello, world!
  </div>
);

but…

And yet…

😍

— How do we embrace the —

inline style mindset in regular CSS?

BEM

A block

— is —

a component

“Never use a block outside
a component of the same name”

components/
  MyComponent/
    MyComponent.js
    MyComponent.css
    icon.svg
    
.MyComponent__foo { ... }

.MyComponent__bar { ... }
.MyComponent__bar--expanded { ... }

“Block, Element, Modifying Your JavaScript Components”

Meanwhile…

Local Scope

require('./MyComponent.css');

// becomes...

import styles from './MyComponent.css';

What does ‘styles’

evaluate to?

First, let’s look at the CSS…

:local(.header) { ... }
:local(.footer) { ... }
import styles from './MyComponent.css';

export default () => (
  <div>
    <div className={styles.header}>...</div>
    <div className={styles.footer}>...</div>
  </div>
);
:local(.header) { ... }
:local(.footer) { ... }

Becomes:

/* Globally unique classes */
._1rJwx92-gmbvaLiDdzgXiJ { ... }
._ah6Hch-gjsAdSE53CxzaEs { ... }

No more

naming collisions

// Styles object:
{
  'header': '_1rJwx92-gmbvaLiDdzgXiJ',
  'footer': '_ah6Hch-gjsAdSE53CxzaEs'
}
loader: 'css?localIdentName=[name]__[local]'
.MyComponent__foo { ... }
.MyComponent__bar { ... }
:local(.field) { ... }
:local(.field):focus { ... }

:local(.backdrop) { ... }
:local(.root_isCollapsed) :local(.backdrop) { ... }

:local(.panel) .transition-active-enter { ... }

“What if locally scoped
CSS was the default?”

.backdrop { ... }
.root_isCollapsed .backdrop { ... }

.field { ... }
.field:focus { ... }

.panel :global(.transition-active-enter) { ... }

PostCSS

postcss-local-scope

— Turned .class into :local(.class) —

The End

— of —

Global CSS

“I hope it’s ok if I integrate your postcss-local-scope module into the css-loader”

@sokra — May 24, 2015

‘css-loader?module’

“Have you thought about writing a standard for CSS modules that others could implement?”

@markdalgleish — May 23, 2015

‘css-loader?modules’

github.com/css-modules

Let’s rewind a little…

Why not CSS in JS?

Inline styles

CSS in JS

— isn’t restricted to —

Inline Styles

Khan Academy

Aphrodite

Jamie Wong / Emily Eisenberg

import { StyleSheet } from 'aphrodite';

const styles = StyleSheet.create({
  field: {
    margin: '0 10px',
    ':focus': { outline: '2px solid blue' },
    '@media (min-width: 600px)': { margin: '0 20px' }
  }
});
import { css } from 'aphrodite';

export default () => (
  <div>
    <input className={css(styles.field)} />
  </div>
);
import { StyleSheetServer } from 'aphrodite';

var {html, css} = StyleSheetServer.renderStatic(() => {
    return ReactDOMServer.renderToString();
});
return `
  <html>
    <head>
      <style data-aphrodite>${css.content}</style>
    </head>
    
    <body>
      <div id='app'>${html}</div>
      ...
    </body>
  </html>
`;

“We must deliver the absolute minimum amount of CSS necessary by only sending down CSS in use by components in the server-side rendered body”

Jamie Wong — March 2016

Personal

preference

CSS Modules

— or —

CSS-in-JS…

What do these
approaches have
in common?

First Class Styles

Locally define styles

— then —

Pass directly to elements

.foo { color: red }

import styles from './Component.css';
<div className={styles.foo} />
const styles = StyleSheet.create({
  foo: { color: 'red' }
});

<div style={styles.foo} />

We've been putting this into practice
for the past year...

Our global CSS footprint?

/* http://meyerweb.com/eric/tools/css/reset/ 
   v2.0 | 20110126
   License: none (public domain)
*/

html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed, 
figure, figcaption, footer, header, hgroup, 
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
  margin: 0;
  padding: 0;
  border: 0;
  font-size: 100%;
  font: inherit;
  vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure, 
footer, header, hgroup, menu, nav, section {
  display: block;
}
body {
  line-height: 1;
}
ol, ul {
  list-style: none;
}
blockquote, q {
  quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
  content: '';
  content: none;
}
table {
  border-collapse: collapse;
  border-spacing: 0;
}
html {
  font-family: @base-font-stack;
  font-size: unit(@base-font-size, px);
  background-color: @sk-background;
  box-sizing: border-box;
  min-height: 100%;
  overflow-y: auto;
}
*,
*:before,
*:after {
  font-family: inherit;
  box-sizing: inherit;
  -webkit-tap-highlight-color: rgba(0,0,0,0);
  -webkit-tap-highlight-color: transparent; /* For some Androids */
}

body {
  overflow-y: hidden;
}

input {
  margin: 0;
}

input[type=search]::-webkit-search-decoration {
  -webkit-appearance:none;
}

Easier style guide extraction

But that’s a topic for another day…

👍
😍😍😍