The End

— of —

Global CSS

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>

CSS at scale feels

Completely different

“How do we scale interfaces better?”

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

Single Dependency Tree

js/
css/
images/
fonts/
components/
  MyComponent/
    MyComponent.js
    MyComponent.css
    icon.svg
    
require('./MyComponent.css');

export default () => (
  <div className="MyComponent">
    <div className="MyComponent__Icon">Icon</div>
    ...
  </div>
);
.MyComponent__Icon {
  background-image: url('icon.svg');
}

Traversing different file types

// webpack.config.js:
loaders: [{
  test: /\.css$/,
  loader: 'style-loader!css-loader!postcss-loader')
},{
  test: /\.svg$/,
  loader: 'url-loader?mimetype=image/svg+xml'
},{
  test: /\.js$/,
  loader: 'babel-loader'
}]

Simple interface

import MyComponent from 'MyComponent';

export default () => <MyComponent />;

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 { ... }
// Styles object:
{
  'header': '_1rJwx92-gmbvaLiDdzgXiJ',
  'footer': '_ah6Hch-gjsAdSE53CxzaEs'
}

No more

naming collisions

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), :global(.class) into .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’

“In the future, we could start generating shared classes between components automatically, treating style re-use as an optimisation at compile time.”

One-to-one mapping

{
  'foo': 'MyComponent__foo'
}

One-to-many mapping?

{
  'foo': 'class_1 class_2 class_3'
}

Composition

.foo {
  composes: heading from './typography.css';
  composes: box from './layout.css';
  color: red;
}
/* typography.css */
.heading { ... }

/* layout.css */
.box { ... }
{
  'foo': `MyComponent__foo
          Typography__heading
          Layout__box`
}

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

@markdalgleish — May 23, 2015

‘css-loader?modules’

React?

JavaScript dependency?

The future…

github.com/css-modules

“This looks complicated…”

Each component is a miniature

CSS Zen Garden

Smarter tools

— not —

Stricter methodologies

Let’s make Big CSS

— feel like —

Small CSS