CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-styled-jsx

Full CSS support for JSX without compromises, providing scoped component-friendly CSS with server-side rendering support

Pending
Overview
Eval results
Files

external-css.mddocs/

External CSS

CSS utilities for creating styles outside of JSX components, including scoped class generation and global style definition.

Capabilities

css Function (Default Export)

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

css.global Function

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

css.resolve Function

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

Styling Third-Party Components

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

Error Handling

Common error scenarios and solutions when using styled-jsx/css functions.

Transpilation Errors

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:

  1. Configure Babel Plugin:
// .babelrc or babel.config.js
{
  "plugins": ["styled-jsx/babel"]
}
  1. Next.js (built-in support):
// No configuration needed - styled-jsx is built into Next.js
export default function Page() {
  return (
    <div>
      <style jsx>{`
        .container { padding: 20px; }
      `}</style>
    </div>
  );
}
  1. Webpack Configuration:
// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        use: {
          loader: 'babel-loader',
          options: {
            plugins: ['styled-jsx/babel']
          }
        }
      }
    ]
  }
};
  1. Development vs Production:
// babel.config.js
module.exports = {
  plugins: [
    [
      'styled-jsx/babel',
      {
        optimizeForSpeed: process.env.NODE_ENV === 'production',
        sourceMaps: process.env.NODE_ENV === 'development'
      }
    ]
  ]
};

Build Environment Issues

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 }]
      ]
    }
  }
};

TypeScript Integration

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"]
  }
}

Server-Side Rendering Issues

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

docs

babel-macro.md

build-integration.md

component-styling.md

external-css.md

index.md

style-registry.md

tile.json