MCPcopy
hub / github.com/vercel/styled-jsx

github.com/vercel/styled-jsx @v5.1.7 sqlite

repository ↗ · DeepWiki ↗ · release v5.1.7 ↗
152 symbols 357 edges 79 files 2 documented · 1%
README

styled-jsx

build status

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

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 () => (





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>



)

Configuration options

The following are optional settings for the babel plugin.

optimizeForSpeed

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'

sourceMaps

Generates source maps (default: false)

styleModule

Module that the transpiled files should import (default: styled-jsx/style)

vendorPrefixes

Turn on/off automatic vendor prefixing (default: true)

Features

  • 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

Using in Next.js

Next.js automatically configures styled-jsx with babel or swc, you don't have to configure it manually.

How It Works

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>



)

Why It Works Like This

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

Targeting The Root

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>



)

Global styles

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.

One-off global selectors

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>



)

Dynamic styles

To make a component's visual representation customizable from the outside world there are three options.

Via interpolated dynamic props

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>
)

Via className toggling

The 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>.

Via inline 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}>.

Constants

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.

Server-Side Rendering

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-jsx v5 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.

Content Security Policy

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';

External CSS and styles outside of the component

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.

External styles

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.

Styles outside of components

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

Extension points exported contracts — how you extend this code

StyleHTMLAttributes (Interface)
(no doc)
global.d.ts

Core symbols most depended-on inside this repo

cssRules
called by 22
src/lib/stylesheet.js
add
called by 20
src/stylesheet-registry.js
transform
called by 19
test/index.js
assert
called by 18
test/styles.js
withMock
called by 17
test/helpers/with-mock.js
insertRule
called by 15
src/lib/stylesheet.js
transformSource
called by 13
test/_transform.js
combinePlugins
called by 12
src/_utils.js

Shape

Function 112
Method 26
Class 13
Interface 1

Languages

TypeScript100%

Modules by API surface

src/_utils.js28 symbols
src/lib/stylesheet.js17 symbols
src/stylesheet-registry.js16 symbols
test/fixtures/attribute-generation-modes.js11 symbols
test/index.js9 symbols
test/fixtures/multiple-jsx.js5 symbols
src/babel.js5 symbols
test/helpers/with-mock.js4 symbols
src/babel-external.js4 symbols
test/stylesheet-registry.js3 symbols
test/fixtures/macro.js3 symbols
test/fixtures/dynamic-element-class.js3 symbols

Dependencies from manifests, versioned

@babel/cli7.18.10 · 1×
@babel/core7.12.3 · 1×
@babel/plugin-proposal-object-rest-spread7.12.1 · 1×
@babel/plugin-syntax-jsx7.14.5 · 1×
@babel/plugin-transform-arrow-functions7.12.1 · 1×
@babel/plugin-transform-modules-commonjs7.12.1 · 1×
@babel/plugin-transform-runtime7.12.1 · 1×
@babel/preset-env7.12.1 · 1×
@babel/preset-react7.12.5 · 1×
@babel/register7.12.1 · 1×
@babel/runtime7.12.5 · 1×
@babel/types7.15.0 · 1×

For agents

$ claude mcp add styled-jsx \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact