const MyStyledDiv = styled.div` font-size: 20px; text-align: center; `
Introducing glamorous 💄
Kent C. Dodds
80014

The styled-component is certainly an impressive project that is great for people writing a lot of CSS. But coming from JS perspective, I have some reservations. In one word — the cost of context switch.

The above code is really a hybrid of two different languages — CSS and JavaScript. Each has it own syntax. Yes, you can neatly use the brand new tagged template literals, but conceptually you are still using it to facilitate the hack of embedding one language into another. As opposed to using directly native JS objects with full JS power:

// declare styles in single JavaScript-native object literal
const style = {
fontSize: '20px',
textAlign: 'center'
}
// and get your styled div in one line
const myStyledDiv = div().setStyle(style)
// or in the curried function style
const myStyledDiv = setStyle(style)(div())

/* or with general reusable factory function */
const createMyStyledDiv = (props, children) => setStyle(style)(div(props, children))
// or in the variadic function style since div() already supports both props and children, each being optional
const createMyStyledDiv = (...args) => setStyle(style)(div(...args))
// or if you love to compose functions
const createMyStyledDiv = compose(
setStyle(style),
div
)
// or use pipe if you like going in the data flow direction
const createMyStyledDiv = pipe(
div,
setStyle(style)
)
// and then get your Div quickly with
const myStyledDiv = createMyStyledNode({style})

/* or with reusable utility functions */
const setFontSize = fontSize => vnode => 
vnode.setStyle({fontSize})
const setTextAlign = textAlign => vnode =>
vnode.setStyle({textAlign})
// and then compose function style
const setMyStyle = vnode => compose(
setFontSize('20px'),
setTextAlign('center')
)
// or the fluent style
const setMyStyle = vnode =>
vnode.setFontStyle('20px')
.setTextAlign('center')
// and then all you need to write is this:
const myStyleDiv = setMyStyle(div())

The point I am making here is that all of these options are instantly available and readable to anyone knowing plain JavaScript. You don’t even need to know any CSS to use the styles settings!

I think there is great power here for a more flexible, reusable and concise code, and hence more maintainable. And it is all native JS, so all your tools to manage, build, test are instantly available! Use the same tools you are already using to test all your CSS as simple pure functions!

Yes, you can still recreate some flexibility with the embedded CSS. But you would have to go extra mile, back-and-forth context switching between two languages, and add the extra layer between two separate syntaxes every time.

But there is even further cost beyond this extra layer, which is to encourage more of the CSS intuition and more advanced CSS usage, which might eventually cause you hit the wall later on, as was one of the very reasons for this library to exist :)

That is BTW the same reservation I have about the JSX (and it is not just me). The context switch cost is there. Now you are in the “HTML” mode. And now you are out. And now your are back again. And then the official ReactJS doc suggests us to write

const App = () =>
<SplitPane
left={
<Contacts />
}
right={
<Chat />
} />

which, removing all the context switching, becomes simply

const App = () => SplitPane({
left: Contacts(),
right: Chat()
})

Somehow it reminds me how it was common not so long ago to write HTML embedded into strings in JavaScript. And then it became a popular “anti-pattern” and got “out of fashion”. Pages were written, hours reading, time spent, code rewritten. With https://codereview.stackexchange.com/ still full of those “anti-pattern”.

And now we have a very similar fashion to embed the CSS into JS. But the history may repeat as it usually does :)