1999
I ❤ CSS
CSS-in-JS
“Just learn CSS”
Misunderstood
communities
Component systems
— & —
Progressive enhancement
I’m very interested
in CSS-in-JS
I think you
should be too
But Why?
- Scoped styles
- Critical CSS
- Smarter optimisations
- Package management
- Non-browser styling
1.
Scoped Styles
Managing CSS at scale
The hardest problem
in front-end
OOCSS
— by Nicole Sullivan —
SMACSS
— by Jonathan Snook —
BEM
— from Yandex —
.Block__element--modifier
Convention
👍
Convention?
BEM Blocks
— are essentially —
Components
Components
— are defined in —
JavaScript
Glamor
— by Sunil Pai —
import { css } from 'glamor'
css({
fontFamily: 'Comic Sans MS',
color: 'blue'
})
// → 'css-1pyvz'
Hashed classes
— to —
enforce scoping
Inline styles
Real CSS
JSS
— by Oleg Slobodskoi —
const styles = {
button: {
padding: '10px',
'&:hover': {
background: 'blue'
}
},
'@media (min-width: 1024px)': {
button: {
padding: '20px'
}
}
}
const { classes } =
jss.createStyleSheet(styles).attach()
document.body.innerHTML = `
<h1 class="${classes.heading}">Hello CSSConf EU!</h1>
`
Scoped CSS
— & —
Components
react-jss
import injectSheet from 'react-jss'
const Button = ({ classes, children }) => (
<button className={classes.button}>
<span className={classes.label}>
{children}
</span>
</button>
)
export default injectSheet(styles)(Button)
“Separating concerns?”
export default {
button: {
background: props => props.color
},
label: {
fontWeight: 'bold'
}
}
import styles from './Button.styles.js'
Styles passed around
like regular code
Component scoping
— is now —
automated
Atomic design
BEM is baked in,
not opt-in
2.
Critical CSS
👋 Patrick Hamann
Google PageSpeed
Inlining styles
— for the —
current page
<head>
<style>.heading{...}</style>
</head>
<body>
<h1 class="heading">...</h1>
<link rel="stylesheet" ... />
</body>
Critical
— by Addy Osmani —
👍
Optional
optimisation
“Hard to maintain
hard to automate”
— Patrick Hamann
CSS-in-JS
— & —
Server rendering
Critical CSS is
not just an
optimisation
Server-side
CSS-in-JS
depends on
critical CSS
Aphrodite
— from Khan Academy —
import { StyleSheet, css } from 'aphrodite'
const styles = StyleSheet.create({
heading: { color: 'blue' }
})
const Heading = ({ children }) => (
<h1 className={css(styles.heading)}>
{ children }
</h1>
)
import { StyleSheetServer } from 'aphrodite'
const { html, css } = StyleSheetServer.renderStatic(
() => ReactDOMServer.renderToString(<App />)
)
const criticalCSS = `
<style data-aphrodite>
${css.content}
</style>
`
const appHtml = `
<div id="root">
${html}
</div>
`
Built for
progressive
enhancement
Server rendered
— or —
Statically pre-rendered
Critical CSS is built in,
not opt-in
3.
Smarter Optimisations
Reducing CSS bundle
— to the —
absolute minimum
Atomic CSS
— from Yahoo —
<div class="Bgc(#0280ae.5) C(#fff) P(20px)">
Atomic CSS
</div>
Tachyons
— by Adam Morse —
<div class="dib f5 f4-ns fw6 mt0 mb1 link black-70">
Tachyons
</a>
Treating classes
like inline styles
👍 / 👎
<aside className={styles.sidebar} />
<aside className={'sidebar'} />
<aside className={'class1 class2 class3 class4'} />
Styletron
— by Ryan Tsao —
Dynamic, zero config
atomic CSS
import styletron from 'styletron'
styletron.injectDeclaration({
prop: 'color',
val: 'red',
media: '(min-width: 800px)'
})
// → 'a'
injectStyle(styletron, {
color: 'red',
display: 'inline-block'
});
// → 'a d'
injectStyle(styletron, {
color: 'red',
fontSize: '1.6em'
});
// → 'a e'
Atomic CSS is baked in,
not opt-in
4.
Package Management
How do we share CSS?
Bower?
Manual CSS inclusion
Not coupled
— to a —
module system
Dependencies
— of —
Dependencies?
Monolithic dependencies
Package manager
— for —
CSS / Sass / Less?
Package manager
— for —
HTML?
We share HTML-in-JS
What if we shared CSS
via JavaScript & npm?
mixins
functions
@extend
{ ...rules }
Compose and share like
any other code
${✨}
polished
— by Max Stoiber & Nik Graf —
The Lodash of CSS-in-JS
clearFix, ellipsis, fontFace, hiDPI, hideText, normalize, placeholder, radialGradient, retinaImage, selection, timingFunctions, wordWrap, adjustHue, complement, darken, desaturate, grayscale, hsl, hsla, invert, lighten, mix, opacify, parseToHsl, parseToRgb, rgb, rgba, saturate, setHue, setLightness, setSaturation, shade, tint, transparentize, animation, backgroundImages, backgrounds, borderColor, borderRadius, borderStyle, borderWidth, buttons, margin, padding, position, size, textInputs, transitions, directionalProperty, em, modularScale, rem, stripUnit, Ratio, RgbColor, RgbaColor, HslColor, HslaColor, FontFaceConfiguration, RadialGradientConfiguration, TimingFunction, AnimationProperty, ButtonState, InputState, toColorString, PointingDirection
JavaScript modules
5.
Non-browser Styling
DOM Mutation
Virtual DOM
import { render } from 'react-dom'
Different
renderers
Virtual DOM whatever
react-native
var styles = StyleSheet.create({
container: {
borderRadius: 4,
borderWidth: 0.5,
borderColor: '#d6d7da',
},
title: {
fontSize: 19,
fontWeight: 'bold',
},
activeTitle: {
color: 'red',
}
});
var styles = StyleSheet.create({
container: {
display: 'flex'
}
});
css-layout
“Yoga’s focus is on creating an expressive layout library, not implementing all of CSS.”
CSS at scale
— is all about picking a —
Reasonable subset
Table layouts
Floats
Flexbox
Cascade
Scoped styles
Cross-platform components
— with —
embedded styles
react-native-web
— by Nicolas Gallagher —
alias: {
'react-native': 'react-native-web'
}
react-primitives
— by Leland Richardson —
reactxp
— from Microsoft —
Taking our
components
even further
react-sketchapp
— by Jon Gold —
Cross-platform,
cross-disciplinary
design systems
Cross-platform code as
the source of truth
Taking CSS where
it’s never been before
Why?
- Scoping
- Scaling
- Maintaining
- Optimising
- Sharing
- Composing
- Unifying
A unified styling language
import {
PageBlock,
Card,
Text
} from 'seek-style-guide/react'
<PageBlock>
<Card>
<Text heading>Hello CSSConf EU!</Text>
</Card>
</PageBlock>
Without breaking
progressive enhancement
“Just learn CSS”
We’re not done yet
- Performance
- Extracting static CSS
- Targeting CSS Variables
- Making developers happy!