Should I use styled components?

You may have asked yourself if you shouldn’t invest more time getting started with this thing called styled components (or CSS-in-JS). They get heavily promoted in modern front-end application frameworks. And sure, they look interesting.

While it depends may be the only right answer, sometimes you might be simply making things more difficult than really needed. You’re fixing the wrong problem.

Take for example the SCSS code.

$blue = #5DBCD2;

@mixin button-styles($bg-color, $color) {
  background: $bg-color;
  color: $color;
  border: none;
  border-radius: 0.20em;
  &:hover{
      background: darken($bg-color, 6%);
      cursor: pointer;
  }
}

.button {
  @include button-styles(#ddd, black)
}

.button--primary {
  @include button-styles($blue, white)
}

To pair with a simple component along the lines of:

const Buttons = props => (
  <>
    <button className="button">Default</button>
    <button className="button--primary">Primary</button>
  </>
)
export default Buttons

It looks like smart reuse of a button-style mixin, saving you to type things twice. It also looks smart, because it seems to follow a well established naming convention called BEM (although is it really BEM?).

The code above was inspired by an online discussion. The author suggested something along the lines of:

import themeVars from "myTheme"
import styled from "styled-components"
import { darken } from "polished"

const Button = styled.button`
  background: ${({ background }) => background || "#ddd"};
  color: ${({ color }) => color || "black"};
  border: none;
  border-radius: 0.25em;
  :hover {
    background: ${({ background }) => darken(0.05, background || "#ddd")};
  }
`

const Buttons = () => {
  const { blue } = themeVars.colors;
  return (
    <>
      <Button>Default</Button>
      <Button background={blue} color={"white"}>Primary</Button>
    </>
  )
}
export default Buttons

You might think this is better when you’re used to writing the earlier mentioned SCSS/SASS, because it skips the ‘unnecessary’ translation to primary/default button classes. It may not be smaller in line length, but everything is nicely packed together as a single component. Ready for re-use. By including a theme object, it is easy to reuse elements and colours, useful to keep things consistent. You could even use it to pull out default margin’s and radia.

Well. Learn CSS again. There is a C in CSS, the cascade. Inheritance is built-in.

With good ol’ CSS you’d write:

.button {
  background: #ddd;
  color: #000;
  border: none;
  border-radius: 0.25em;
  &:hover{
      background: #ccc; /*estimation*/
      /* cursor: pointer; <- also don't: another discussion */
  }
}

.button--primary {
  background: #5DBCD2;
  color: #fff;
  &:hover{
      background: #4DACC2; /*estimation*/
  }
}

The HTML would be:

<button class="button"></button>
<button class="button button--primary”></button>

I also fixed classes here to make it proper BEM. In BEM, what the original author seems to be using, learns that modifiers modify, they are not the full styled element itself. Let’s not over duplicate & complicate things.