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.
optimizeForSpeedsourceMapsstyleModulevendorPrefixesclassName togglingstyleresolve tagjsx prop on <style> tagFirstly, 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 () => (
only this paragraph will get the style :)
{/* you can include <Component />s here that include
other
s that don't get unexpected styles! */}
<style jsx>{`
p {
color: red;
}
`}</style>
)
The following are optional settings for the babel plugin.
optimizeForSpeedBlazing 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'
sourceMapsGenerates source maps (default: false)
styleModuleModule that the transpiled files should import (default: styled-jsx/style)
vendorPrefixesTurn on/off automatic vendor prefixing (default: true)
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 () => (
only this paragraph will get the style :)
<_JSXStyle id="123">{`p.jsx-123 {color: red;}`}</_JSXStyle>
)
Unique classnames give us style encapsulation and _JSXStyle is heavily optimized for:
Notice that the outer `
from the example above also gets ajsx-123classname. We do this so that
you can target the "root" element, in the same manner that
[:host`](https://web.dev/articles/shadowdom-v1) works with Shadow DOM.
If you want to target only the host, we suggest you use a class:
export default () => (
<style jsx>{`
.root {
color: green;
}
`}</style>
)
To skip scoping entirely, you can make the global-ness of your styles explicit by adding global.
export default () => (
<style jsx global>{`
body {
background: red;
}
`}</style>
)
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 () => (
<Select optionClassName="react-select" />
<style jsx>{`
/* "div" will be prefixed, but ".react-select" won't */
div :global(.react-select) {
color: red;
}
`}</style>
)
To make a component's visual representation customizable from the outside world there are three options.
Any value that comes from the component's render method scope is treated as dynamic. This makes it possible to use props and state for example.
const Button = props => (
<button>
{props.children}
<style jsx>{`
button {
padding: ${'large' in props ? '50' : '20'}px;
background: ${props.theme.background};
color: #999;
display: inline-block;
font-size: 1em;
}
`}</style>
</button>
)
New styles' injection is optimized to perform well at runtime.
That said when your CSS is mostly static we recommend to split it up in static and dynamic styles and use two separate style tags so that, when changing, only the dynamic parts are recomputed/rendered.
const Button = props => (
<button>
{props.children}
<style jsx>{`
button {
color: #999;
display: inline-block;
font-size: 2em;
}
`}</style>
<style jsx>{`
button {
padding: ${'large' in props ? '50' : '20'}px;
background: ${props.theme.background};
}
`}</style>
</button>
)
className togglingThe second option is to pass properties that toggle class names.
const Button = props => (
<button className={'large' in props && 'large'}>
{props.children}
<style jsx>{`
button {
padding: 20px;
background: #eee;
color: #999;
}
.large {
padding: 50px;
}
`}</style>
</button>
)
Then you would use this component as either <Button>Hi</Button> or <Button large>Big</Button>.
style*best for animations
Imagine that you wanted to make the padding in the button above completely customizable. You can override the CSS you configure via inline-styles:
const Button = ({ padding, children }) => (
<button style={{ padding }}>
{children}
<style jsx>{`
button {
padding: 20px;
background: #eee;
color: #999;
}
`}</style>
</button>
)
In this example, the padding defaults to the one set in <style> (20), but the user can pass a custom one via <Button padding={30}>.
It is possible to use constants like so:
import { colors, spacing } from '../theme'
import { invertColor } from '../theme/utils'
const Button = ({ children }) => (
<button>
{children}
<style jsx>{`
button {
padding: ${spacing.medium};
background: ${colors.primary};
color: ${invertColor(colors.primary)};
}
`}</style>
</button>
)
Please keep in mind that constants defined outside of the component scope are treated as static styles.
styled-jsx v5 introduced StyledRegistry component and useStyleRegistry hook to let you scope styles rendering in each SSR render to keep concurrent-safe.
registry.styles() will return the array of react components for style tags.registry.flush() can clean the existing styles in the registry, it's optional for SSR when you have a standalone registry for each SSR render.Next.js 12 integrates with
styled-jsxv5 and manages the registry for you.
import React from 'react'
import ReactDOM from 'react-dom/server'
import { StyleRegistry, useStyleRegistry } from 'styled-jsx'
import App from './app'
function Styles() {
const registry = useStyleRegistry()
const styles = registry.styles()
return <>{styles}</>
}
export default (req, res) => {
const app = ReactDOM.renderToString(<App />)
const html = ReactDOM.renderToStaticMarkup(
<StyleRegistry>
<html>
<head>
<Styles />
</head>
<body>
</body>
</html>
</StyleRegistry>
)
res.end('<!doctype html>' + html)
}
There's also a new API createStyleRegistry that is introduced when you have to create a registry manually. In this way you can operate the registry yourself to extract the rendered styles (registry.styles()) or flush them out (registry.flush()).
const registry = createStyleRegistry()
const styles = registry.styles() // access styles
function Page() {
return (
<StyleRegistry registry={registry}>
<App />
</StyleRegistry>
)
}
By default <StyleRegistry /> will use the registry from root top StyleRegistry, which means there's only one registry in the react tree.
It's paramount that you use one of these two functions so that the generated styles can be diffed when the client loads and duplicate styles are avoided.
Strict CSP is supported.
You should generate a nonce per request.
import nanoid from 'nanoid'
const nonce = Buffer.from(nanoid()).toString('base64') //ex: N2M0MDhkN2EtMmRkYi00MTExLWFhM2YtNDhkNTc4NGJhMjA3
You must then pass a nonce to registry.styles({ nonce }) and set a <meta property="csp-nonce" content={nonce} /> tag.
Your CSP policy must share the same nonce as well (the header nonce needs to match the html nonce and remain unpredictable).
Content-Security-Policy: default-src 'self'; style-src 'self' 'nonce-N2M0MDhkN2EtMmRkYi00MTExLWFhM2YtNDhkNTc4NGJhMjA3';
In styled-jsx styles can be defined outside of the component's render method or in separate JavaScript modules using the styled-jsx/css library. styled-jsx/css exports three tags that can be used to tag your styles:
css, the default export, to define scoped styles.css.global to define global styles.css.resolve to define scoped styles that resolve to the scoped className and a styles element.In an external file:
/* styles.js */
import css from 'styled-jsx/css'
// Scoped styles
export const button = css`
button {
color: hotpink;
}
`
// Global styles
export const body = css.global`body { margin: 0; }`
// Resolved styles
export const link = css.resolve`a { color: green; }`
// link.className -> scoped className to apply to `a` elements e.g. jsx-123
// link.styles -> styles element to render inside of your component
// Works also with default exports
export default css`
div {
color: green;
}
`
You can then import and use those styles:
import styles, { button, body } from './styles'
export default () => (
<button>styled-jsx</button>
<style jsx>{styles}</style>
<style jsx>{button}</style>
<style jsx global>
{body}
</style>
)
N.B. All the tags except for resolve don't support dynamic styles.
resolve and global can also be imported individually:
import { resolve } from 'styled-jsx/css'
import { global } from 'styled-jsx/css'
If you use Prettier we recommend you to use the default css export syntax since the tool doesn't support named imports.
The css tag from styled-jsx/css can be also used to define styles in your components files but outside of the component itself. This might help wi
$ claude mcp add styled-jsx \
-- python -m otcore.mcp_server <graph>