Archived course lesson

Add Styled Components

Part of Frontend Serverless with React and GraphQL

Objective: We will set up Styled Components into the base of our project so that we can utilize it across the app.

Our first stop now that we have a base Next.js instance running is to add styled components. This will allow us to write css in a more modular fashion where the styles will be scoped to a particular component. This works well with React’s modular style. We need to first add the styled-components package as well as a babel plugin for the package.

npm install --save styled-components
npm install --save-dev babel-plugin-styled-components

We need to now configure babel to use the styled-components plugin.

{
  "presets": ["next/babel"],
  "plugins": [["styled-components", { "ssr": true }]]
}

Now we can add our first style- in our case we will be creating a styled header. We can import styled components at the top of our file and then create a styled h1 component by simply using styled.h1 followed by a string with all of our styles. Then, instead of using the <h1> tag in our React component, we can use the <StyledHeader> component in the same way and it will create a h1 tag with the styles applied to that component.

import styled from 'styled-components';

const StyledHeader = styled.h1`
  font-size: 2em;
  text-align: left;
  padding: 16px 16px;
`;

const Index = () => {
  return (
    <div>
      <StyledHeader>Index Page</StyledHeader>
    </div>
  );
};

export default Index;

What we should see is that the component does indeed get styled, but there is flash of a second where it will show the unstyled text. We can fix this by extending our <Document /> component by injecting our styles into the head of or page. We do this by creating a _document.tsx in our pages folder which allows us to overwrite the base document component which is there by default.

import Document from 'next/document';
import { ServerStyleSheet } from 'styled-components';

export default class MyDocument extends Document {
  static async getInitialProps(ctx) {
    const sheet = new ServerStyleSheet();
    const originalRenderPage = ctx.renderPage;

    try {
      ctx.renderPage = () =>
        originalRenderPage({
          enhanceApp: App => props => sheet.collectStyles(<App {...props} />),
        });

      const initialProps = await Document.getInitialProps(ctx);
      return {
        ...initialProps,
        styles: (
          <>
            {initialProps.styles}
            {sheet.getStyleElement()}
          </>
        ),
      };
    } finally {
      sheet.seal();
    }
  }
}

Once we finish, we should see that after we reload our page, the styled <h1> shows up immediately without a flash of bad styles and we should also see a favicon and title appear in our brower’s tab. If you don’t see this immediately, restart your web server by pressing ctrl+c and start it up again to make sure the changes load.