Full, scoped and component-friendly CSS support for JSX (rendered on the server or the client).
Code and docs are for v3 which we highly recommend you to try. Looking for styled-jsx v2? Switch to the v2 branch.
- Getting started
- Configuration options
- Features
- How It Works
- Targeting The Root
- Global styles
- Dynamic styles
- Constants
- Server-Side Rendering
- External CSS and styles outside of the component
- CSS Preprocessing via Plugins
- Rendering in tests
- FAQ
- Syntax Highlighting
- ESLint
- TypeScript
- Credits
Firstly, install the package:
npm install --save styled-jsx
Next, add styled-jsx/babel
to plugins
in your babel configuration:
{
"plugins": ["styled-jsx/babel"]
}
Now add <style jsx>
to your code and fill it with CSS:
export default () => (
<div>
<p>only this paragraph will get the style :)</p>
{/* you can include <Component />s here that include
other <p>s that don't get unexpected styles! */}
<style jsx>{`
p {
color: red;
}
`}</style>
</div>
)
The following are optional settings for the babel plugin.
Blazing fast and optimized CSS rules injection system based on the CSSOM APIs.
{
"plugins": [["styled-jsx/babel", { "optimizeForSpeed": true }]]
}
When in production* this mode is automatically enabled.
Beware that when using this option source maps cannot be generated and styles cannot be edited via the devtools.
* process.env.NODE_ENV === 'production'
Generates source maps (default: false
)
Module that the transpiled files should import (default: styled-jsx/style
)
Turn on/off automatic vendor prefixing (default: true
)
- Full CSS support, no tradeoffs in power
- Runtime size of just 3kb (gzipped, from 12kb)
- Complete isolation: Selectors, animations, keyframes
- Built-in CSS vendor prefixing
- Very fast, minimal and efficient transpilation (see below)
- High-performance runtime-CSS-injection when not server-rendering
- Future-proof: Equivalent to server-renderable "Shadow CSS"
- Source maps support
- Dynamic styles and themes support
- CSS Preprocessing via Plugins
Next.js automatically configures styled-jsx
with babel or swc, you don't have to configure it manually.
The example above transpiles to the following:
import _JSXStyle from 'styled-jsx/style'
export default () => (
<div className="jsx-123">
<p className="jsx-123">only this paragraph will get the style :)</p>
<_JSXStyle id="123">{`p.jsx-123 {color: red;}`}</_JSXStyle>
</div>
)
Unique classnames give us style encapsulation and _JSXStyle
is heavily optimized for:
- Injecting styles upon render
- Only injecting a certain component's style once (even if the component is included multiple times)
- Removing unused styles
- Keeping track of styles for server-side rendering
Notice that the outer <div>
from the example above also gets a jsx-123
classname. We do this so that
you can target the "root" element, in the same manner that
:host
works with Shadow DOM.
If you want to target only the host, we suggest you use a class:
export default () => (
<div className="root">
<style jsx>{`
.root {
color: green;
}
`}</style>
</div>
)
To skip scoping entirely, you can make the global-ness of your styles explicit by adding global.
export default () => (
<div>
<style jsx global>{`
body {
background: red;
}
`}</style>
</div>
)
The advantage of using this over <style>
is twofold: no need
to use dangerouslySetInnerHTML
to avoid escaping issues with CSS
and take advantage of styled-jsx
's de-duping system to avoid
the global styles being inserted multiple times.
Sometimes it's useful to skip selectors scoping. In order to get a one-off global selector we support :global()
, inspired by css-modules.
This is very useful in order to, for example, generate a global class that
you can pass to 3rd-party components. For example, to style
react-select
which supports passing a custom class via optionClassName
:
import Select from 'react-select'
export default () => (
<div>
<Select optionClassName="react-select" />
<style jsx>{`
/* "div" will be prefixed, but ".react-select" won't */
div :global(.react-select) {
color: red;
}
`}</style>
</div>
)