Fix Global CSS with PostCSS

Andrey Sitnik, Evil Martians

Fix Global CSS with PostCSS

Andrey Sitnik, Evil Martians

Part 1 What is PostCSS?

Inside PostCSS

CSS
source map
Parser
Plugin
Plugin
Stringifier
New CSS
new source map

Plugin Example postcss-nested

.block {
    &_title {
        font-size: 200%;
    }
}
.block_title {
    font-size: 200%;
}

Plugin Example autoprefixer

:fullscreen {
}
:-webkit-full-screen {
}
:-moz-full-screen {
}
:-ms-fullscreen {
}
:fullscreen {
}

1 300 000 Downloads per Month

PostCSS Users

Part 2 Problem

Thinking Sass

.foo {
    @mixin transition(width 1s);
    @mixin rtl-float(left);
}

Use PostCSS to keep code maintainable—not just for syntax sugar

Why did we create computers?

1. All machines must suffer

2. Divide and Conquer

OSI/ISO

7. Application HTTP, FTP, SMTP, SSH, TELNET
6. Presentation HTML, CSS, GIF
5. Session RPC, PAP, SSL, SQL
4. Transport TCP, UDP, NETBEUI
3. Network IPv4, IPv6, IPsec, AppleTalk, ICMP
2. Data link PPP, IEEE 802.2, L2TP, MAC, LLDP
1. Physical Ethernet physical layer, DSL, USB, ISDN, DOCSIS

Operating System

CommonJS

var React = require('react');
 
module.exports = React.createClass({

});

Design Style Guides

And then Global CSS :-(

* {
    box-sizing: border-box;
}
.title {
    font-size: 30px;
}

Problems

  1. Global selectors
  2. Global reset
  3. Inherited properties
  4. Page based media queries

Part 3 Components

Isolated Components

postcss-use

@use postcss-center;
 
.logo {
    top: center;
}

Part 4 Selectors

Problem

/* logo.css */
.name {
    font-size: 20px;
}
/* header.css */
.name {
    font-size: 16px;
}

postcss-bem

@b Logo {
    @e name {
        color: gray;
    }
}
.Logo-name {
    color: gray
}

All machines must suffer

CSS Modules

.name {
    color: gray;
}
.Logo__name__sVK0p {
    color: gray
}

Client Side: webpack

import styles from './logo.css';
 
class Logo extends React.Component {
    render() {
        return <div className={ styles.name }></div>;
    }
}

Server Side: postcss-modules

- styles = read_json('components/logo/logo.css.json')
 
div( class=styles['logo'] )
  div( class=styles['name'] )

Part 5 Reset

Problem

 *  {
    box-sizing: border-box;
    padding: 0;
    margin: 0;
}

postcss-autoreset

.logo {
}
.name {  
}
.name.is-big {
}
.logo {
    all: initial;
}
.name {
    all: initial;
}
.name.is-big {
}

Configuration

autoreset({
    reset: {
        'box-sizing': 'border-box',
        'all': 'initial'
    }
});

Part 6 Properties

Inherited Properties

<Header>
    color: white
    <Logo>
        background: white
    </Logo>
</Header>

Third-Party Widgets

h2 {
    color: red;
}
div {
    margin-top: 10px;
}

postcss-cssnext

.logo {
    all: initial;
}
.logo {
    color: black;
    background: white;
    box-sizing: content-box;
    line-height: normal;
    text-shadow: none;
    vertical-align: baseline;
    white-space: normal;

Part 7 Media Queries

Problem

/* Page width */
@media (max-width: 600px) {
    .photo {
        width: auto;
    }
}

Component Media Queries

.photo:container(width <= 600px) {
    width: auto;
}
.photo:container(background-color lightness < 20%) {
    color: white;
}

cq-prolyfill

<script src="cq-prolyfill.min.js" async></script>

Part 8 Summary

Absolute Isolation with PostCSS

  1. Transformations: postcss-use
  2. Selectors: postcss-modules
  3. Reset: postcss-autoreset
  4. Properties: all: inital and postcss-cssnext
  5. Media Queries: cq-prolyfill

PostCSS is not an Enemy of Sass

Legacy project:

New project:

.pipe( sass() )
.pipe( postcss([
    ...plugins
]) )
.pipe( postcss([
    precss,
    ...plugins
]) )

github.com/postcss/postcss