This plugin adds support for server-side rendering, minification of styles, and a nicer debugging experience.
Install the babel-plugin first:
npm install --save-dev babel-plugin-styled-components
Then add it to your babel configuration like so:
⚠️ The plugin call order in your .babelrc file matters. If you're using the env property in your babel configuration, then putting this plugin into the plugins array won't suffice. Instead it needs to be put into each env's plugins array to maintain it being executed first. See this for more information.
{ "plugins": ["babel-plugin-styled-components"] }
By adding a unique identifier to every styled component, this plugin avoids checksum mismatches due to different class generation on the client and on the server. If you do not use this plugin and try to server-side render styled-components React will complain with an HTML attribute mismatch warning during rehydration.
You can disable it if necessary with the ssr option:
{ "plugins": [ [ "babel-plugin-styled-components", { "ssr": false } ] ] }
This option enhances the attached CSS class name on each component with richer output to help identify your components in the DOM without React DevTools. In your page source you'll see: <button class="Button-asdf123 asdf123" /> instead of just <button class="asdf123" />.
It also allows you to see the component's displayName in React DevTools. For example, consider writing a styled component that renders a button element, called MyButton. It will normally show up in DevTools as styled.button, but with the displayName option enabled, it has the name you gave it: MyButton.
This makes it easier to find your components and to figure out where they live in your app.
If you don't need this feature, you can disable it with the displayName option:
{ "plugins": [ [ "babel-plugin-styled-components", { "displayName": false } ] ] }
By default, the displayName of a component will be prefixed with the filename in order to make the component name as unique as possible.
You can force the component displayName to be solely the component name by disabling the fileName option:
{ "plugins": [ [ "babel-plugin-styled-components", { "fileName": false } ] ] }
One example you might want to do this, is testing components with enzyme. While you can always use .find(ComponentName) it's definitely possible to search component by its displayName with .find("ComponentName"). In the latter case you will need to disable the fileName option. If you do want this for testing only, make sure to add this only under your test environment.
A common pattern is to put components in Button/index.jsx instead of Button.jsx. By default, if the fileName option is set to true, the plugin will generate the display name using the directory name (<button class="Button-asdf123 asdf123" />) instead of the file name (<button class="index-asdf123 asdf123" />), because the former provides more information.
The meaninglessFileNames option allows to customize the list of file names that are not relevant to the description of a styled component's functionality, and hence the directory name should be used instead:
{ "plugins": [ [ "babel-plugin-styled-components", { "meaninglessFileNames": ["index", "styles"] } ] ] }
For example, adding styles to the list would enable you to store your styled components in a Button/styles.js file.
This option defaults to ["index"].
If either fileName or displayName are set to false, this option has no effect.
Two types of minifications are performed by this plugin: one removes all whitespace & comments from your CSS and the other transpiles tagged template literals, keeping valuable bytes out of your bundles.
If desired, you can disable this behavior via babel configuration:
{ "plugins": [ ["babel-plugin-styled-components", { "minify": false, "transpileTemplateLiterals": false }] ] }
Due to how styled components are transpiled and constructed, by default minifiers cannot properly perform dead code elimination on them because they are assumed to have side effects. However, there is a feature that can be enabled to aid this process called "pure annotation".
{ "plugins": [ ["babel-plugin-styled-components", { "pure": true }] ] }
It utilizes a babel helper to tag each styled component and library helper with the #__PURE__ JS comment that some minifiers use to overcome the aforementioned issue.
This plugin transpiles styled-components tagged template literals down to a smaller representation than what Babel normally creates.
Wait, transpiling tagged template literals? Doesn't Babel do this natively? 🤔 With Babel, you're likely transpiling ES2015+ JavaScript to ES5-compliant code for older browser support. The most popularly recommended base Babel presets (es2015 / env / latest) include the babel-plugin-transform-es2015-template-literals transform to make tagged template literals work in older browsers, but there is a caveat: output of that transform is quite verbose. It's done this way to meet specification requirements.
Here's an example of the transpiled code processed with babel-preset-latest:
var _templateObject = _taggedTemplateLiteral(['width: 100%;'], ['width: 100%;']) function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })) } var Simple = _styledComponents2.default.div(_templateObject)
styled-components does not require full spec compatibility. Our Babel plugin will transpile template literals attached to styled components to a slightly different, smaller form which still works in older browsers but has a much smaller footprint.
Here's the previous example with the styled-components babel plugin on and the { transpileTemplateLiterals: true } option:
var Simple = _styledComponents2.default.div(['width: 100%;'])
The plugin is also smart enough to not modify tagged template literals belonging to other libraries and use cases:
// Following will be converted: styled.div`` keyframe`` css```some text` // But this will not be converted: // Here the outer template literal will be converted // because it's attached to the component factory, // but the inner template literals will not be touched: styled.div` color: ${light ? `white` : `black`}; `
You can disable this feature with the transpileTemplateLiterals option:
{ "plugins": [ [ "babel-plugin-styled-components", { "transpileTemplateLiterals": false } ] ] }
Read more about Tagged Template Literals in our dedicated section explaining them.
The namespace will ensure that your class names will be unique; this setting is handy when you are working with micro frontends where class name collision can occur.
If desired, you can enable this behavior via babel configuration:
{ "plugins": [ ["babel-plugin-styled-components", { "namespace": "my-app" }] ] }
Here's an example of the transpiled code processed with namespace enabled:
_styledComponents2.default.div.withConfig({ displayName: 'code__before', componentId: 'my-app__sc-3rfj0a-1', })(['color:blue;'])
⚠️ This feature is available from version 1.11.
Babel macros are quickly gaining steam as a full-featured option to allow advanced code transpilation for zero-config projects like create-react-app.
If your scaffold is set up with babel-plugin-macros, then simply use the new styled-components/macro import instead of styled-components:
import styled, { createGlobalStyle } from 'styled-components/macro' const Thing = styled.div` color: red; ` const GlobalStyle = createGlobalStyle` body { color: 'white'; } `
The macro incorporates all the functionality of our babel plugin while allowing the unejected tooling to handle the Babel part of the build process. Special thanks to Luc Leray (@lucleray) for making this happen!
babel-plugin-macros uses cosmiconfig to read a babel-plugin-macros configuration which can be located in any of the following files up the directories from the importing file:
You can then specify the same options as our babel plugin in styledComponents entry:
// babel-plugin-macros.config.js module.exports = { // ... // Other macros config styledComponents: { pure: true, }, }
For more information, see EXPERIMENTAL config for babel-plugin-macros .
You may want to ensure that objects are consistently imported from the macro across your project. This can be achieved by using a no-restricted-imports rule from ESLint:
"no-restricted-imports": [ "error", { "paths": [{ "name": "styled-components", "message": "Please import from styled-components/macro." }], "patterns": [ "!styled-components/macro" ] } ]
typescript-plugin-styled-components is a plugin for TypeScript that gives you a nicer debugging experience.
⚠️ TypeScript does not allow to use any plugin or transformer directly from the command line compiler tsc. So the plugin only works with build toolchains such as webpack with one of TypeScript loaders. There's an open issue to bring plugins to tsc though if you want to upvote it!
Please refer to the project's GitHub repo for documentation.
Jest Styled Components is a set of utilities for testing Styled Components with Jest. This package improves the snapshot testing experience and provides a brand new matcher to make expectations on the style rules.
npm install --save-dev jest-styled-components
When we are building a UI with Styled Components, we want to make sure the output doesn't change unexpectedly. Snapshot testing is an excellent way to test React components, and this package makes the experience even more delightful by adding the style to the snapshots.
Here's an example of a test:
import React from 'react' import styled from 'styled-components' import renderer from 'react-test-renderer' import 'jest-styled-components' const Button = styled.button` color: red; ` test('it works', () => { const tree = renderer.create(<Button />).toJSON() expect(tree).toMatchSnapshot() })
And here's an example of the resulting snapshot:
exports[`it works 1`] = ` .c0 { color: red; } <button className="c0" /> `
For a real world demo, check out this website's repository.
If we only want to check whether a particular style has been applied to an element, we can use the toHaveStyleRule matcher. This function takes two required parameters, a property (string) and a value (string or RegExp), and an optional object to search for rules nested within an at-rule or to add modifiers to the class selector.
import React from 'react' import styled from 'styled-components' import renderer from 'react-test-renderer' import 'jest-styled-components' const Button = styled.button` color: red; @media (max-width: 640px) { &:hover { color: green; } } ` test('it works', () => { const tree = renderer.create(<Button />).toJSON() expect(tree).toHaveStyleRule('color', 'red') expect(tree).toHaveStyleRule('color', 'green', { media: '(max-width: 640px)', modifier: ':hover', }) })
Lint your styled components with stylelint!
Configuring stylelint (v15+) for the first time? Follow these steps:
You need:
npm install --save-dev \ stylelint \ stylelint-config-standard \ postcss-styled-syntax
Add a .stylelintrc file to the root of your project:
{ "extends": [ "stylelint-config-standard" ], "customSyntax": "postcss-styled-syntax" }
You need:
We recommend using Stylelint v9+ as this has added features that allow us to report correct line numbers on CSS syntax errors
npm install --save-dev \ stylelint \ stylelint-processor-styled-components \ stylelint-config-styled-components \ stylelint-config-recommended
Add a .stylelintrc file to the root of your project:
{ "processors": [ "stylelint-processor-styled-components" ], "extends": [ "stylelint-config-recommended", "stylelint-config-styled-components" ] }
You need to run stylelint. Add a lint:css script to your package.json which runs stylelint with a glob to all of your styled components:
{ "scripts": { "lint:css":"stylelint './src/**/*.js'" } }
The processor ignores javascript files that don't contain any styled-components, so don't worry about being too broad as long as you restrict it to javascript (or TypeScript).
Now you can lint your CSS by running the script! 🎉
npm run lint:css
Stylelint --fix option works with same rules on version 15+.
If you want to lint on build, rather than as a separate command, you can use the stylelint-custom-processor-loader for webpack.
When using this processor a couple of stylelint rules throw errors that cannot be prevented, like no-empty-source or no-missing-end-of-source-newline. There's also a couple rules which we need to enforce, like no-vendor-prefix rules. (styled-components automatically vendor prefixes your code, so you don't need to do it manually)
The stylelint-config-styled-components will automatically disable rules that cause conflicts.
You can override rules defined in shared configs in your custom .stylelintrc.
Some other libraries also implement the styled.x pattern with tagged template literals. This processor will lint the CSS in those tagged template literals too, as long as they use the styled keyword.
If you want to use the processor with another library but you also want to change the keyword (e.g. to write cool.div instead of styled.div) use the moduleName option:
import cool from 'other-library'; const Button = cool.button` color: blue; `;
{ "processors": [ [ "stylelint-processor-styled-components", { "moduleName": "other-library" } ] ] }
That double array is on purpose but only necessary if you set options, see the processors configuration docs.
We only officially support styled-components, but the hope is that other libraries can also benefit from the processor.
Sometimes stylelint can throw an error (e.g. CssSyntaxError) even though nothing is wrong with your CSS. This is often due to an interpolation, more specifically the fact that the processor doesn't know what you're interpolating.
A simplified example:
const something = 'background'; const Button = styled.div` ${something}: papayawhip; `;
When you have interpolations in your styles the processor can't know what they are, so it makes a good guess and replaces them with a syntactically equivalent placeholder value. Since stylelint is not a code flow analysis tool this doesn't cover all edge cases and the processor will get it wrong every now and then.
Interpolation tagging allows you to tell the processor what an interpolation is in case it guesses wrong; it can then replace the interpolation with a syntactically correct value based on your tag.
For example:
const something = 'background'; const Button = styled.div` // Tell the processor that "something" is a property ${/* sc-prop */ something}: papayawhip; `;
Now the processor knows that the something interpolation is a property, and it can replace the interpolation with a property for linting.
To tag an interpolation add a comment at either the start or the end of the interpolation. (${/* sc-tag */ foo} or ${bar /* sc-tag */}) Tags start with sc- and, if specified, a tag overrides the processors guess about what the interpolation is.
The full list of supported tags:
If you are in doubt of the vocabulary you can refer to this CSS vocabulary list with examples.
For example, when you interpolate another styled component, what you really interpolate is its unique selector. Since the processor doesn't know that, you can tell it to replace it with a selector when linting:
const Wrapper = styled.div` ${/* sc-selector */ Button} { color: red; } `;
You can also use shorthand tags to avoid cluttering the code. For example:
const Wrapper = styled.div` ${/* sc-sel */ Button} { color: red; } `;
sc-custom is meant to be used as a last resort escape hatch. Prefer to use the standard tags if possible!
On top of the above standard tags the processor also has the sc-custom tag to allow you to cover more unique and uncommon edge cases. With the sc-custom tag you can decide yourself what the placeholder value will be.
For example:
// Switch between left and right based on language settings passed through via the theme const rtlSwitch = (props) => (props.theme.dir === 'rtl' ? 'left' : 'right'); const Button = styled.button` background: green; // Tell the processor to replace the interpolation with "left" // when linting margin-${/* sc-custom "left" */ rtlSwitch}: 12.5px; `;
Turn off rules with stylelint-disable comments (see the stylelint documentation for all allowed syntax) both inside and outside of the tagged template literals.
import React from 'react'; import styled from 'styled-components'; // Disable stylelint from within the tagged template literal const Wrapper = styled.div` /* stylelint-disable */ background-color: 123; `; // Or from the JavaScript around the tagged template literal /* stylelint-disable */ const Wrapper = styled.div` background-color: 123; `;
In order to have stylelint correctly apply indentation rules the processor needs to do a bit of opinionated preprocessing on the styles, which results in us only officially supporting one indentation style. (the supported style is the "default" one as shown in all the documentation)
The important thing is that you put the closing backtick on the base level of indentation as follows:
Right
if (condition) { const Button = styled.button` color: red; `; }
Wrong
if (condition) { const Button = styled.button` color: red; ` }
if (condition) { const Button = styled.button` color: red;` }
It may be that other tagged template literal styles are coincidentally supported, but no issues will be handled regarding indentation unless the above style was used.
Create themes for your styled components using styled-theming
Read the introductory blog post
Install the babel-plugin first:
npm install --save styled-theming
import React from 'react' import styled, { ThemeProvider } from 'styled-components' import theme from 'styled-theming' const boxBackgroundColor = theme('mode', { light: '#fff', dark: '#000', }) const Box = styled.div` background-color: ${boxBackgroundColor}; ` export default function App() { return ( <ThemeProvider theme={{ mode: 'light' }}> <Box>Hello World</Box> </ThemeProvider> ) }
<ThemeProvider> is part of styled-components, but is required for styled-theming.
import { ThemeProvider } from 'styled-components'
<ThemeProvider> accepts a single prop theme which you should pass an object with either strings or getter functions. For example:
<ThemeProvider theme={{ mode: "dark", size: "large" }}> <ThemeProvider theme={{ mode: modes => modes.dark, size: sizes => sizes.large }}>
You should generally set up a <ThemeProvider> at the root of your app:
function App() { return ( <ThemeProvider theme={...}> {/* rest of your app */} </ThemeProvider> ); }
Most of your theming will be done with this function.
name should match one of the keys in your <ThemeProvider> theme.
;<ThemeProvider theme={{ whatever: '...' }} />
theme("whatever", {...});
values should be an object where one of the keys will be selected by the value provided to <ThemeProvider> theme.
<ThemeProvider theme={{ mode: "light" }} /> <ThemeProvider theme={{ mode: "dark" }} /> theme("mode", { light: "...", dark: "...", });
The values of this object can be any CSS value.
theme("mode", { light: "#fff", dark: "#000", }); theme("font", { sansSerif: '"Helvetica Neue", Helvetica, Arial, sans-serif', serif: 'Georgia, Times, "Times New Roman", serif', monoSpaced: "Consolas, monaco, monospace", });
These values can also be functions that return CSS values.
theme('mode', { light: props => props.theme.userProfileAccentColor.light, dark: props => props.theme.userProfileAccentColor.dark, })
theme will create a function that you can use as a value in styled-component's styled function.
import styled from 'styled-components' import theme from 'styled-theming' const backgroundColor = theme('mode', { light: '#fff', dark: '#000', }) const Box = styled.div` background-color: ${backgroundColor}; `
It's often useful to create variants of the same component that are selected via an additional prop.
To make this easier with theming, styled-theming provides a theme.variants function.
import styled from "styled-components"; import theme from "styled-theming"; const backgroundColor = theme.variants("mode", "variant", { default: { light: "gray", dark: "darkgray" }, primary: { light: "blue", dark: "darkblue" }, success: { light: "green", dark: "darkgreen" }, warning: { light: "orange", dark: "darkorange" }, }); const Button = styled.button` background-color: ${backgroundColor}; `; Button.propTypes = { variant: PropTypes.oneOf(["default", "primary", "success", "warning"]) }; Button.defaultProps = { variant: "default", }; <Button /> <Button variant="primary" /> <Button variant="success" /> <Button variant="warning" />
The one thing you used to lose when writing CSS in template literals is syntax highlighting. We're working hard on making proper syntax highlighting happening in all editors. We currently have support for Atom, Visual Studio Code, WebStorm, and soon Sublime Text.
This is what it looks like when properly highlighted:
@gandm, the creator of language-babel, has added support for styled-components in Atom!
To get proper syntax highlighting, all you have to do is install and use the language-babel package for your JavaScript files!
A PR by @garetmckinley has been merged into babel-sublime but has not been released to Package Control. It is, however, available to install directly from GitHub as described in this issue.
Another option is Naomi by Alexandre Borela, a collection of syntax highlighting definitions for Sublime Text 3 which supports styled-components out-of-the-box.
@gandm's language-babel has been ported to VSCode under the name Babel JavaScript by Michael McDermott. It provides the same all-in-one solution for Babel syntax highlighting with styled-components included.
If you would like to keep your current JavaScript syntax highlighting, you can use the vscode-styled-components extension to provide styled-components syntax highlighting inside your Javascript files. You can install it as usual from the Marketplace.
The vim-styled-components plugin gives you syntax highlighting inside your Javascript files. Install it with your usual plugin manager like Plug, Vundle, Pathogen, etc.
Also if you're looking for an awesome javascript syntax package you can never go wrong with YAJS.vim.
The webstorm-styled-components plugin adds code completion and highlighting for CSS properties and values in the template strings. And it also provides code completion and navigation for JavaScript symbols in the interpolations. You can install it from the IDE: go to Preferences | Plugins and search for Styled Components.
We could use your help to get syntax highlighting support to other editors! All these syntax highlighting were built by the Styled Components community so if you want to start working on syntax highlighting for your editor, we would love to see it.