DEV Community

Alan Patrick
Alan Patrick

Posted on

Three concepts of the styled-components library

Introduction

Lately, I've been playing with styled-components. It is a CSS-in-JS library that uses tagged template literals. I want to talk about three concepts that I got puzzled by: Interpolation, GlobalStyle and ThemeProvider.

What is Interpolation?

Interpolation is adapting a component based on the props passed to it; meaning, you can inject values through props. For example:

const MockElement = styled.div`
  --size: ${(props) => (props.big ? '100px' : '50px')};
  width: var(--size);
  height: var(--size);
  background-color: yellowgreen;
`;

render(
  <div>
    // This renders a 50x50 square, because there was no "big" prop
    <MockElement />
    // This renders a 100x100 square, because "big" was passed
    <MockElement big />
  <div>
)
Enter fullscreen mode Exit fullscreen mode

So you can use props as truthy values. What about custom values? That works too!

const MockElement = styled.div`
  background-color: ${props => props.color ? props.color : 'yellowgreen'};

  --size: ${(props) => (props.big ? '100px' : '50px')};
  width: var(--size);
  height: var(--size);
`;

render(
  <div>
    // This renders a blue square
    <MockElement color='blue'/>
    // This renders... no color??
    <MockElement color />
  <div>
)
Enter fullscreen mode Exit fullscreen mode

Styled props are truthy by default, but since no value was passed, nothing gets rendered. To use the default value with this technique, you either skip the prop entirely, or you pass a null.

But BEWARE! You must pass a function when interpolating a value, or the code breaks. Something like the following wouldn't work:

const MockElement = styled.div`
  background-color: ${props.color}; /* It must be a function */
`;
Enter fullscreen mode Exit fullscreen mode

Must the function be inline? No! You can simply pass any function as a callback:

function declaredFunction (props) {
  let scale = `${props.factor * 50}px`
  return scale
}

const MockElement = styled.div`
  --size: ${declaredFunction};
  width: var(--size);
  height: var(--size);
  background-color: ${props => props.color ? props.color : 'yellowgreen'};
`;

render(
  <div>
    // This renders a 150x150, yellowgreen square
    <MockElement big color={null} factor={3}/>
  <div>
)
Enter fullscreen mode Exit fullscreen mode

This marks the end of exploring interpolation. On to the next!

What is GlobalStyle?

Self-explanatory as the name is, a GlobalStyle component is used to define general styling rules for the application. A close comparison would be using an index.css file that gets imported and bundled before all other stylesheets, thus being overwritten by css modules that follow it later.

Using a global style is fairly simple! First, you must create the GlobalStyle.js file, like so:

import { createGlobalStyle } from 'style-components';

const GlobalStyle = createGlobalStyle`
  /* Insert global styling here */
`;

export default GlobalStyle;
Enter fullscreen mode Exit fullscreen mode

Then, put the component...anywhere, really. At least, in the few tests I did, I put the component anywhere within the project and it worked just fine. However, for the sake of organization, I've put in my routing system (with react-router), like so:

# App.js

import GlobalStyle from './utils/GlobalStyle';

function App() {
  return (
    <BrowserRouter>
      <GlobalStyle />
      <Routes>
        {/*The routes and elements go here*/}
      </Routes>
    </BrowserRouter>
  );
}
Enter fullscreen mode Exit fullscreen mode

Cool! On to the final topic: ThemeProvider.

What is ThemeProvider?

ThemeProvider is a source of universal props to all its children. You must put the component at the root of your project, if you want all components to have access to it.

So, if you use App.js as your root, you could do something like:

#App.js
import { ThemeProvider } from 'styled-components';

const themeObject = {
  button : {
    primary : {
      background: 'lightblue',
      color: 'white',
    },
    secondary: {
      /* other keywords*/
    }
  }
}

function App() {
  return (
    <ThemeProvider theme={themeObject}>
      <CoolButton />
    </ThemeProvider>
  );
}
Enter fullscreen mode Exit fullscreen mode

That themeObject becomes accessible to all objects that are children of ThemeProvider. You use the theme prop through interpolation, like this:

#CoolButton.styled.js
import styled from 'styled-components';

const CoolButton = styled.button`
  background-color: ${props => props.theme.button.primary.background};
  /* As seen above and below, you just need to access the string from the theme object */
  color: ${props => props.theme.button.primary.color};
`
Enter fullscreen mode Exit fullscreen mode

You can also combine all three components, by making GlobalComponent a child of ThemeProvider and interpolating values as needed. One useful example is setting the font family.

# theme.js

const theme = {
  heading: "Cool Heading",
  subHeading: "Cute Heading"
};

export default theme;
Enter fullscreen mode Exit fullscreen mode
# GlobalStyle.js

import { createGlobalStyle } from 'styled-components';
import coolFontPath from './font-file1.woff';
import cuteFontPath from './font-file2.woff';

const GlobalStyle = createGlobalStyle`
  @font-face {
    font-family: 'Cool Heading';
    src: url(${coolFontPath};
  }

  @font-face {
    font-family: 'Cute Heading';
    src: url(${cuteFontPath};
  }

  h1 {
    font-family: ${props => props.theme.heading};
  }

  span.subheading {
    font-family: ${props => props.theme.subHeading}
  }
`
export default GlobalStyle;
Enter fullscreen mode Exit fullscreen mode
# App.js

import GlobalStyle from './GlobalStyle.js';
import theme from './theme.js';
import { ThemeProvider } from 'styled-components';

const App = () => {
  return (
  <ThemeProvider theme={theme}>
    <h1>I belong to the Cool Heading family</h1>
    <span className='subheading'>
      I belong to the Cute Heading family
    </span>
  </ThemeProvider>
  );
}
Enter fullscreen mode Exit fullscreen mode

Summary

So there you have it! This was the exploration of three important concepts of the styled-library: Interpolation, GlobalStyling and ThemeProvider. Hope it was of use!

Top comments (0)