.css__in--react {
will-change: transform;
}
CSS IN React
Joe Seifi
Eventbrite
@BODY fo(fa=he,si=18)
@P co(nu=3,wi=80)
(BODY fontSize=normal
BGColor=white
FGColor=black
(H1 fontSize=largest
BGColor=red
FGColor=white)
)
h1.font.size = 24pt 100%
h2.font.size = 20pt 40%
*LI.prebreak: 0.5
*LI.postbreak: 0.5
*OL.LI.label: 1
*OL*OL.LI.label: A
(element H1
(make paragraph
font-size: 14pt
font-weight: 'bold))
(style a
(block #f) ; format as inline phrase
(color blue) ; in blue if you’ve got it
(click (follow (attval 'href))) ; and on click, follow url
LI {
VertPos: Top = LeftSib . Actual Bottom;
}
A {
if (getAttribute(self, "href") != "") then
fgColor = "blue";
underlineNumber = 1;
endif
}
tags.H1.color = "blue";
tags.p.fontSize = "14pt";
with (tags.H3) {
color = "green";
}
classes.punk.all.color = "#00FF00"
ids.z098y.letterSpacing = "0.3em"
RRP
@BODY fo(fa=he,si=18)
@P co(nu=3,wi=80)
PWP
(BODY fontSize=normal
BGColor=white
FGColor=black
(H1 fontSize=largest
BGColor=red
FGColor=white)
)
CHSS
h1.font.size = 24pt 100%
h2.font.size = 20pt 40%
RRP
*LI.prebreak: 0.5
*LI.postbreak: 0.5
*OL.LI.label: 1
*OL*OL.LI.label: A
DSSSL
(element H1
(make paragraph
font-size: 14pt
font-weight: 'bold))
RRP
(style a
(block #f) ; format as inline phrase
(color blue) ; in blue if you’ve got it
(click (follow (attval 'href))) ; and on click, follow url
PSL
LI {
VertPos: Top = LeftSib . Actual Bottom;
}
A {
if (getAttribute(self, "href") != "") then
fgColor = "blue";
underlineNumber = 1;
endif
}
JSSS
tags.H1.color = "blue";
tags.p.fontSize = "14pt";
with (tags.H3) {
color = "green";
}
classes.punk.all.color = "#00FF00"
ids.z098y.letterSpacing = "0.3em"
Pre-CSS
1993-1996
My first website ~ 1997
JavaScript MVC Components
💄!11
CSS Modular CSS CSS in JS
OOCSS
SMACS
SUIT
BEM
ATOMIC
💄
Super Powers
of CSS in React
- Automation
- Sharable
- Adaptable
- Scalable
- Maintainable
Giving up Control,
actually gives you more
control and new
Super Powers
Automation
Managing CSS Classnames
There are only
2 hard problems in
Computer Science:
cache invalidation &
naming things
Phil Karlton from Netscape
B__E--M > 0__1--0
regular css imports
.btn {
color: #fff;
background: pink;

}
button.css
import './button.css'
css-modules
import styles from './button.css'
.btn {
color: #fff;
background: pink;

}
button.css
css-modules
import styles from './button.css'
console.log(styles)
> {
“btn": "button_btn_2Yt"
}
.btn {
color: #fff;
background: pink;

}
button.css
import React from 'react'
import CSSModules from ‘react-css-modules'
import styles from ‘./button.css’
@CSSModules(styles)
const Button = ({ children }) =>
<button styleName=“btn”>
{children}
</button>
React CSS Modules
Buy
.btn {
color: #fff;
background: pink;

}
button.css
React CSS Modules
.btn {
color: #fff;
background: pink;

}
.button_btn_2Yt {
color: #fff;
background-color: pink;
}
<button class="button_btn_2Yt">
Buy
</button>
browser
import React from 'react'
import CSSModules from ‘react-css-modules'
import styles from ‘./button.css’
@CSSModules(styles)
const Button = ({ children }) =>
<button styleName=“btn”>
{children}
</button>
// render
<Button>Buy</Button>
button.css
Buy
DeCSS
.Button {
color: #fff;
background: orange;
}
import React from 'react'
import { Button } from './Button.css'
Button.css
DeCSS
.Button {
color: #fff;
background: orange;
}
import React from 'react'
import { Button } from './Button.css'
const MyButton = ({ children }) => (
<Button tag="button">
{children}
</Button>
)
// render
<MyButton>Buy</MyButton>
Button.css
DeCSS
.Button {
color: #fff;
background: orange;
}
.button_Button_2V6 {
color: #fff;
background: orange;
}
<button class="button_Button_2V6">
Buy
</button>
browser
import React from 'react'
import { Button } from './Button.css'
const MyButton = ({ children }) => (
<Button tag="button">
{children}
</Button>
)
// render
<MyButton>Buy</MyButton>
Button.css
Buy
Sharable
Bootstrap Nation
122K
2nd largest project on Github
React classNames
<button id="btn">

Buy

</button>
Buy
HTML
<button id="btn">

Buy

</button>
$("#btn").click(() => {
// take money

}
Buy
HTML JavaScript
<button id="btn">

Buy

</button>
$("#btn").click(() => {
// take money

}
Buy
HTML JavaScript
<Button onClick="this.takeMoney">

Buy

</Button>
HTML in JavaScript
Buy
<Button onClick="this.takeMoney">

Buy

</Button>
HTML in JavaScript
Buy
<button className="btn">

Buy

</button>
.btn {
color: #fff;
background-color: pink;
}
Buy
HTML CSS
classNames > Components
.glue_to_ui { /** **/ }
Styled Components
Buy
import React from 'react'
import styled from 'styled-components'
Styled Components
Buy
import React from 'react'
import styled from 'styled-components'
const Button = styled.button`
color: #fff;
background-color: pink;
`
Styled Components
Buy
import React from 'react'
import styled from 'styled-components'
const Button = styled.button`
color: #fff;
background-color: pink;
` .ctyFSz {
color: #fff;
background-color: pink;
}
.sc-bdVaJa {
}
<button class="sc-bdVaJa ctyFSz”>
Buy
</button>
browser
Buy
// render
<Button>Buy</Button>
Styled Components
Buy
43
// shared-lib
export const Shared = ({ className }) => (
<div className={ className }>Sharing is caring!</div>
)
// our-app
import styled from 'styled-components'
import { Shared } from 'shared-lib'
Styled Components
Buy
44
// shared-lib
export const Shared = ({ className }) => (
<div className={ className }>Sharing is caring!</div>
)
// our-app
import styled from 'styled-components'
import { Shared } from 'shared-lib'
const Wrapped = styled(Shared)`color: pink;`
Styled Components
Buy
45
// shared-lib
export const Shared = ({ className }) => (
<div className={ className }>Sharing is caring!</div>
)
// our-app
import styled from 'styled-components'
import { Shared } from 'shared-lib'
const Wrapped = styled(Shared)`color: pink;`
<Shared />
Sharing is caring!
<Wrapped />
Sharing is caring!
JSON vs CSS
Glamorous
Buy
import React from ‘react'
import glamorous from 'glamorous'
Glamorous
Buy
import React from ‘react'
import glamorous from 'glamorous'
const Button = glamorous.button({
color: '#fff',
backgroundColor: 'pink'
})
Glamorous
Buy
import React from ‘react'
import glamorous from 'glamorous'
const Button = glamorous.button({
color: '#fff',
backgroundColor: 'pink'
}) .css-glamorous-button--1yceljy,
[data-css-glamorous-button--1yceljy] {
color: #fff;
background-color: pink;
}
<button
class="css-glamorous-button--1yceljy">
Button
</button>
browser
Buy
// render
<Button>Buy</Button>
Emotion
Buy
50
import { css } from 'emotion'
const base = css({
fontWeight: 600
})
const child = css`
${base};
color: pink;
background-color: black;
`
<p className={ child }>
Inheriting base styles
</p>
Inheriting base styles
Adaptable
53
Styled System
Buy
54
import styled from 'styled-components'
import { width } from 'styled-system'
const Box = styled.div`${width}`
const responsiveWidths = [ 1, 1/2, 1/4 ]
const App = () => (
<Box width={ responsiveWidths }>
100% below smallest breakpoint
50% from next breakpoint up
25% from next breakpoint up
</Box>
)
Styling Layout
Styled System
55
Adapt Styles to App State
Styling State
Styled Components
Buy
56
<Password />
Enter Password
import styled from 'styled-components'
const Input = styled.input`padding: 5px;`
const Password = Input.extend.attrs({
placeholder: 'Enter Password’
})
`
border-color: black;
`
<Input />
Styling State
Styled Components
Buy
57
<Password />
Enter Password
import styled from 'styled-components'
const Input = styled.input`padding: 5px;`
const Password = Input.extend.attrs({
placeholder: 'Enter Password’
})
`
border-color: ${props => props.error ? 'red' : 'black'};
`
<Password error />
Enter Password
<Input />
DeCSS
.Button {
color: #fff;
background: orange;
}
.Button-danger {
background: red;
}
import React from 'react'
import { Button } from './Button.css'
const MyButton = ({ children, danger }) => (
<Button tag=“button" danger={ danger }>
{children}
</Button>
)
Button.css
DeCSS
.Button {
color: #fff;
background: orange;
}
.Button-danger {
background: red;
}
import React from 'react'
import { Button } from './Button.css'
const MyButton = ({ children, danger }) => (
<Button tag=“button" danger={ danger }>
{children}
</Button>
)
Button.css
module: {
rules: [
{
test: /.css$/,
use: [
'style-loader',
'decss-loader/react',
'css-loader?modules
]
},
]
}
webpack.config
DeCSS
.Button {
color: #fff;
background: orange;
}
.Button-danger {
background: red;
}
import React from 'react'
import { Button } from './Button.css'
const MyButton = ({ children, danger }) => (
<Button tag="button" danger={ danger }>
{children}
</Button>
)
// render
<MyButton danger>Buy</MyButton>
Button.css
.button_Button_2V6 {
color: #fff;
background: orange;
}
.button_Button-danger_2nt {
background: red;
}
<button class="button_Button-danger_2nt
button_Button_2V6">
Buy
</button>
browser
Buy
Buy
61
Styling Elements
Global Styling
// Emotion
// set color of nav globally
const MyNav = styled(Nav)`
:global(.nav) {
color: pink;
}
`
// set box-sizing on all HTML elements
import { injectGlobal } from 'emotion'
injectGlobal`
* {
box-sizing: border-box;
}
`
/* CSS Modules */
// set color of nav globally
:global .nav {
color: pink;
}
Maintainable
dealing with
Dead & Unused CSS
Example Scenario
Buy
65
import './input.css'
const C1 = () => <input className="c1" />
const C2 = () => <input className="c2" />
input.css
.c1 {
padding: 1em;
}
.c2 {
padding: 2em
}
Buy
66
import './input.css'
const C1 = () => <input className="c1" />
const C2 = () => <input className="c2" />
const App = () => <div><C1 /><C2 /></div>
<style type="text/css">
.c1 {
padding: 1em;
}
.c2 {
padding: 2em
}
</style>
input.css
browser
Example Scenario
.c1 {
padding: 1em;
}
.c2 {
padding: 2em
}
Stop Using <C2 />
Buy
67
import './input.css'
const C1 = () => <input className="c1" />
const C2 = () => <input className="c2" />
const App = () => <div><C1 /></div>
.c1 {
padding: 1em;
}
.c2 {
padding: 2em
}
input.css
<style type="text/css">
.c1 {
padding: 1em;
}
.c2 {
padding: 2em
}
</style>
browser
Unused CSS
Buy
68
import './input.css'
const C1 = () => <input className="c1" />
const C2 = () => <input className="c2" />
const App = () => <div><C1 /></div>
input.css
<style type="text/css">
.c1 {
padding: 1em;
}
.c2 {
padding: 2em
}
</style>
browser
.c1 {
padding: 1em;
}
.c2 {
padding: 2em
}
Delete <C2 />
Buy
69
import './input.css'
const C1 = () => <input className="c1" />
const App = () => <div><C1 /></div>
input.css
<style type="text/css">
.c1 {
padding: 1em;
}
.c2 {
padding: 2em
}
</style>
browser
.c1 {
padding: 1em;
}
.c2 {
padding: 2em
}
Dead CSS
Buy
70
import './input.css'
const C1 = () => <input className="c1" />
const App = () => <div><C1 /></div>
input.css
<style type="text/css">
.c1 {
padding: 1em;
}
.c2 {
padding: 2em
}
</style>
browser
.c1 {
padding: 1em;
}
.c2 {
padding: 2em
}
Buy
71
import styled from 'react-emotion'
const C1 = styled.input`padding: 1em`
const C2 = styled.input`padding: 2em`
const App = () => <div><C1 /><C2 /></div>
<style type="text/css" data-emotion="">
.css-1ylegpj-C1 {
padding:1em;
}
.css-12zs2me-C2 {
padding:2em;
}
</style>
App.js
browser
using
Styled Components
Buy
72
import styled from 'react-emotion'
const C1 = styled.input`padding: 1em`
const C2 = styled.input`padding: 2em`
const App = () => <div><C1 /></div>
<style type="text/css" data-emotion="">
.css-1ylegpj-C1 {
padding:1em;
}
</style>
browser
there’s
No Unused / Dead CSS
Buy
73
import styled from 'react-emotion'
const C1 = styled.input`padding: 1em`
const C2 = styled.input`padding: 2em`
const App = () => <div><C1 /></div>
<style type="text/css" data-emotion="">
.css-1ylegpj-C1 {
padding:1em;
}
</style>
browser
automatic
Critical CSS
74
testing styles using
Snapshots
Buy
75
import React from 'react'
import styled from 'styled-components'
import renderer from 'react-test-renderer'
import 'jest-styled-components'
const Button = styled.button`color: pink;`
testing styles using
Snapshots
Buy
76
import React from 'react'
import styled from 'styled-components'
import renderer from 'react-test-renderer'
import 'jest-styled-components'
const Button = styled.button`color: pink;`
test('Button renders correctly', () => {
const button = renderer.create(<Button />).toJSON()
expect(button).toMatchSnapshot()
expect(button).toHaveStyleRule('color', 'pink')
})
testing styles using
Snapshots
Buy
77
import React from 'react'
import styled from 'styled-components'
import renderer from 'react-test-renderer'
import 'jest-styled-components'
const Button = styled.button`color: pink;`
test('Button renders correctly', () => {
const button = renderer.create(<Button />).toJSON()
expect(button).toMatchSnapshot()
expect(button).toHaveStyleRule('color', 'pink')
})
testing styles using
Snapshots
Buy
78
import React from 'react'
import styled from 'styled-components'
import renderer from 'react-test-renderer'
import 'jest-styled-components'
const Button = styled.button`color: pink;`
test('Button renders correctly', () => {
const button = renderer.create(<Button />).toJSON()
expect(button).toMatchSnapshot()
expect(button).toHaveStyleRule('color', 'pink')
})
testing styles using
Snapshots
exports[`Button renders correctly 1`] = `
.c0 {
color: pink;
}
<button
className="c0"
/>
`;
Button.spec.js.snap
Buy
79
import React from 'react'
import styled from 'styled-components'
import renderer from 'react-test-renderer'
import 'jest-styled-components'
const Button = styled.button`color: pink;`
test('Button renders correctly', () => {
const button = renderer.create(<Button />).toJSON()
expect(button).toMatchSnapshot()
expect(button).toHaveStyleRule('color', 'pink')
})
jest --watch
testing styles using
Snapshots
Scaleable
82
Server Side Rendering
CSS in JS
Buy
83
import React from 'react'
import { renderStylesToString } from 'emotion-server'
import { renderToString } from 'react-dom/server
import App from './App'
const html = renderStylesToString(renderToString(<App />))
Server Side Rendering
Buy
84
import React from 'react'
import { renderStylesToString } from 'emotion-server'
import { renderToString } from 'react-dom/server
import App from './App'
const html = renderStylesToString(renderToString(<App />))
<!DOCTYPE html>
<html lang="en">
<body><div id="root"><main data-reactroot=""><div><style data-emotion-
css="66u5jz">.css-66u5jz{padding:1em;}</style><input class="css-66u5jz e1c3ej80"/><style
data-emotion-css="186egwm">.css-186egwm{padding:2em;}</style><input class="css-186egwm
e1c3ej81"/></div></main></div>
<script type="text/javascript" src="/runtime.js"></script><script type="text/javascript"
src="/vendors~main.js"></script><script type="text/javascript" src="/main.js"></script></
body>
</html>
browser
Server Side Rendering
Buy
85
import React from 'react'
import { renderStylesToString } from 'emotion-server'
import { renderToString } from 'react-dom/server
import App from './App'
const html = renderStylesToString(renderToString(<App />))
<!DOCTYPE html>
<html lang="en">
<body><div id="root"><main data-reactroot=""><div><style data-emotion-
css="66u5jz">.css-66u5jz{padding:1em;}</style><input class="css-66u5jz e1c3ej80"/><style
data-emotion-css="186egwm">.css-186egwm{padding:2em;}</style><input class="css-186egwm
e1c3ej81"/></div></main></div>
<script type="text/javascript" src="/runtime.js"></script><script type="text/javascript"
src="/vendors~main.js"></script><script type="text/javascript" src="/main.js"></script></
body>
</html>
browser
Server Side Rendering
Buy
86
import React from 'react'
import { renderStylesToString } from 'emotion-server'
import { renderToString } from 'react-dom/server
import App from './App'
const html = renderStylesToString(renderToString(<App />))
<!DOCTYPE html>
<html lang="en">
<body><div id="root"><main data-reactroot=""><div><style data-emotion-
css="66u5jz">.css-66u5jz{padding:1em;}</style><input class="css-66u5jz e1c3ej80"/><style
data-emotion-css="186egwm">.css-186egwm{padding:2em;}</style><input class="css-186egwm
e1c3ej81"/></div></main></div>
<script type="text/javascript" src="/runtime.js"></script><script type="text/javascript"
src="/vendors~main.js"></script><script type="text/javascript" src="/main.js"></script></
body>
</html>
browser
Server Side Rendering
87
Right To Left Support
CSS in JS
CSS & i18n
Right to Left
88
import rtlCSSJS from 'rtl-css-js'
const styles = {
marginLeft: '50px',
borderLeft: '10px solid black',
background: 'linear-gradient(to left, pink, orange)'
}
const rtl = rtlCSSJS(styles)
console.log(JSON.stringify(rtl, null, ' '))
> {
"marginRight": "2em",
"borderRight": "10px solid black",
"background": "linear-gradient(to right, pink, orange)"
}
CSS & i18n
Right to Left
89
import rtlCSSJS from 'rtl-css-js'
const styles = {
marginLeft: '50px',
borderLeft: '10px solid black',
background: 'linear-gradient(to left, pink, orange)'
}
const rtl = rtlCSSJS(styles)
console.log(JSON.stringify(rtl, null, ' '))
>
{
"marginRight": "2em",
"borderRight": "10px solid black",
"background": "linear-gradient(to right, pink, orange)"
}
Themes
creating
Themes
91
import glamorous, { ThemeProvider } from 'glamorous'
const dark = { color: ‘pink’, background: ‘black’ }
const light = { color: ‘black’, background: ‘gray’ }
const Box = glamorous.div(({ theme }) => ({
color: theme.color, background: theme.background;
}))
creating
Themes
92
import glamorous, { ThemeProvider } from 'glamorous'
const dark = { color: ‘pink’, background: ‘black’ }
const light = { color: ‘black’, background: ‘gray’ }
const Box = glamorous.div(({ theme }) => ({
color: theme.color, background: theme.background;
}))
export default class App extends Component {
render () {
return(
<ThemeProvider theme={ dark }>
<Box>Theme color</Box>
</ThemeProvider>
)
}
}
creating
Themes
93
import glamorous, { ThemeProvider } from 'glamorous'
const dark = { color: ‘pink’, background: ‘black’ }
const light = { color: ‘black’, background: ‘gray’ }
const Box = glamorous.div(({ theme }) => ({
color: theme.color, background: theme.background;
}))
export default class App extends Component {
render () {
return(
<ThemeProvider theme={ dark }>
<Box>Theme color</Box>
</ThemeProvider>
)
}
}
Theme color
creating
Themes
94
import glamorous, { ThemeProvider } from 'glamorous'
const dark = { color: ‘pink’, background: ‘black’ }
const light = { color: ‘black’, background: ‘gray’ }
const Box = glamorous.div(({ theme }) => ({
color: theme.color, background: theme.background;
}))
export default class App extends Component {
render () {
return(
<ThemeProvider theme={ light }>
<Box>Theme color</Box>
</ThemeProvider>
)
}
}
Theme color
React Native
Kent C. Dodds
@kentcdodds
Mark Dalgleish
@markdalgleish
Oleg Isonen
@oleg008
Michele Bertoli
@MicheleBertoli
Tom Raviv
@RavivTom
Bruce Lawson
@brucel
Sunil Pai
@threepointone
Sultan Tarimo
@thysultan
Kye Hohenberger
@tkh44
Patrick Arminio
@patrick91
Phil Pluckthun
@_philpl
Max Stoiber
@mxstbr
Glen Maddern
@glenmaddern
Superpowers CSS in JS LeadersFrameworks
Styled Components
Emotion
Glamorous
Styled System
Glamor
React CSS Modules
Automation
Shareable
Adaptable
Scaleable
Maintainable
Joe Seifi
@joeseifi http://seifi.org https://github.com/joeshub/css-in-react
Christopher Chedeau
@vjeux
DeCSS

CSS in React - Will Change Transform

  • 1.
  • 2.
  • 3.
  • 4.
  • 6.
    @BODY fo(fa=he,si=18) @P co(nu=3,wi=80) (BODYfontSize=normal BGColor=white FGColor=black (H1 fontSize=largest BGColor=red FGColor=white) ) h1.font.size = 24pt 100% h2.font.size = 20pt 40% *LI.prebreak: 0.5 *LI.postbreak: 0.5 *OL.LI.label: 1 *OL*OL.LI.label: A (element H1 (make paragraph font-size: 14pt font-weight: 'bold)) (style a (block #f) ; format as inline phrase (color blue) ; in blue if you’ve got it (click (follow (attval 'href))) ; and on click, follow url LI { VertPos: Top = LeftSib . Actual Bottom; } A { if (getAttribute(self, "href") != "") then fgColor = "blue"; underlineNumber = 1; endif } tags.H1.color = "blue"; tags.p.fontSize = "14pt"; with (tags.H3) { color = "green"; } classes.punk.all.color = "#00FF00" ids.z098y.letterSpacing = "0.3em"
  • 7.
    RRP @BODY fo(fa=he,si=18) @P co(nu=3,wi=80) PWP (BODYfontSize=normal BGColor=white FGColor=black (H1 fontSize=largest BGColor=red FGColor=white) ) CHSS h1.font.size = 24pt 100% h2.font.size = 20pt 40% RRP *LI.prebreak: 0.5 *LI.postbreak: 0.5 *OL.LI.label: 1 *OL*OL.LI.label: A DSSSL (element H1 (make paragraph font-size: 14pt font-weight: 'bold)) RRP (style a (block #f) ; format as inline phrase (color blue) ; in blue if you’ve got it (click (follow (attval 'href))) ; and on click, follow url PSL LI { VertPos: Top = LeftSib . Actual Bottom; } A { if (getAttribute(self, "href") != "") then fgColor = "blue"; underlineNumber = 1; endif } JSSS tags.H1.color = "blue"; tags.p.fontSize = "14pt"; with (tags.H3) { color = "green"; } classes.punk.all.color = "#00FF00" ids.z098y.letterSpacing = "0.3em" Pre-CSS 1993-1996
  • 8.
  • 11.
  • 12.
    CSS Modular CSSCSS in JS OOCSS SMACS SUIT BEM ATOMIC 💄
  • 14.
    Super Powers of CSSin React - Automation - Sharable - Adaptable - Scalable - Maintainable
  • 15.
    Giving up Control, actuallygives you more control and new Super Powers
  • 16.
  • 17.
  • 18.
    There are only 2hard problems in Computer Science: cache invalidation & naming things Phil Karlton from Netscape
  • 19.
  • 20.
    regular css imports .btn{ color: #fff; background: pink;
 } button.css import './button.css'
  • 21.
    css-modules import styles from'./button.css' .btn { color: #fff; background: pink;
 } button.css
  • 22.
    css-modules import styles from'./button.css' console.log(styles) > { “btn": "button_btn_2Yt" } .btn { color: #fff; background: pink;
 } button.css
  • 23.
    import React from'react' import CSSModules from ‘react-css-modules' import styles from ‘./button.css’ @CSSModules(styles) const Button = ({ children }) => <button styleName=“btn”> {children} </button> React CSS Modules Buy .btn { color: #fff; background: pink;
 } button.css
  • 24.
    React CSS Modules .btn{ color: #fff; background: pink;
 } .button_btn_2Yt { color: #fff; background-color: pink; } <button class="button_btn_2Yt"> Buy </button> browser import React from 'react' import CSSModules from ‘react-css-modules' import styles from ‘./button.css’ @CSSModules(styles) const Button = ({ children }) => <button styleName=“btn”> {children} </button> // render <Button>Buy</Button> button.css Buy
  • 25.
    DeCSS .Button { color: #fff; background:orange; } import React from 'react' import { Button } from './Button.css' Button.css
  • 26.
    DeCSS .Button { color: #fff; background:orange; } import React from 'react' import { Button } from './Button.css' const MyButton = ({ children }) => ( <Button tag="button"> {children} </Button> ) // render <MyButton>Buy</MyButton> Button.css
  • 27.
    DeCSS .Button { color: #fff; background:orange; } .button_Button_2V6 { color: #fff; background: orange; } <button class="button_Button_2V6"> Buy </button> browser import React from 'react' import { Button } from './Button.css' const MyButton = ({ children }) => ( <Button tag="button"> {children} </Button> ) // render <MyButton>Buy</MyButton> Button.css Buy
  • 29.
  • 31.
  • 32.
  • 33.
  • 34.
    <button id="btn">
 Buy
 </button> $("#btn").click(() =>{ // take money
 } Buy HTML JavaScript
  • 35.
    <button id="btn">
 Buy
 </button> $("#btn").click(() =>{ // take money
 } Buy HTML JavaScript
  • 36.
  • 37.
  • 38.
    <button className="btn">
 Buy
 </button> .btn { color:#fff; background-color: pink; } Buy HTML CSS
  • 39.
  • 40.
    Styled Components Buy import Reactfrom 'react' import styled from 'styled-components'
  • 41.
    Styled Components Buy import Reactfrom 'react' import styled from 'styled-components' const Button = styled.button` color: #fff; background-color: pink; `
  • 42.
    Styled Components Buy import Reactfrom 'react' import styled from 'styled-components' const Button = styled.button` color: #fff; background-color: pink; ` .ctyFSz { color: #fff; background-color: pink; } .sc-bdVaJa { } <button class="sc-bdVaJa ctyFSz”> Buy </button> browser Buy // render <Button>Buy</Button>
  • 43.
    Styled Components Buy 43 // shared-lib exportconst Shared = ({ className }) => ( <div className={ className }>Sharing is caring!</div> ) // our-app import styled from 'styled-components' import { Shared } from 'shared-lib'
  • 44.
    Styled Components Buy 44 // shared-lib exportconst Shared = ({ className }) => ( <div className={ className }>Sharing is caring!</div> ) // our-app import styled from 'styled-components' import { Shared } from 'shared-lib' const Wrapped = styled(Shared)`color: pink;`
  • 45.
    Styled Components Buy 45 // shared-lib exportconst Shared = ({ className }) => ( <div className={ className }>Sharing is caring!</div> ) // our-app import styled from 'styled-components' import { Shared } from 'shared-lib' const Wrapped = styled(Shared)`color: pink;` <Shared /> Sharing is caring! <Wrapped /> Sharing is caring!
  • 46.
  • 47.
    Glamorous Buy import React from‘react' import glamorous from 'glamorous'
  • 48.
    Glamorous Buy import React from‘react' import glamorous from 'glamorous' const Button = glamorous.button({ color: '#fff', backgroundColor: 'pink' })
  • 49.
    Glamorous Buy import React from‘react' import glamorous from 'glamorous' const Button = glamorous.button({ color: '#fff', backgroundColor: 'pink' }) .css-glamorous-button--1yceljy, [data-css-glamorous-button--1yceljy] { color: #fff; background-color: pink; } <button class="css-glamorous-button--1yceljy"> Button </button> browser Buy // render <Button>Buy</Button>
  • 50.
    Emotion Buy 50 import { css} from 'emotion' const base = css({ fontWeight: 600 }) const child = css` ${base}; color: pink; background-color: black; ` <p className={ child }> Inheriting base styles </p> Inheriting base styles
  • 52.
  • 53.
  • 54.
    Buy 54 import styled from'styled-components' import { width } from 'styled-system' const Box = styled.div`${width}` const responsiveWidths = [ 1, 1/2, 1/4 ] const App = () => ( <Box width={ responsiveWidths }> 100% below smallest breakpoint 50% from next breakpoint up 25% from next breakpoint up </Box> ) Styling Layout Styled System
  • 55.
  • 56.
    Styling State Styled Components Buy 56 <Password/> Enter Password import styled from 'styled-components' const Input = styled.input`padding: 5px;` const Password = Input.extend.attrs({ placeholder: 'Enter Password’ }) ` border-color: black; ` <Input />
  • 57.
    Styling State Styled Components Buy 57 <Password/> Enter Password import styled from 'styled-components' const Input = styled.input`padding: 5px;` const Password = Input.extend.attrs({ placeholder: 'Enter Password’ }) ` border-color: ${props => props.error ? 'red' : 'black'}; ` <Password error /> Enter Password <Input />
  • 58.
    DeCSS .Button { color: #fff; background:orange; } .Button-danger { background: red; } import React from 'react' import { Button } from './Button.css' const MyButton = ({ children, danger }) => ( <Button tag=“button" danger={ danger }> {children} </Button> ) Button.css
  • 59.
    DeCSS .Button { color: #fff; background:orange; } .Button-danger { background: red; } import React from 'react' import { Button } from './Button.css' const MyButton = ({ children, danger }) => ( <Button tag=“button" danger={ danger }> {children} </Button> ) Button.css module: { rules: [ { test: /.css$/, use: [ 'style-loader', 'decss-loader/react', 'css-loader?modules ] }, ] } webpack.config
  • 60.
    DeCSS .Button { color: #fff; background:orange; } .Button-danger { background: red; } import React from 'react' import { Button } from './Button.css' const MyButton = ({ children, danger }) => ( <Button tag="button" danger={ danger }> {children} </Button> ) // render <MyButton danger>Buy</MyButton> Button.css .button_Button_2V6 { color: #fff; background: orange; } .button_Button-danger_2nt { background: red; } <button class="button_Button-danger_2nt button_Button_2V6"> Buy </button> browser Buy
  • 61.
    Buy 61 Styling Elements Global Styling //Emotion // set color of nav globally const MyNav = styled(Nav)` :global(.nav) { color: pink; } ` // set box-sizing on all HTML elements import { injectGlobal } from 'emotion' injectGlobal` * { box-sizing: border-box; } ` /* CSS Modules */ // set color of nav globally :global .nav { color: pink; }
  • 63.
  • 64.
  • 65.
    Example Scenario Buy 65 import './input.css' constC1 = () => <input className="c1" /> const C2 = () => <input className="c2" /> input.css .c1 { padding: 1em; } .c2 { padding: 2em }
  • 66.
    Buy 66 import './input.css' const C1= () => <input className="c1" /> const C2 = () => <input className="c2" /> const App = () => <div><C1 /><C2 /></div> <style type="text/css"> .c1 { padding: 1em; } .c2 { padding: 2em } </style> input.css browser Example Scenario .c1 { padding: 1em; } .c2 { padding: 2em }
  • 67.
    Stop Using <C2/> Buy 67 import './input.css' const C1 = () => <input className="c1" /> const C2 = () => <input className="c2" /> const App = () => <div><C1 /></div> .c1 { padding: 1em; } .c2 { padding: 2em } input.css <style type="text/css"> .c1 { padding: 1em; } .c2 { padding: 2em } </style> browser
  • 68.
    Unused CSS Buy 68 import './input.css' constC1 = () => <input className="c1" /> const C2 = () => <input className="c2" /> const App = () => <div><C1 /></div> input.css <style type="text/css"> .c1 { padding: 1em; } .c2 { padding: 2em } </style> browser .c1 { padding: 1em; } .c2 { padding: 2em }
  • 69.
    Delete <C2 /> Buy 69 import'./input.css' const C1 = () => <input className="c1" /> const App = () => <div><C1 /></div> input.css <style type="text/css"> .c1 { padding: 1em; } .c2 { padding: 2em } </style> browser .c1 { padding: 1em; } .c2 { padding: 2em }
  • 70.
    Dead CSS Buy 70 import './input.css' constC1 = () => <input className="c1" /> const App = () => <div><C1 /></div> input.css <style type="text/css"> .c1 { padding: 1em; } .c2 { padding: 2em } </style> browser .c1 { padding: 1em; } .c2 { padding: 2em }
  • 71.
    Buy 71 import styled from'react-emotion' const C1 = styled.input`padding: 1em` const C2 = styled.input`padding: 2em` const App = () => <div><C1 /><C2 /></div> <style type="text/css" data-emotion=""> .css-1ylegpj-C1 { padding:1em; } .css-12zs2me-C2 { padding:2em; } </style> App.js browser using Styled Components
  • 72.
    Buy 72 import styled from'react-emotion' const C1 = styled.input`padding: 1em` const C2 = styled.input`padding: 2em` const App = () => <div><C1 /></div> <style type="text/css" data-emotion=""> .css-1ylegpj-C1 { padding:1em; } </style> browser there’s No Unused / Dead CSS
  • 73.
    Buy 73 import styled from'react-emotion' const C1 = styled.input`padding: 1em` const C2 = styled.input`padding: 2em` const App = () => <div><C1 /></div> <style type="text/css" data-emotion=""> .css-1ylegpj-C1 { padding:1em; } </style> browser automatic Critical CSS
  • 74.
  • 75.
    Buy 75 import React from'react' import styled from 'styled-components' import renderer from 'react-test-renderer' import 'jest-styled-components' const Button = styled.button`color: pink;` testing styles using Snapshots
  • 76.
    Buy 76 import React from'react' import styled from 'styled-components' import renderer from 'react-test-renderer' import 'jest-styled-components' const Button = styled.button`color: pink;` test('Button renders correctly', () => { const button = renderer.create(<Button />).toJSON() expect(button).toMatchSnapshot() expect(button).toHaveStyleRule('color', 'pink') }) testing styles using Snapshots
  • 77.
    Buy 77 import React from'react' import styled from 'styled-components' import renderer from 'react-test-renderer' import 'jest-styled-components' const Button = styled.button`color: pink;` test('Button renders correctly', () => { const button = renderer.create(<Button />).toJSON() expect(button).toMatchSnapshot() expect(button).toHaveStyleRule('color', 'pink') }) testing styles using Snapshots
  • 78.
    Buy 78 import React from'react' import styled from 'styled-components' import renderer from 'react-test-renderer' import 'jest-styled-components' const Button = styled.button`color: pink;` test('Button renders correctly', () => { const button = renderer.create(<Button />).toJSON() expect(button).toMatchSnapshot() expect(button).toHaveStyleRule('color', 'pink') }) testing styles using Snapshots exports[`Button renders correctly 1`] = ` .c0 { color: pink; } <button className="c0" /> `; Button.spec.js.snap
  • 79.
    Buy 79 import React from'react' import styled from 'styled-components' import renderer from 'react-test-renderer' import 'jest-styled-components' const Button = styled.button`color: pink;` test('Button renders correctly', () => { const button = renderer.create(<Button />).toJSON() expect(button).toMatchSnapshot() expect(button).toHaveStyleRule('color', 'pink') }) jest --watch testing styles using Snapshots
  • 81.
  • 82.
  • 83.
    Buy 83 import React from'react' import { renderStylesToString } from 'emotion-server' import { renderToString } from 'react-dom/server import App from './App' const html = renderStylesToString(renderToString(<App />)) Server Side Rendering
  • 84.
    Buy 84 import React from'react' import { renderStylesToString } from 'emotion-server' import { renderToString } from 'react-dom/server import App from './App' const html = renderStylesToString(renderToString(<App />)) <!DOCTYPE html> <html lang="en"> <body><div id="root"><main data-reactroot=""><div><style data-emotion- css="66u5jz">.css-66u5jz{padding:1em;}</style><input class="css-66u5jz e1c3ej80"/><style data-emotion-css="186egwm">.css-186egwm{padding:2em;}</style><input class="css-186egwm e1c3ej81"/></div></main></div> <script type="text/javascript" src="/runtime.js"></script><script type="text/javascript" src="/vendors~main.js"></script><script type="text/javascript" src="/main.js"></script></ body> </html> browser Server Side Rendering
  • 85.
    Buy 85 import React from'react' import { renderStylesToString } from 'emotion-server' import { renderToString } from 'react-dom/server import App from './App' const html = renderStylesToString(renderToString(<App />)) <!DOCTYPE html> <html lang="en"> <body><div id="root"><main data-reactroot=""><div><style data-emotion- css="66u5jz">.css-66u5jz{padding:1em;}</style><input class="css-66u5jz e1c3ej80"/><style data-emotion-css="186egwm">.css-186egwm{padding:2em;}</style><input class="css-186egwm e1c3ej81"/></div></main></div> <script type="text/javascript" src="/runtime.js"></script><script type="text/javascript" src="/vendors~main.js"></script><script type="text/javascript" src="/main.js"></script></ body> </html> browser Server Side Rendering
  • 86.
    Buy 86 import React from'react' import { renderStylesToString } from 'emotion-server' import { renderToString } from 'react-dom/server import App from './App' const html = renderStylesToString(renderToString(<App />)) <!DOCTYPE html> <html lang="en"> <body><div id="root"><main data-reactroot=""><div><style data-emotion- css="66u5jz">.css-66u5jz{padding:1em;}</style><input class="css-66u5jz e1c3ej80"/><style data-emotion-css="186egwm">.css-186egwm{padding:2em;}</style><input class="css-186egwm e1c3ej81"/></div></main></div> <script type="text/javascript" src="/runtime.js"></script><script type="text/javascript" src="/vendors~main.js"></script><script type="text/javascript" src="/main.js"></script></ body> </html> browser Server Side Rendering
  • 87.
    87 Right To LeftSupport CSS in JS
  • 88.
    CSS & i18n Rightto Left 88 import rtlCSSJS from 'rtl-css-js' const styles = { marginLeft: '50px', borderLeft: '10px solid black', background: 'linear-gradient(to left, pink, orange)' } const rtl = rtlCSSJS(styles) console.log(JSON.stringify(rtl, null, ' ')) > { "marginRight": "2em", "borderRight": "10px solid black", "background": "linear-gradient(to right, pink, orange)" }
  • 89.
    CSS & i18n Rightto Left 89 import rtlCSSJS from 'rtl-css-js' const styles = { marginLeft: '50px', borderLeft: '10px solid black', background: 'linear-gradient(to left, pink, orange)' } const rtl = rtlCSSJS(styles) console.log(JSON.stringify(rtl, null, ' ')) > { "marginRight": "2em", "borderRight": "10px solid black", "background": "linear-gradient(to right, pink, orange)" }
  • 90.
  • 91.
    creating Themes 91 import glamorous, {ThemeProvider } from 'glamorous' const dark = { color: ‘pink’, background: ‘black’ } const light = { color: ‘black’, background: ‘gray’ } const Box = glamorous.div(({ theme }) => ({ color: theme.color, background: theme.background; }))
  • 92.
    creating Themes 92 import glamorous, {ThemeProvider } from 'glamorous' const dark = { color: ‘pink’, background: ‘black’ } const light = { color: ‘black’, background: ‘gray’ } const Box = glamorous.div(({ theme }) => ({ color: theme.color, background: theme.background; })) export default class App extends Component { render () { return( <ThemeProvider theme={ dark }> <Box>Theme color</Box> </ThemeProvider> ) } }
  • 93.
    creating Themes 93 import glamorous, {ThemeProvider } from 'glamorous' const dark = { color: ‘pink’, background: ‘black’ } const light = { color: ‘black’, background: ‘gray’ } const Box = glamorous.div(({ theme }) => ({ color: theme.color, background: theme.background; })) export default class App extends Component { render () { return( <ThemeProvider theme={ dark }> <Box>Theme color</Box> </ThemeProvider> ) } } Theme color
  • 94.
    creating Themes 94 import glamorous, {ThemeProvider } from 'glamorous' const dark = { color: ‘pink’, background: ‘black’ } const light = { color: ‘black’, background: ‘gray’ } const Box = glamorous.div(({ theme }) => ({ color: theme.color, background: theme.background; })) export default class App extends Component { render () { return( <ThemeProvider theme={ light }> <Box>Theme color</Box> </ThemeProvider> ) } } Theme color
  • 95.
  • 98.
    Kent C. Dodds @kentcdodds MarkDalgleish @markdalgleish Oleg Isonen @oleg008 Michele Bertoli @MicheleBertoli Tom Raviv @RavivTom Bruce Lawson @brucel Sunil Pai @threepointone Sultan Tarimo @thysultan Kye Hohenberger @tkh44 Patrick Arminio @patrick91 Phil Pluckthun @_philpl Max Stoiber @mxstbr Glen Maddern @glenmaddern Superpowers CSS in JS LeadersFrameworks Styled Components Emotion Glamorous Styled System Glamor React CSS Modules Automation Shareable Adaptable Scaleable Maintainable Joe Seifi @joeseifi http://seifi.org https://github.com/joeshub/css-in-react Christopher Chedeau @vjeux DeCSS