• 18-19 College Green, Dublin 2
  • 01 685 9088
  • info@cunninghamwebsolutions.com
  • cunninghamwebsolutions
    Cunningham Web Solutions
    • Home
    • About Us
    • Our Services
      • Web Design
      • Digital Marketing
      • SEO Services
      • E-commerce Websites
      • Website Redevelopment
      • Social Media Services
    • Digital Marketing
      • Adwords
      • Social Media Services
      • Email Marketing
      • Display Advertising
      • Remarketing
    • Portfolio
    • FAQ’s
    • Blog
    • Contact Us
    MENU CLOSE back  

    How To Use Styled-Components In React

    You are here:
    1. Home
    2. Web Design
    3. How To Use Styled-Components In React
    Thumbnail for 25337
    Smashing Editorial

    How To Use Styled-Components In React

    How To Use Styled-Components In React

    Adebiyi Adedotun

    2020-07-23T10:30:00+00:00
    2020-07-23T12:34:00+00:00

    Styled components are a CSS-in-JS tool that bridges the gap between components and styling, offering numerous features to get you up and running in styling components in a functional and reusable way. In this article, you’ll learn the basics of styled components and how to properly apply them to your React applications. You should have worked on React previously before going through this tutorial. If you’re looking for various options in styling React components, you can check out our previous post on the subject.

    At the core of CSS is the capability to target any HTML element — globally — no matter its position in the DOM tree. This can be a hindrance when used with components, because components demand, to a reasonable extent, colocation (i.e. keeping assets such as states and styling) closer to where they’re used (known as localization).

    In React’s own words, styled components are “visual primitives for components”, and their goal is to give us a flexible way to style components. The result is a tight coupling between components and their styles.

    Note: Styled components are available both for React and React Native, and while you should definitely check out the React Native guide, our focus here will be on styled components for React.

    Why Styled Components?

    Apart from helping you to scope styles, styled components include the following features:

    • Automatic vendor prefixing
      You can use standard CSS properties, and styled components will add vendor prefixes should they be needed.
    • Unique class names
      Styled components are independent of each other, and you do not have to worry about their names because the library handles that for you.
    • Elimination of dead styles
      Styled components remove unused styles, even if they’re declared in your code.
    • and many more.

    Installation

    Installing styled components is easy. You can do it through a CDN or with a package manager such as Yarn…

    yarn add styled-components

    … or npm:

    npm i styled-components

    Our demo uses create-react-app.

    Starting Out

    Perhaps the first thing you’ll notice about styled components is their syntax, which can be daunting if you don’t understand the magic behind styled components. To put it briefly, styled components use JavaScript’s template literals to bridge the gap between components and styles. So, when you create a styled component, what you’re actually creating is a React component with styles. It looks like this:

    import styled from "styled-components";
    
    // Styled component named StyledButton
    const StyledButton = styled.button`
      background-color: black;
      font-size: 32px;
      color: white;
    `;
    
    function Component() {
      // Use it like any other component.
      return <StyledButton> Login </StyledButton>;
    }

    Here, StyledButton is the styled component, and it will be rendered as an HTML button with the contained styles. styled is an internal utility method that transforms the styling from JavaScript into actual CSS.

    In raw HTML and CSS, we would have this:

    button {
      background-color: black;
      font-size: 32px;
      color: white;
    }
    
    <button> Login </button>

    If styled components are React components, can we use props? Yes, we can.

    Adapting Based on Props

    Styled components are functional, so we can easily style elements dynamically. Let’s assume we have two types of buttons on our page, one with a black background, and the other blue. We do not have to create two styled components for them; we can adapt their styling based on their props.

    import styled from "styled-components";
    
    const StyledButton = styled.button`
      min-width: 200px;
      border: none;
      font-size: 18px;
      padding: 7px 10px;
      /* The resulting background color will be based on the bg props. */
      background-color: ${props => props.bg === "black" ? "black" : "blue";
    `;
    
    function Profile() {
      return (
        <div>
          <StyledButton bg="black">Button A</StyledButton>
          <StyledButton bg="blue">Button B</StyledButton>
        </div>
      )
    }

    Because StyledButton is a React component that accepts props, we can assign a different background color based on the existence or value of the bg prop.

    You’ll notice, though, that we haven’t given our button a type. Let’s do that:

    function Profile() {
      return (
        <>
          <StyledButton bg="black" type="button">
            Button A
          </StyledButton>
          <StyledButton bg="blue" type="submit" onClick={() => alert("clicked")}>
            Button B
          </StyledButton>
        </>
      );
    }

    Styled components can differentiate between the types of props they receive. They know that type is an HTML attribute, so they actually render , while using the bg prop in their own processing. Notice how we attached an event handler, too?

    Speaking of attributes, an extended syntax lets us manage props using the attrs constructor. Check this out:

    const StyledContainer = styled.section.attrs((props) => ({
      width: props.width || "100%",
      hasPadding: props.hasPadding || false,
    }))`
      --container-padding: 20px;
      width: ${(props) => props.width}; // Falls back to 100%
      padding: ${(props) =>
        (props.hasPadding && "var(--container-padding)") || "none"};
    `;

    Notice how we don’t need a ternary when setting the width? That’s because we’ve already set a default for it with width: props.width || "100%",. Also, we used CSS custom properties because we can!

    Note: If styled components are React components, and we can pass props, then can we also use states? The library’s GitHub account has an issue addressing this very matter.

    Extending Styles

    Let’s say you’re working on a landing page, and you’ve set your container to a certain max-width to keep things centered. You have a StyledContainer for that:

    const StyledContainer = styled.section`
      max-width: 1024px;
      padding: 0 20px;
      margin: 0 auto;
    `;

    Then, you discover that you need a smaller container, with padding of 10 pixels on both sides, instead of 20 pixels. Your first thought might be to create another styled component, and you’d be right, but it wouldn’t take any time before you realize that you are duplicating styles.

    const StyledContainer = styled.section`
      max-width: 1024px;
      padding: 0 20px;
      margin: 0 auto;
    `;
    
    const StyledSmallContainer = styled.section`
      max-width: 1024px;
      padding: 0 10px;
      margin: 0 auto;
    `;

    Before you go ahead and create StyledSmallContainer, like in the snippet above, let’s learn the way to reuse and inherit styles. It’s more or less like how the spread operator works:

    const StyledContainer = styled.section`
      max-width: 1024px;
      padding: 0 20px;
      margin: 0 auto;
    `;
    
    // Inherit StyledContainer in StyledSmallConatiner
    const StyledSmallContainer = styled(StyledContainer)`
      padding: 0 10px;
    `;
    
    function Home() {
      return (
        <StyledContainer>
          <h1>The secret is to be happy</h1>
        </StyledContainer>
      );
    }
    
    function Contact() {
      return (
        <StyledSmallContainer>
          <h1>The road goes on and on</h1>
        </StyledSmallContainer>
      );
    }

    In your StyledSmallContainer, you’ll get all of the styles from StyledContainer, but the padding will be overridden. Keep in mind that, ordinarily, you’ll get a section element rendered for StyledSmallContainer, because that’s what StyledContainer renders. But that doesn’t mean it’s carved in stone or unchangeable.

    The “as” Polymorphic Prop

    With the as polymorphic prop, you can swap the end element that gets rendered. One use case is when you inherit styles (as in the last example). If, for example, you’d prefer a div to a section for StyledSmallContainer, you can pass the as prop to your styled component with the value of your preferred element, like so:

    function Home() {
      return (
        <StyledContainer>
          <h1>It's business, not personal</h1>
        </StyledContainer>
      );
    }
    
    function Contact() {
      return (
        <StyledSmallContainer as="div">
          <h1>Never dribble when you can pass</h1>
        </StyledSmallContainer>
      );
    }

    Now, StyledSmallContainer will be rendered as a div. You could even have a custom component as your value:

    function Home() {
      return (
        <StyledContainer>
          <h1>It's business, not personal</h1>
        </StyledContainer>
      );
    }
    
    function Contact() {
      return (
        <StyledSmallContainer as={StyledContainer}>
          <h1>Never dribble when you can pass</h1>
        </StyledSmallContainer>
      );
    }

    Don’t take it for granted.

    SCSS-Like Syntax

    The CSS preprocessor Stylis enables styled components to support SCSS-like syntax, such as nesting:

    const StyledProfileCard = styled.div`
      border: 1px solid black;
    
      > .username {
        font-size: 20px;
        color: black;
        transition: 0.2s;
    
        &:hover {
          color: red;
        }
    
        + .dob {
          color: grey;
        }
      }
    `;
    
    function ProfileCard() {
      return (
        <StyledProfileCard>
          <h1 className="username">John Doe</h1>
          <p className="dob">
            Date: <span>12th October, 2013</span>
          </p>
          <p className="gender">Male</p>
        </StyledProfileCard>
      );
    }

    Animation

    Styled components have a keyframes helper that assists with constructing (reusable) animation keyframes. The advantage here is that the keyframes will be detached from the styled components and can be exported and reused wherever needed.

    import styled, {keyframes} from "styled-components";
    
    const slideIn = keyframes`
      from {
        opacity: 0;
      }
    
      to {
        opacity: 1;
      }
    `;
    
    const Toast = styled.div`
      animation: ${slideIn} 0.5s cubic-bezier(0.4, 0, 0.2, 1) both;
      border-radius: 5px;
      padding: 20px;
      position: fixed;
    `;

    Global Styling

    While the original goal of CSS-in-JS and, by extension, styled components is scoping of styles, we can also leverage styled components’ global styling. Because we’re mostly working with scoped styles, you might think that’s an invariable factory setting, but you’d be wrong. Think about it: What really is scoping? It’s technically possible for us — in the name of global styling — to do something similar to this:

    ReactDOM.render(
      <StyledApp>
        <App />
      </StyledApp>,
      document.getElementById("root")
    );

    But we already have a helper function — createGlobalStyle — whose sole reason for existence is global styling. So, why deny it its responsibility?

    One thing we can use createGlobalStyle for is to normalize the CSS:

    import {createGlobalStyle} from "styled-components";
    
    const GlobalStyle = createGlobalStyle`
        /* Your css reset here */
    `;
    
    // Use your GlobalStyle
    function App() {
      return (
        <div>
          <GlobalStyle />
          <Routes />
        </div>
      );
    }

    Note: Styles created with createGlobalStyle do not accept any children. Learn more in the documentation.

    At this point, you might be wondering why we should bother using createGlobalStlye at all. Here are a few reasons:

    • We can’t target anything outside of the root render without it (for example, html, body, etc.).
    • createGlobalStyle injects styles but does not render any actual elements. If you look at the last example closely, you’ll notice we didn’t specify any HTML element to render. This is cool because we might not actually need the element. After all, we’re concerned with global styles. We are targeting selectors at large, not specific elements.
    • createGlobalStyle is not scoped and can be rendered anywhere in our app and will be applicable as long as it’s in the DOM. Think about the concept, not the structure.
    import {createGlobalStyle} from "styled-components";
    
    const GlobalStyle = createGlobalStyle`
      /* Your css reset here */
    
      .app-title {
        font-size: 40px;
      }
    `;
    
    const StyledNav = styled.nav`
        /* Your styles here */
    `;
    
    function Nav({children}) {
      return (
        <StyledNav>
          <GlobalStyle />
          {children}
        </StyledNav>
      );
    }
    
    function App() {
      return (
        <div>
          <Nav>
            <h1 className="app-title">STYLED COMPONENTS</h1>
          </Nav>
          <Main />
          <Footer />
        </div>
      );
    }

    If you think about the structure, then app-title should not be styled as set in GlobalStyle. But it doesn’t work that way. Wherever you choose to render your GlobalStyle, it will be injected when your component is rendered.

    Be careful: createGlobalStyles will only be rendered if and when it’s in the DOM.

    CSS Helper

    Already we’ve seen how to adapt styles based on props. What if we wanted to go a little further? The CSS helper function helps to achieve this. Let’s assume we have two text-input fields with states: empty and active, each with a different color. We can do this:

    const StyledTextField = styled.input`
      color: ${(props) => (props.isEmpty ? "none" : "black")};
    `;

    All’s well. Subsequently, if we need to add another state of filled, we’d have to modify our styles:

    const StyledTextField = styled.input`
      color: ${(props) =>
        props.isEmpty ? "none" : props.active ? "purple" : "blue"};
    `;

    Now the ternary operation is growing in complexity. What if we add another state to our text-input fields later on? Or what if we want to give each state additional styles, other than color? Can you imagine cramping the styles into the ternary operation? The css helper comes in handy.

    const StyledTextField = styled.input`
      width: 100%;
      height: 40px;
    
      ${(props) =>
        (props.empty &&
          css`
            color: none;
            backgroundcolor: white;
          `) ||
        (props.active &&
          css`
            color: black;
            backgroundcolor: whitesmoke;
          `)}
    `;

    What we’ve done is sort of expanded our ternary syntax to accommodate more styles, and with a more understandable and organized syntax. If the previous statement seems wrong, it’s because the code is trying to do too much. So, let’s step back and refine:

    const StyledTextField = styled.input`
    width: 100%;
    height: 40px;
    
    // 1. Empty state
    ${(props) =>
      props.empty &&
      css`
        color: none;
        backgroundcolor: white;
      `}
    
    // 2. Active state
    ${(props) =>
      props.active &&
      css`
        color: black;
        backgroundcolor: whitesmoke;
      `}
    
    // 3. Filled state
    ${(props) =>
      props.filled &&
      css`
        color: black;
        backgroundcolor: white;
        border: 1px solid green;
      `}
    `;

    Our refinement splits the styling into three different manageable and easy-to-understand chunks. It’s a win.

    StyleSheetManager

    Like the CSS helper, StyleSheetManager is a helper method for modifying how styles are processed. It takes certain props — like disableVendorPrefixes (you can check out the full list) — that help you opt out of vendor prefixes from its subtree.

    import styled, {StyleSheetManager} from "styled-components";
    
    const StyledCard = styled.div`
      width: 200px;
      backgroundcolor: white;
    `;
    
    const StyledNav = styled.div`
      width: calc(100% - var(--side-nav-width));
    `;
    
    function Profile() {
      return (
        <div>
          <StyledNav />
          <StyleSheetManager disableVendorPrefixes>
            <StyledCard> This is a card </StyledCard>
          </StyleSheetManager>
        </div>
      );
    }

    disableVendorPrefixes is passed as a prop to . So, the styled components wrapped by would be disabled, but not the ones in .

    Easier Debugging

    When introducing styled components to one of my colleagues, one of their complaints was that it’s hard to locate a rendered element in the DOM — or in React Developer Tools, for that matter. This is one of the drawbacks of styled components: In trying to provide unique class names, it assigns unique hashes to elements, which happen to be cryptic, but it makes the displayName readable for easier debugging.

    import React from "react";
    import styled from "styled-components";
    import "./App.css";
    
    const LoginButton = styled.button`
      background-color: white;
      color: black;
      border: 1px solid red;
    `;
    
    function App() {
      return (
        <div className="App">
          <LoginButton>Login</LoginButton>
        </div>
      );
    }

    By default, styled components render LoginButton as in the DOM, and as LoginButton in React Developer Tools, which makes debugging easier. We can toggle the displayName boolean if we don’t want this behavior. This requires a Babel configuration.

    Note: In the documentation, the package babel-plugin-styled-components is specified, as well as a .babelrc configuration file. The issue with this is that, because we’re using create-react-app, we can’t configure a lot of things unless we eject. This is where Babel macros come in.

    We’ll need to install babel-plugin-macros with npm or Yarn, and then create a babel-plugin-macros.config.js at the root of our application, with the content:

    module.exports = {
      styledComponents: {
        displayName: true,
        fileName: false,
      },
    };

    With the fileName value inverted, the displayName will be prefixed with the file name for even more unique precision.

    We also now need to import from the macro:

    // Before
    import styled from "styled-components";
    
    // After
    import styled from "styled-components/macro";

    Conclusion

    Now that you can programmatically compose your CSS, do not abuse the freedom. For what it’s worth, do your very best to maintain sanity in your styled components. Don’t try to compose heavy conditionals, nor suppose that every thing should be a styled component. Also, do not over-abstract by creating nascent styled components for use cases that you are only guessing are somewhere around the corner.

    Further Resources

    1. Documentation, Styled Components
    2. “Building a Reusable Component System with React.js and styled-components”, Lukas Gisder-Dubé
    3. Usage with Next.js
    4. Usage with Gatsby

    (ks, ra, yk, al, il)

    From our sponsors: How To Use Styled-Components In React

    Posted on 23rd July 2020Web Design
    FacebookshareTwittertweetGoogle+share

    Related posts

    Archived
    22nd March 2023
    Archived
    18th March 2023
    Archived
    20th January 2023
    Thumbnail for 25788
    Handling Continuous Integration And Delivery With GitHub Actions
    19th October 2020
    Thumbnail for 25781
    Supercharge Testing React Applications With Wallaby.js
    19th October 2020
    Thumbnail for 25778
    A Monthly Update With New Guides And Community Resources
    19th October 2020
    Latest News
    • Archived
      22nd March 2023
    • Archived
      18th March 2023
    • Archived
      20th January 2023
    • 20201019 ML Brief
      19th October 2020
    • Thumbnail for 25788
      Handling Continuous Integration And Delivery With GitHub Actions
      19th October 2020
    • Thumbnail for 25786
      The Future of CX with Larry Ellison
      19th October 2020
    News Categories
    • Digital Marketing
    • Web Design

    Our services

    Website Design
    Website Design

    A website is an important part of any business. Professional website development is an essential element of a successful online business.

    We provide website design services for every type of website imaginable. We supply brochure websites, E-commerce websites, bespoke website design, custom website development and a range of website applications. We love developing websites, come and talk to us about your project and we will tailor make a solution to match your requirements.

    You can contact us by phone, email or send us a request through our online form and we can give you a call back.

    More Information

    Digital Marketing
    Digital Marketing

    Our digital marketeers have years of experience in developing and excuting digital marketing strategies. We can help you promote your business online with the most effective methods to achieve the greatest return for your marketing budget. We offer a full service with includes the following:

    1. Social Media Marketing

    2. Email & Newsletter Advertising

    3. PPC - Pay Per Click

    4. A range of other methods are available

    More Information

    SEO
    SEO Services

    SEO is an essential part of owning an online property. The higher up the search engines that your website appears, the more visitors you will have and therefore the greater the potential for more business and increased profits.

    We offer a range of SEO services and packages. Our packages are very popular due to the expanse of on-page and off-page SEO services that they cover. Contact us to discuss your website and the SEO services that would best suit to increase your websites ranking.

    More Information

    E-commerce
    E-commerce Websites

    E-commerce is a rapidly growing area with sales online increasing year on year. A professional E-commerce store online is essential to increase sales and is a reflection of your business to potential customers. We provide professional E-commerce websites custom built to meet our clients requirements.

    Starting to sell online can be a daunting task and we are here to make that journey as smooth as possible. When you work with Cunningham Web Solutions on your E-commerce website, you will benefit from the experience of our team and every detail from the website design to stock management is carefully planned and designed with you in mind.

    More Information

    Social Media Services
    Social Media Services

    Social Media is becoming an increasingly effective method of marketing online. The opportunities that social media marketing can offer are endless and when managed correctly can bring great benefits to every business.

    Social Media Marketing is a low cost form of advertising that continues to bring a very good ROI for our clients. In conjuction with excellent website development and SEO, social media marketing should be an essential part of every digital marketing strategy.

    We offer Social Media Management packages and we also offer Social Media Training to individuals and to companies. Contact us to find out more.

    More Information

    Cunningham Web Solutions
    © Copyright 2025 | Cunningham Web Solutions
    • Home
    • Our Services
    • FAQ's
    • Account Services
    • Privacy Policy
    • Contact Us