FAQs

What do I need to do to migrate to v4?

This is a pretty big release with lots of changes both under the hood and at the API level. As the beta progresses, we will try to release codemods to make the items below simpler. Also, if you find any issues with the steps below, please leave constructive feedback!

  1. Upgrade to the latest styled-components:
npm install styled-components
  1. Make sure your application is using react >= 16.3; internally we are using the new React.forwardRef API and new context APIs if you wish to try and polyfill for older React version support
npm install [email protected]^16.3 react-[email protected]^16.3
Note

If you are using enzyme or other dependencies like react-test-renderer, there may be more related upgrades to complete if you are coming from an old version of react.

  1. If you are using the .extend API, switch your components to use styled(StyledComponent) instead.

A codemod is available to expedite this.

🚫

import styled from 'styled-components'

const Component = styled.div`
  background: blue;
  color: red;
`

const ExtendedComponent = Component.extend`
  color: green;
`

import styled from 'styled-components'

const Component = styled.div`
  background: blue;
  color: red;
`

const ExtendedComponent = styled(Component)`
  color: green;
`

See the "extending styles" documentation for more examples.

  1. If you were using the injectGlobal API to add global styles to your page, use the new createGlobalStyle helper component instead.

A codemod is available to expedite this.

🚫

import { injectGlobal } from 'styled-components'

injectGlobal`
  body {
    color: red;
  }
`

import { createGlobalStyle } from "styled-components"

const GlobalStyle = createGlobalStyle`
  body {
    color: red;
  }
`

// later in your app's render method
<React.Fragment>
  <Navigation />
  <OtherImportantTopLevelComponentStuff />
  <GlobalStyle />
</React.Fragment>

See the documentation for createGlobalStyle to see all the cool stuff you can do with it that wasn't possible before with injectGlobal!

  1. If you were using the innerRef prop, change it to a normal ref.

🚫

const Component = styled.div`
  background: blue;
  color: red;
`

// later in your render method
<Component innerRef={element => { this.myElement = element }}>Something something</Component>

const Component = styled.div`
  background: blue;
  color: red;
`

// later in your render method
<Component ref={element => { this.myElement = element }}>Something something</Component>
  1. If you're using the keyframes component in a partial without the css helper, you'll need to use the helper now. In general, always use the css helper when composing styling partials to be interpolated into a styled component.

🚫

import styled, { keyframes } from 'styled-components'

const animation = keyframes`
  0% {
    opacity: 0;
  }

  100 {
    opacity: 1;
  }
`

const animationRule = `
  ${animation} 1s infinite alternate
`

const Component = styled.div`
  animation: ${animationRule};
`

import styled, { css, keyframes } from 'styled-components'

const animation = keyframes`
  0% {
    opacity: 0;
  }

  100 {
    opacity: 1;
  }
`

const animationRule = css`
  ${animation} 1s infinite alternate;
`

const Component = styled.div`
  animation: ${animationRule};
`
  1. If you're using TypeScript, the typings are now located in DefinitelyTyped:
npm install @types/styled-components

That's it! Aside from migrating, we also highly recommend reading up on the new "as" prop which is intended to replace the withComponent API in the future.

Can I nest rules?

Yes: nesting is a feature intentionally ported from Sass. Used sparingly it's a great way to lighten your code by reducing the need to create explicit classes for every element.

It can also be used by parent components to define contextual constraints that aren't properly a concern of the affected children:

const EqualDivider = styled.div`
  display: flex;
  margin: 0.5rem;
  padding: 1rem;
  background: papayawhip;
  ${props => props.vertical && "flex-direction: column;"}

  > * {
    flex: 1;

    &:not(:first-child) {
      ${props => props.vertical ? "margin-top" : "margin-left"}: 1rem;
    }
  }
`;

const Child = styled.div`
  padding: 0.25rem 0.5rem;
  background: palevioletred;
`;

render(
  <div>
  <EqualDivider>
    <Child>First</Child>
    <Child>Second</Child>
    <Child>Third</Child>
  </EqualDivider>
  <EqualDivider vertical>
    <Child>First</Child>
    <Child>Second</Child>
    <Child>Third</Child>
  </EqualDivider>
  </div>
);
First
Second
Third
First
Second
Third

