Full CSS support for JSX without compromises, providing scoped component-friendly CSS with server-side rendering support
—
CSS utilities for creating styles outside of JSX components, including scoped class generation and global style definition.
Creates scoped CSS styles outside of JSX components. Requires Babel transformation to function properly.
/**
* Creates scoped CSS styles (compile-time only)
* @param chunks - Template literal string chunks
* @param args - Template literal interpolated values
* @returns JSX style element (after Babel transformation)
* @throws Error if not processed by styled-jsx Babel plugin
*/
function css(chunks: TemplateStringsArray, ...args: any[]): JSX.Element;Usage Examples:
import css from 'styled-jsx/css';
// Basic scoped CSS
const buttonStyles = css`
.button {
padding: 12px 24px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
}
.button:hover {
opacity: 0.9;
}
`;
function Button({ children }) {
return (
<div>
<button className="button">{children}</button>
{buttonStyles}
</div>
);
}
// With dynamic values
function createThemeStyles(theme) {
return css`
.container {
background: ${theme.background};
color: ${theme.text};
padding: ${theme.spacing.medium};
}
.header {
border-bottom: 1px solid ${theme.border};
margin-bottom: ${theme.spacing.large};
}
`;
}
function ThemedComponent({ theme, children }) {
const styles = createThemeStyles(theme);
return (
<div className="container">
<div className="header">Header</div>
{children}
{styles}
</div>
);
}Creates global CSS styles that are not scoped to components.
/**
* Creates global CSS styles (compile-time only)
* @param chunks - Template literal string chunks
* @param args - Template literal interpolated values
* @returns JSX style element with global styles (after Babel transformation)
* @throws Error if not processed by styled-jsx Babel plugin
*/
function css.global(
chunks: TemplateStringsArray,
...args: any[]
): JSX.Element;Usage Examples:
import css from 'styled-jsx/css';
// Global reset styles
const globalReset = css.global`
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html, body {
height: 100%;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}
button {
font-family: inherit;
}
`;
function App() {
return (
<div>
<h1>My Application</h1>
{globalReset}
</div>
);
}
// Dynamic global styles
function createGlobalTheme(theme) {
return css.global`
:root {
--primary-color: ${theme.primary};
--secondary-color: ${theme.secondary};
--background-color: ${theme.background};
--text-color: ${theme.text};
}
body {
background-color: var(--background-color);
color: var(--text-color);
}
.btn-primary {
background-color: var(--primary-color);
color: white;
}
`;
}
function ThemeProvider({ theme, children }) {
const globalTheme = createGlobalTheme(theme);
return (
<div>
{globalTheme}
{children}
</div>
);
}Creates scoped CSS that returns both the generated className and the style element, useful for styling external components.
/**
* Creates scoped CSS that returns className and styles (compile-time only)
* @param chunks - Template literal string chunks
* @param args - Template literal interpolated values
* @returns Object with className and styles (after Babel transformation)
* @throws Error if not processed by styled-jsx Babel plugin
*/
function css.resolve(
chunks: TemplateStringsArray,
...args: any[]
): { className: string; styles: JSX.Element };Usage Examples:
import css from 'styled-jsx/css';
import ExternalComponent from 'some-library';
// Basic resolve usage
function StyledExternalComponent() {
const { className, styles } = css.resolve`
a {
color: #007bff;
text-decoration: none;
font-weight: 500;
}
a:hover {
text-decoration: underline;
}
`;
return (
<div>
<ExternalComponent className={className} />
{styles}
</div>
);
}
// Dynamic resolve styles
function createLinkStyles(color, size) {
return css.resolve`
a {
color: ${color};
font-size: ${size};
text-decoration: none;
border-bottom: 1px solid transparent;
transition: border-color 0.2s;
}
a:hover {
border-bottom-color: ${color};
}
`;
}
function CustomLink({ href, color = '#007bff', size = '16px', children }) {
const { className, styles } = createLinkStyles(color, size);
return (
<div>
<a href={href} className={className}>
{children}
</a>
{styles}
</div>
);
}
// Multiple resolved styles
function MultiStyleComponent() {
const buttonStyle = css.resolve`
button {
padding: 8px 16px;
border: none;
border-radius: 4px;
background: #007bff;
color: white;
cursor: pointer;
}
`;
const inputStyle = css.resolve`
input {
padding: 8px 12px;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 14px;
}
input:focus {
outline: none;
border-color: #007bff;
box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.25);
}
`;
return (
<form>
<input className={inputStyle.className} placeholder="Enter text" />
<button className={buttonStyle.className} type="submit">
Submit
</button>
{inputStyle.styles}
{buttonStyle.styles}
</form>
);
}Common patterns for styling external libraries and components using css.resolve.
// Pattern for styling third-party components
const { className, styles } = css.resolve`/* styles */`;
<ExternalComponent className={className} />
{styles}Usage Examples:
import css from 'styled-jsx/css';
import Select from 'react-select';
import DatePicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css';
// Styling react-select
function CustomSelect({ options, value, onChange }) {
const { className, styles } = css.resolve`
.react-select__control {
border: 2px solid #e1e5e9 !important;
border-radius: 8px !important;
min-height: 44px !important;
box-shadow: none !important;
}
.react-select__control--is-focused {
border-color: #007bff !important;
box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.1) !important;
}
.react-select__value-container {
padding: 8px 12px !important;
}
.react-select__option--is-focused {
background-color: #f8f9fa !important;
}
.react-select__option--is-selected {
background-color: #007bff !important;
}
`;
return (
<div>
<Select
className={className}
classNamePrefix="react-select"
options={options}
value={value}
onChange={onChange}
/>
{styles}
</div>
);
}
// Styling react-datepicker
function CustomDatePicker({ selected, onChange }) {
const { className, styles } = css.resolve`
.react-datepicker-wrapper {
width: 100%;
}
.react-datepicker__input-container input {
width: 100%;
padding: 12px 16px;
border: 2px solid #e1e5e9;
border-radius: 8px;
font-size: 16px;
background: white;
}
.react-datepicker__input-container input:focus {
outline: none;
border-color: #007bff;
box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.1);
}
.react-datepicker {
border: 1px solid #e1e5e9;
border-radius: 8px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.react-datepicker__header {
background-color: #007bff;
border-bottom: none;
border-radius: 8px 8px 0 0;
}
.react-datepicker__current-month {
color: white;
}
.react-datepicker__day--selected {
background-color: #007bff;
border-radius: 4px;
}
`;
return (
<div className={className}>
<DatePicker
selected={selected}
onChange={onChange}
dateFormat="MM/dd/yyyy"
placeholderText="Select a date"
/>
{styles}
</div>
);
}
// Modal/Dialog styling
import Modal from 'react-modal';
function StyledModal({ isOpen, onRequestClose, children }) {
const { className, styles } = css.resolve`
.modal-overlay {
background-color: rgba(0, 0, 0, 0.6) !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
}
.modal-content {
background: white !important;
border-radius: 12px !important;
padding: 24px !important;
max-width: 500px !important;
max-height: 80vh !important;
overflow-y: auto !important;
border: none !important;
outline: none !important;
position: relative !important;
}
`;
return (
<div>
<Modal
isOpen={isOpen}
onRequestClose={onRequestClose}
className={{
base: `modal-content ${className}`,
afterOpen: 'modal-content--after-open',
beforeClose: 'modal-content--before-close'
}}
overlayClassName={{
base: `modal-overlay ${className}`,
afterOpen: 'modal-overlay--after-open',
beforeClose: 'modal-overlay--before-close'
}}
>
{children}
</Modal>
{styles}
</div>
);
}Common error scenarios and solutions when using styled-jsx/css functions.
All css functions must be processed by the styled-jsx Babel plugin. Without proper transpilation, runtime errors will occur.
/**
* Runtime error thrown when css functions are not transpiled
* Occurs when Babel plugin is not configured or working properly
*/
class TranspilationError extends Error {
message: "styled-jsx/css: if you are getting this error it means that your `css` tagged template literals were not transpiled.";
}Common Error Scenarios:
import css from 'styled-jsx/css';
// ❌ This will throw an error if Babel plugin is not configured
const styles = css`
.button { color: red; }
`;
// Error: styled-jsx/css: if you are getting this error it means that your `css` tagged template literals were not transpiled.
// ❌ Same error for css.global
const globalStyles = css.global`
body { margin: 0; }
`;
// Error: styled-jsx/css: if you are getting this error it means that your `global` tagged template literals were not transpiled.
// ❌ Same error for css.resolve
const { className, styles } = css.resolve`
.link { color: blue; }
`;
// Error: styled-jsx/css: if you are getting this error it means that your `resolve` tagged template literals were not transpiled.Solutions:
// .babelrc or babel.config.js
{
"plugins": ["styled-jsx/babel"]
}// No configuration needed - styled-jsx is built into Next.js
export default function Page() {
return (
<div>
<style jsx>{`
.container { padding: 20px; }
`}</style>
</div>
);
}// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.(js|jsx)$/,
use: {
loader: 'babel-loader',
options: {
plugins: ['styled-jsx/babel']
}
}
}
]
}
};// babel.config.js
module.exports = {
plugins: [
[
'styled-jsx/babel',
{
optimizeForSpeed: process.env.NODE_ENV === 'production',
sourceMaps: process.env.NODE_ENV === 'development'
}
]
]
};Problem: CSS functions work in development but fail in production builds.
Solution: Ensure Babel plugin is included in production configuration:
// babel.config.js
module.exports = {
presets: ['@babel/preset-env', '@babel/preset-react'],
plugins: ['styled-jsx/babel'],
env: {
production: {
plugins: [
['styled-jsx/babel', { optimizeForSpeed: true }]
]
}
}
};Problem: TypeScript compilation errors with css template literals.
Solution: Install types and configure properly:
npm install --save-dev @types/styled-jsx// tsconfig.json
{
"compilerOptions": {
"jsx": "preserve",
"types": ["styled-jsx"]
}
}Problem: Styles not being extracted during SSR.
Solution: Use StyleRegistry for proper SSR handling:
import { StyleRegistry, createStyleRegistry } from 'styled-jsx';
import css from 'styled-jsx/css';
// ✅ Correct SSR setup
function renderPage() {
const registry = createStyleRegistry();
const appHtml = ReactDOM.renderToString(
<StyleRegistry registry={registry}>
<App />
</StyleRegistry>
);
const styles = registry.styles();
return { appHtml, styles };
}Install with Tessl CLI
npx tessl i tessl/npm-styled-jsx