CSSconf Budapest, Kathrin Holzmann
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
HTML
CSS
First Paint
"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"
HTML
CSS
First Paint
First Paint
JavaScript Chunk
(HTML & CSS)
β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';π Fast Loading
π€ Naming & Scoping
π Props & State for styling
π¦Vanilla CSS
π Styled Components
π¦ Webpack with CSS Loader
| 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 |
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>
);
};π Small Web Applications - Vanilla CSS is fine
πCSS in JS strong on bigger Applications
π Scripting time increases
<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β />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 />
);<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"]
}yarn add babel-plugin-macros --devimport styled from 'styled-components/macro';<textarea
class="
CommentForm_TextField-sc-9uworz-3
jFJrEI
"
/>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"
/>.gTiizE {
border: solid 1px purple;
display: flex;
}
.kqreen {
background-color: SkyBlue;
margin: 25px;
}
.gkdfKN {
font-size: 16px;
}.card
.card__image
.card__description
.card__button--primary
.card__button--secondary
Atom
Molecule
Organism
BEM + ATOMIC DESIGN
<textarea
class="
CommentForm__TextField-sc-9uworz-3
jFJrEI
"
/><textarea
class="commentForm__textField"
/>π Generated naming lowers maintenance
βοΈ Pattern and Conventions are still needed
π£ Collaborate with your Designers
Primary
Secondary
Inactive
Inactive
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} />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
};
`;<button class="
Button-sc-1c1bx2q-0
jMkYSM
"
/>.jMkYSM {
background: lavender;
color: ivory;
opacity: 0.3;
}props:{
"variant": "secondary",
"inactive": true,
"children": "Send"
}.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}
/><button class="button button--primary" />
<button class="button button--secondary" />
<button class="
button
button--secondary
button--inactive"
/>βοΈ 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
β
β
π
βοΈ
βοΈ
π¨
βοΈ
βοΈ
π
Β π°
@thecakedesk