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 } ] ] }
displayName
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.
This plugin adds support for server-side rendering, minification of styles, and better debugging experience when using styled-components with the SWC compiler.
First, install the @swc/plugin-styled-components
and @swc/core
packages:
npm install --save-dev @swc/plugin-styled-components @swc/core
Then, add the plugin to your .swcrc
configuration file:
{ "jsc": { "experimental": { "plugins": [ [ "@swc/plugin-styled-components", { "displayName": true, "ssr": true } ] ] } } }
displayName
:
displayName
in React DevTools.true
true
or false
ssr
:
true
true
or false
fileName
:
displayName
of a component will be prefixed with the filename or solely the component name.true
true
or false
meaninglessFileNames
:
["index", "styles"]
minify
:
true
true
or false
transpileTemplateLiterals
:
styled-components
tagged template literals to a smaller representation. Helps reduce bundle size.true
true
or false
pure
:
false
true
or false
namespace
:
undefined
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 don't 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 this feature by setting the ssr
option to false
:
{ "jsc": { "experimental": { "plugins": [ [ "@swc/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. It also allows you to see the component's displayName
in React
DevTools.
If you don't need this feature, you can disable it by setting the displayName
option to false
:
{ "jsc": { "experimental": { "plugins": [ [ "@swc/plugin-styled-components", { "displayName": false } ] ] } } }
displayName
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:
{ "jsc": { "experimental": { "plugins": [ [ "@swc/plugin-styled-components", { "fileName": false } ] ] } } }
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 displayName
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 you 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:
{ "jsc": { "experimental": { "plugins": [ [ "@swc/plugin-styled-components", { "meaninglessFileNames": ["index", "styles"] } ] ] } } }
This plugin minifies your CSS by removing all whitespace and comments. It also transpiles tagged template literals to a smaller representation, keeping valuable bytes out of your bundles.
If desired, you can disable this behavior by setting the minify
option to false
:
{ "jsc": { "experimental": { "plugins": [ [ "@swc/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".
{ "jsc": { "experimental": { "plugins": [ [ "@swc/plugin-styled-components", { "pure": true } ] ] } } }
Similar to the Babel plugin, this plugin transpiles styled-components
tagged template literals to a smaller representation than what SWC normally creates. This helps reduce the bundle size.
You can disable this feature by setting the transpileTemplateLiterals
option to false
:
{ "jsc": { "experimental": { "plugins": [ [ "@swc/plugin-styled-components", { "transpileTemplateLiterals": false } ] ] } } }
The namespace
option ensures that your class names will be unique, which is handy when working with micro-frontends where class name collisions can occur.
To enable this behavior, set the namespace
option in your configuration:
{ "jsc": { "experimental": { "plugins": [ [ "@swc/plugin-styled-components", { "namespace": "my-app" } ] ] } } }
This functionality was removed in v6.1 due to lack of usage and unnecessary bloat for other consumers. More info
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:
.babel-plugin-macrosrc
.babel-plugin-macrosrc.json
.babel-plugin-macrosrc.yaml
.babel-plugin-macrosrc.yml
.babel-plugin-macrosrc.js
babel-plugin-macros.config.js
babelMacros
in package.json
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.
toHaveStyleRule
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:
stylelint
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:
stylelint
styled-components
stylelint-config-styled-components
to disable stylelint rules that clash with styled-components
stylelint
config! (for example stylelint-config-recommended
)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.
stylelint-config-styled-components
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.
stylelint-processor-styled-components
)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:
sc-block
sc-selector
sc-declaration
sc-property
sc-value
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
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>
<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> ); }
theme(name, values)
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}; `
theme.variants(name, prop, themes)
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.