CSS in JS
-
beware the Hype!
CSSconf Budapest, Kathrin Holzmann
I love Makeup Tutorials




π―ββοΈπ―ββοΈπ―ββοΈπ―ββοΈ


π―ββοΈπ―ββοΈπ―ββοΈ


π―ββοΈπ―ββοΈπ―ββοΈ
==






CSS is the Makeup of the Web
π¨πΏβπ»π©πΎβπ»π©πΌβπ»π¨π½βπ»π©π»βπ»π¨πΌβπ»


π¨πΏβπ»π©πΎβπ»π©πΌβπ»π¨π½βπ»π©π»βπ»π¨πΌβπ»
==




#ReactGate
The Hype is Real!
Take nobody's word for it
It is an expression of the determination of Fellows to withstand the domination of authority and to verify all statements by an appeal to facts determined by experiment

What is Wrong with CSS?
HTML
CSS
First Paint
CSS is Render Blocking
"CSS is a render blocking resource. Get it to the client as soon and as quickly as possible to optimize the time to first render"
What can we do?
Use HTTP2
HTML
CSS
First Paint
Split your CSS
First Paint
JavaScript Chunk
(HTML & CSS)

What tools to use?
βNPM Package for React

π Write your CSS within your JS
βοΈ Configuration via Babel Plugin
βοΈ Emotion
yarn add styled-componentsimport styled from 'styled-components'
return ()yarn add styled-componentsimport styled from 'styled-components'
const TextField = styled.textarea`
width: 800px;
height: 250px;
display: block;
`
return ()yarn add styled-componentsimport styled from 'styled-components'
const TextField = styled.textarea`
width: 800px;
height: 250px;
display: block;
`
return (<TextField />)
βBundler for node
π combines assets & JS and splitsΒ it
βοΈ webpack config file
βοΈ Parcel
module.exports = {
module: {
rules: [
{
test: /\.css$/,
loader: 'css-loader',
options: {
sourceMap: true,
},
},
],
},import css from 'file.css';Features to fact check?
π Fast Loading
π€ Naming & Scoping
π Props & State for styling
1.) Are we fast yet?

π¦Vanilla CSS
π Styled Components
π¦ Webpack with CSS Loader

Chrome performance tool
π LoadingΒ
- Size of the files
- Connection of the user
βοΈ Scripting
- Complexity of the script
- Size of the file
- Used device
| Loading | Scripting | Sum | |
|---|---|---|---|
| π¦Vanilla | 16,9 | 100,4 | 117,3 |
| π¦Vanilla & Bootstrap | 21,3 | 105,0 | 126,3 |
| π¦Webpack | 11,0 | 112,0 | 123,0 |
| π Styled Components | 7,9 | 150,0 | 157,9 |
why is that?


const BlogContainer = styled.section`
...`
class Blog extends React.Component {
return (
<BlogContainer>
{...}
</BlogContainer>
);
};import './blog.css';
class Blog extends React.Component {
return (
<section className="blogContainer">
{...}
</section>
);
};Styled Components
Webpack


Styled Components
Webpack
π Small Web Applications - Vanilla CSS is fine
Learnings
πCSS in JS strong on bigger Applications
π Scripting time increases
2) Can we Scope now?
<button class="button primary" />.button
background-color: SkyBlue
.button.primary
background-color: Plum
.primary
background-color: SpringGreen
<button class=βmyButton primary special mp-0 card__button--special pull-right md-6 js-runFunctionβ />Styled Components
const TextField
return (
);const TextField = styled.textarea`
width: 800px;
height: 250px;
display: block;
`;
return (
);const TextField = styled.textarea`
width: 800px;
height: 250px;
display: block;
`;
return (
<TextField />
);Rendered
<textarea class="sc-bdVaJa gKGhKY" />.gKGhKY {
width: 800px;
height: 250px;
display: block;
}
Where is my code coming from?
What do these classes mean?
What about this second class?



yarn add --dev babel-plugin-styled-components{
"plugins": ["babel-plugin-styled-components"]
}babel config
yarn add babel-plugin-macros --devimport styled from 'styled-components/macro';Styled Component js
<textarea
class="
CommentForm_TextField-sc-9uworz-3
jFJrEI
"
/>Rendered
beware the wrapocalypse
WrapperComponent extends React.Component {
const StyledWrapper = styled(Wrapper)``
return (<StyledWrapper />)
}const Wrapper = styled.div`...`;const Wrapper = styled(WrapperComponent)`...`;Components/Wrapper.js
Classes/WrapperComponent.js
Container/Blog.js
<div
class="
Wrapper-sc-13l2abh-0
Blog__Wrapper-sc-164h82l-1
kqreen
WrapperComponent__StyledWrapper-sc-1wfwx7d-0
gTiizE"
/>Wrapocalypse
.gTiizE {
border: solid 1px purple;
display: flex;
}
.kqreen {
background-color: SkyBlue;
margin: 25px;
}
.gkdfKN {
font-size: 16px;
}WebPack
Naming COnvention: BEM
.card
.card__image
.card__description
.card__button--primary
.card__button--secondary
Design Patterns: Atomic Design
Atom
Molecule
Organism
Design systemΒ
βοΈ
BEM + ATOMIC DESIGN
<textarea
class="
CommentForm__TextField-sc-9uworz-3
jFJrEI
"
/><textarea
class="commentForm__textField"
/>Styled Components
DESIGN SYSTEM
BUT naming is hard!!!

