DEV Community

Cover image for You Might Not Need styled-components
Will Munslow
Will Munslow

Posted on

You Might Not Need styled-components

styled-components can be quite nice for whipping up components but for old farts like me that are more familiar with old-timey CSS, I prefer to use CSS Modules.

When using CSS Modules, we quickly find out that while somethings are simpler (media queries) some things are not so easy (how the $@^% do I use a theme?).

Theming

styled-components has a ThemeProvider which is nice. Grab some JSON from a server somewhere and pass it to the ThemeProvider and you can use it in your styles.

We can do that, too. First, we make a Theme Context component. The entire thing is 4 lines, one line is blank and we probably don't even need the first line, anyway...

import { createContext } from "react";

export const ThemeContext = createContext();
export const ThemeProvider = ThemeContext.Provider;
Enter fullscreen mode Exit fullscreen mode

To use it, we import the ThemeProvider, then wrap it around some JSX that we need to style:

import { ThemeProvider } from "./ThemeContext";

<ThemeProvider value={theme}>
  <Button>Press</Button>
</ThemeProvider>
Enter fullscreen mode Exit fullscreen mode

Here is a simplified example of a Button component using the theme:

import React, { useContext } from "react";
import styles from "./Button.module.css";
import { ThemeContext } from "./ThemeContext";

export const Button = (props) => {
  const theme = useContext(ThemeContext);

  const style = {
    "--bg-color": theme.backgroundColor,
    "--fg-color": theme.foregroundColor,
    ...props.style
  };

  return (
    <button
      className={styles.Button}
      style={style}
    />
  );
};
Enter fullscreen mode Exit fullscreen mode

The values we need in the theme are passed to the CSS through the style attribute. The CSS module can use the CSS variables like so:

.Button {
  color: var(--fg-color);
  background-color: var(--bg-color);
}
Enter fullscreen mode Exit fullscreen mode

Adapting Based On Props

Sometimes you want to change the styles on a component based on some props. This becomes quite easy with CSS.

<Button size="large">
  Primary Large
</Button>
Enter fullscreen mode Exit fullscreen mode

CSS

.Button {
  font-size: 14px;
}

.Button[data-size=large] {
  font-size: 16px;
}
Enter fullscreen mode Exit fullscreen mode

Window.matchMedia

The last trick is rather rare, but I ran into an issue where a breakpoint was not known in advance and I had to use logic in javascript to determine if a class should be added to a component or not.

Window.matchMedia allowed me to solve this problem.

This allowed my component to accept a breakpoint prop and add a CSS class if the window was sized smaller than the breakpoint.

const maxWidth = width =>
  window.matchMedia(`(max-width: ${width}px)`).matches;

const getItemClasses = breakpoint => {
  const names = [styles.Item];
  if (maxWidth(breakpoint)) names.push(styles.ItemSmall);
  return names.join(" ");
};

return (
  <div className={getItemClasses(breakpoint)}>{children}</div>
);
Enter fullscreen mode Exit fullscreen mode

Conclusion

These tricks covered the features of styled-components that I used but allowed me to use CSS Modules instead. I hope you find them useful.

Top comments (0)