It's also incredibly convenient to co-locate media queries, since we can see at a glance exactly how the component will respond at any resolution.

const ColorChanger = styled.section`
  background: papayawhip;
  color: palevioletred;

  @media(min-width: 768px) {
    background: mediumseagreen;
    color: papayawhip;
  }
`;

render(
  <ColorChanger href="#">
    <h2>Hello world!</h2>
  </ColorChanger>
);

Hello world!

Can I use CSS frameworks?

Integrating an existing CSS framework with styled-components is really easy! You can use its existing class names alongside your components.

For example, imagine you have an existing app with two classes you want to use again: .small and .big. If you want the class to always be attached to the component, you should use the attrs method to attach it. If you want to attach it only in some cases you can use the className props like you always have!

// Using .attrs, we attach the .small class to every <Button />
const Button = styled.button.attrs({
  className: "small",
})`
  background: black;
  color: white;
  cursor: pointer;
  margin: 1em;
  padding: 0.25em 1em;
  border: 2px solid black;
  border-radius: 3px;
`;

render(
  <div>
    <Button>Styled Components</Button>
    {/* Here we attach the class .big to this specific instance of the Button */}
    <Button className="big">The new way to style components!</Button>
  </div>
);

If the framework has a bunch of raw global CSS that needs to be included on the page, you can add it using the createGlobalStyle API. This is also useful for things like CSS resets.

Note

Note that for styled-components v3 and below, the previous API for global styles was injectGlobal.

How can I override styles with higher specificity?

The way to override styles with a high specificity is to simply increase the specificity of your own styles. This could be done using !important, but that's error prone and generally not a good idea.

We recommend the following technique:

const MyStyledComponent = styled(AlreadyStyledComponent)`
  &&& {
    color: palevioletred;
    font-weight: bold;
  }
`

Each & gets replaced with the generated class, so the injected CSS then looks like this:

.MyStyledComponent-asdf123.MyStyledComponent-asdf123.MyStyledComponent-asdf123 {
  color: palevioletred;
  font-weight: bold;
}

The repeated class bumps the specificity high enough to override the source order without being very tedious to write!

How can I override inline styles?

Inline styles will always take precedence over external CSS, so you cannot override it by simply increasing specificity.

There is a neat trick however, which is to use the style element-attr CSS Selector in conjunction with !important:

const MyStyledComponent = styled(InlineStyledComponent)`
  &[style] {
    font-size: 12px !important;
    color: blue !important;
  }
`

Why do my DOM nodes have two classes?

Each node actually has two classes connected to it: one is static per component, meaning each element of a styled component has this class. It hasn't any style attached to it. Instead, it's used to quickly identify which styled component a DOM objects belongs to or to make minor changes in the DevTools. It's also used for component selectors. The static class probably will look something like: .sc-fVOeaW.

The other is dynamic, meaning it will be different for every element of your styled component with different props, based on what the interpolations result in. It will probably look like .fVOeaW (note the lack of "sc" prefix.)

For example, the styled component <Button /> would render with the same static class every time. If the styles are changed using interpolations, like <Button secondary />, then the dynamic class will be a different one, while the static class would remain the same.

When to use attrs?

You can pass in attributes to styled components using attrs, but it is not always sensible to do so.

The rule of thumb is to use attrs when you want every instance of a styled component to have that prop, and pass props directly when every instance needs a different one:

const PasswordInput = styled.input.attrs({
  // Every <PasswordInput /> should be type="password"
  type: "password"
})``

// This specific one is hidden, so let's set aria-hidden
<PasswordInput aria-hidden="true" />

The same goes for props that can be inferred based on the "mode" of another prop. In this case you can set a property on attrs to a function that computes that prop based on other props.

I am a library author. Should I bundle styled-components with my library?

If you are a library author, we recommend that you should not bundle and ship styled-components module with your library. There are two steps that you need to do to achieve this:

  • Marking styled-components as external in your package dependencies
  • Removing styled-components from your library bundle

Marking styled-components as external in your package dependencies