Questions to Ask your Designer
- What problem of the user should it solve?
- Is it a variation of a existing component?
- Is it a combination of existing components?
- Whats its semantic meaning
Learnings
π Generated naming lowers maintenance
βοΈ Pattern and Conventions are still needed
π£ Collaborate with your Designers
3) can we have props?
Primary
Secondary
Inactive
Inactive
State changes appearance
Default
Inactive
<button class="button button--primary" />
<button class="button button--secondary" />
<button class="button button--secondary
button--inactive" /><Button variant='primary' />
<Button variant='secondary' />
<Button variant='secondary'
inactive = {this.state.inactive} />Classic approach
What we want
Styled Components
const Button = styled.button`
background:
color:
opacity:
`;const Button = styled.button`
background: ${props =>
};
color: ${props =>
};
opacity: ${props =>
};
`;const Button = styled.button`
background: ${props =>
props.variant === 'primary' ? 'cadetblue'
};
color: ${props =>
props.variant === 'primary' ? 'ivory'
};
opacity: ${props =>
};
`;const Button = styled.button`
background: ${props =>
props.variant === 'primary' ? 'cadetblue'
: props.variant === 'secondary' ?
'lavender'
};
color: ${props =>
props.variant === 'primary' ? 'ivory'
: props.variant === 'secondary' ?
'ivory'
};
opacity: ${props =>
};
`;const Button = styled.button`
background: ${props =>
props.variant === 'primary' ? 'cadetblue'
: props.variant === 'secondary' ?
'lavender'
: 'antiquewhite'
};
color: ${props =>
props.variant === 'primary'? 'ivory'
: props.variant === 'secondary' ?
'ivory'
: 'grey'
};
opacity: ${props =>
};
`;const Button = styled.button`
background: ${props =>
props.variant === 'primary' ? 'cadetblue'
: props.variant === 'secondary' ?
'lavender'
: 'antiquewhite'
};
color: ${props =>
props.variant === 'primary'? 'ivory'
: props.variant === 'secondary' ?
'ivory'
: 'grey'
};
opacity: ${props =>
props.inactive ? 0.3 : 1
};
`;Rendered
<button class="
Button-sc-1c1bx2q-0
jMkYSM
"
/>.jMkYSM {
background: lavender;
color: ivory;
opacity: 0.3;
}props:{
"variant": "secondary",
"inactive": true,
"children": "Send"
}
Webpack?
.button {
background: antiquewhite;
color: grey;
}.button {
background: antiquewhite;
color: grey;
&--primary
{
color: ivory;
}
&--primary {
background: cadetblue;
}
}.button {
background: antiquewhite;
color: grey;
&--primary,
&--secondary {
color: ivory;
}
&--primary {
background: cadetblue;
}
&--secondary {
background: lavender;
}
}.button {
background: antiquewhite;
color: grey;
&--primary,
&--secondary {
color: ivory;
}
&--primary {
background: cadetblue;
}
&--secondary {
background: lavender;
}
&--inactive {
opacity: 0.3;
}
}
const Button = (props) => {
return (
<button {...other}>
{children}
</button>
);
};
import classNames from 'classnames';
const Button = (props) => {
return (
<button {...other}>
{children}
</button>
);
};
import classNames from 'classnames';
const Button = (props) => {
const {
variant,
inactive
} = props;
return (
<button {...other}>
{children}
</button>
);
};
import classNames from 'classnames';
const Button = (props) => {
const {
variant,
inactive
} = props;
const classes = classNames(
'button',
`button--${variant}`,
{ 'button--inactive': inactive }
);
return (
<button {...other}>
{children}
</button>
);
};
import classNames from 'classnames';
const Button = (props) => {
const {
variant,
inactive
} = props;
const classes = classNames(
'button',
`button--${variant}`,
{ 'button--inactive': inactive }
);
return (
<button className={classes} {...other}>
{children}
</button>
);
};
Button.propTypes = {
variant: PropTypes.oneOf(['',
'primary',
'secondary'
]),
inactive: PropTypes.bool
}
Button.defaultProps = {
variant: '',
inactive: false
}<Button variant="primary" />
<Button variant="seondary" />
<Button variant="secondary"
inactive={this.state.inactive}
/>Usage
<button class="button button--primary" />
<button class="button button--secondary" />
<button class="
button
button--secondary
button--inactive"
/>
Rendered
Learnings
βοΈ Patterns and Conventions helpful in both solutions
π No link between props and CSS for Styled-Components
β£οΈ Mixing design and function props can be dangerous
π Fast Loading
π€ Naming & Scoping
π Props & State for styling
π
π¦
β
β
π
βοΈ
βοΈ
π¨
Summary
βοΈ
βοΈ
π
Β π°
tools over
conventions & Patterns?
it's not an or question
Tools should support you to retain conventions & Patterns
Thank you
@thecakedesk
CSS in JS - beware the Hype!
By Kathrin Holzmann
CSS in JS - beware the Hype!
Everyone is hyped about CSS in JS - but is it really worth the hype? Or are there already ways to solve the Problems - maybe even in a better way?
- 1,358