To do this, you will need to move it from dependencies to devDependencies and include it in the peerDependencies list in your package.json file:

  {
-   "dependencies" : {
+   "devDependencies" : {
      "styled-components": "^3.4.9"
    },
+   "peerDependencies" : {
+     "styled-components": ">= 3"
+   }
  }

Moving styled-components to devDependencies will guarantee that it wouldn't be installed along with your library (npm install or yarn add will ignore devDependencies when a library is installed).

Adding styled-components to peerDependencies will signal your library consumers that styled-components is not included with the library and they need to install it themselves.

Also, note that in the peerDependencies section the version string has been made a more permissive >= 3. This allows future versions of styled-components to work automatically and you can simply narrow the range with a patch update to your library if a breaking change is eventually added.

Removing styled-components from your library bundle

If you are bundling your library before shipping it, make sure that you are not bundling styled-components along with it. Here are some examples of how to do this with some popular module bundling tools:

With Microbundle

If you are using Microbundle, it will handle this step automatically. Microbundle treats every dependency in the peerDependencies list as external and excludes it from the build for you.

With Rollup.js

If you are using Rollup.js, you should provide an external option in your config:

  export default {
    entry: "my-awesome-library.js",
+   external: [
+     "styled-components"
+   ]
  }

Another approach is to use the rollup-plugin-peer-deps-external plugin which will automatically add the peerDependencies in the external option array for you.

+ import peerDepsExternal from 'rollup-plugin-peer-deps-external';

  export default {
    entry: "my-awesome-library.js",
+   plugins: [
+    // Preferably set as first plugin.
+    peerDepsExternal(),
+   ]
  }

With Webpack

If you are using Webpack, you should provide an externals option in your config:

  modules.export = {
    entry: "my-awesome-library.js",
+   externals: {
+     "styled-components": {
+       commonjs: "styled-components",
+       commonjs2: "styled-components",
+       amd: "styled-components",
+     },
+   },
  }
Note

You can find more useful information on how to bundle a library with Webpack at "Authoring Libraries" section of Webpack documentation.

Why am I getting a warning about several instances of module on the page?

If you are seeing a warning message in the console like the one below, you probably have several instances of styled-components initialized on the page.

It looks like there are several instances of "styled-components" initialized in this application. This may cause dynamic styles not rendering properly, errors happening during rehydration process and makes you application bigger without a good reason.

If you are using a building tool like webpack, consider checking your bundle for duplication of the "styled-components" module.

This may cause dynamic styles not working properly or even errors during rehydration if you are using server-side rendering.

Possible reasons

There are several common reasons for this to happen:

  • You have several applications that are using styled-components running on the same page (e.g., several entry points in webpack are loaded on the same page)
  • You have another styled-components library somewhere in your dependencies
  • You have a monorepo structure for your project (e.g, lerna, yarn workspaces) and styled-components module is a dependency in more than one package (this one is more or less the same as the previous one)

Running multiple applications on one page

If you have several applications running on one page, consider using one styled-components module for all of them. If you are using webpack, you can use CommonsChunkPlugin to create an explicit vendor chunk, that will contain the styled-components module:

  module.exports = {
    entry: {
+     vendor: ["styled-components"],
      app1: "./src/app.1.js",
      app2: "./src/app.2.js",
    },
    plugins: [
+     new webpack.optimize.CommonsChunkPlugin({
+       name: "vendor",
+       minChunks: Infinity,
+     }),
    ]
  }

Duplicated module in node_modules

If you think that the issue is in duplicated styled-components module somewhere in your dependencies, there are several ways to check this. You can use npm ls styled-components, yarn list styled-components or find -L ./node_modules | grep /styled-components/package.json commands in your application folder.

If none of these commands identified the duplication, try analyzing your bundle for multiple instances of styled-components. You can just check your bundle source, or use a tool like source-map-explorer or webpack-bundle-analyzer.

If you identified that duplication is the issue that you are encountering there are several things you can try to solve it:

If you are using npm you can try running npm dedupe. This command searches the local dependencies and tries to simplify the structure by moving common dependencies further up the tree.

Note

Be aware that npm dedupe doesn't work well with symlinked folders (i.e., when you use npm link)

If you are using webpack, you can change the way it will resolve the styled-components module. You can overwrite the default order in which webpack will look for your dependencies and make your application node_modules more prioritized than default node module resolution order:

  resolve: {
+   alias: {
+     "styled-components": path.resolve(appFolder, "node_modules", "styled-components"),
+   }
  }

Why am I getting HTML attribute warnings?

The warning message below indicates that non-standard attributes are being attached to HTML DOM elements such as <div> or <a>. If you are seeing this warning message, it is likely that you or a library you are using is attaching props as attributes to HTML DOM elements.

Warning: Received "true" for a non-boolean attribute

If you're seeing this warning you are probably passing true where "true" would be appropriate. It's likely that this comes from a .attrs({}) property, or from a completely unrelated prop that you're passing to a styled(Component) component.

To learn more about how props are passed, see this section.

For example:

const Link = props => (
  <a {...props} className={props.className}>
    {props.text}
  </a>
)

const StyledComp = styled(Link)`
  color: ${props => (props.red ? 'red' : 'blue')};
`

<StyledComp text="Click" href="https://www.styled-components.com/" red />

This will render:

<a text="Click" href="https://www.styled-components.com/" red=true class="[generated class]">Click</a>

React will warn on non-standard attributes being attached such as "red" and "text", which are not valid HTML attributes for the <a> element. To fix this, you can use argument destructuring to pull out those known styling props:

const Link = ({ className, red, text, ...props }) => (
  <a {...props} className={className}>
    {text}
  </a>
)

const StyledComp = styled(Link)`
  color: ${props => (props.red ? 'red' : 'blue')};
`

<StyledComp text="Click" href="https://www.styled-components.com/" red />

This will render:

<a href="https://www.styled-components.com/" class="[generated class]">
  Click
</a>

When you use argument destructuring, any variables pulled out of the props object will not be included when spread-applying the remaining props (...props);

Which browsers are supported?

styled-components supports the same set of browsers as the current React version.

  • v2.x (React v0.14+): IE9+, all evergreen browsers
  • v3.x (React v0.14+): IE9+, all evergreen browsers
  • v4.x (React v16.3+): IE11, IE 9+ (with Map + Set polyfills), all evergreen browsers

Evergreen browsers include Chrome and Firefox (and derviatives) as they can be updated regardless of operating system version. Edge and Safari should both also work fine since all versions for the last several years support the relevant APIs.

How do I use styled-components with create-react-app?

The basic functionality of the library should work out of the box like any other library.

However, if you want to do server-side rendering or take advantage of some of the advanced capabilities of the styled-components babel plugin without ejecting you'll need to set up react-app-rewired and react-app-rewire-styled-components.

Babel Macro

As of create-react-app v2, there is now an alternative to setting up react-app-rewired through use of "babel macros". See the documentation for the styled-components babel macro for setup and usage.

How can I fix issues when using npm link or yarn link?

Local linking can be a useful tool to co-develop projects simultaneously. However, it creates chaotic situations with libraries that are meant to be used as singletons like react and styled-components since each of your local projects likely has a full set of development dependencies downloaded (and bundlers prefer local versions of dependencies by default.)

The solution is to add aliasing. Here's an example config for webpack:

// const path = require('path');

{
  resolve: {
    alias: {
      // adjust this path as needed depending on where your webpack config is
      'styled-components': path.resolve('../node_modules/styled-components')
    }
  }
}

This ensures that for your build the same copy of the library will always be used, even across symlinked projects.

How do I fix flickering text after server side rendering?

When using global styling APIs like createGlobalStyle or the former injectGlobal, adding and removing certain styles from the DOM like @font-face definitions can cause momentary flickering of text on the page. This typically happens during the rehydration phase of server-side rendering. We're still tweaking how these behaviors work to avoid the issue long-term.

However, there is a CSS solution to the problem in the font-display CSS rule. By setting the rule to "fallback" mode, once a font has been loaded it will not be reloaded. This eliminates the flicker.

@font-face {
  font-family: 'Foo';
  src: url('/path/to/foo.woff') format('woff');
  font-style: normal;
  font-weight: 400;
  font-display: fallback; /* <- this can be added to each @font-face definition */
}