OpenAINext.jsMar 28, 2019, 12:50 PM

Styling Next.js with Styled JSX

A condensed section focused on the key takeaways first.

Original Post

Quick Digest

Summary

A condensed section focused on the key takeaways first.

openaienmodel: gpt-5-mini-2025-08-07

Styling Next.js with Styled JSX

Key Points

  • Scoped component CSS by default
  • Global styles via <style jsx global>
  • Dynamic styles from props or themes

Summary

Styled JSX is included by default in Next.js and provides scoped, component-level CSS using a simple <style jsx> tag. It supports global styles (<style jsx global>), external style modules via styled-jsx/css, one-off global selectors with :global(), dynamic styles driven by props, and theming through imported theme objects. Use a Layout wrapped in pages/_app.js to share global styles across pages.

Key Points

  • Scoped component CSS: use <style jsx> inside the component root to scope styles automatically and avoid side effects.
  • Global styles: use <style jsx global> for page-specific globals or place globals in a Layout component and wrap pages via pages/_app.js.
  • External styles: move reusable/global CSS into styled-jsx/css modules and import them into components.
  • One-off overrides: target child components with :global(.className) when you need to override styles from a parent page.
  • Dynamic styles: adapt styles based on props either by injecting dynamic CSS in a separate <style jsx> tag or by toggling class names; separate static and dynamic styles for performance.
  • Theming: expose tokens in a styles/theme.js object and interpolate theme values into style jsx blocks to avoid hardcoded values.
  • Best practices: place <style jsx> inside the component root, keep dynamic parts isolated, and use a Layout for app-wide globals.

Quick recommendations

  • Prefer class toggles for complex conditional styles; use dynamic CSS blocks only when necessary.
  • Keep global rules minimal and scoped via a Layout to prevent unintended overrides.
  • Store common variables in a theme file and import them where needed.

Full Translation

Translations

A translation section that keeps the flow of the original article.

openaijamodel: gpt-5-mini-2025-08-07

Styled JSXでNext.jsをスタイリング

ブログに戻る — 2019年3月28日(木)

Styled JSXでNext.jsをスタイリング

Styled JSXはコンポーネント向けにカプセル化されスコープされたCSSを書けるCSS-in-JSライブラリです。あるコンポーネントに追加したスタイルは他のコンポーネントに影響を与えないため、意図しない副作用を気にせずにスタイルの追加・変更・削除ができます。

はじめに

Next.jsにはデフォルトでStyled JSXが含まれているため、既存のReact要素内に <style jsx> タグを追加してCSSを書くだけで開始できます。例えば:

pages/index.js
function Home () {
  return (
    <div className="container">
      <h1>Hello Next.js</h1>
      <p>Let's explore different ways to style Next.js apps</p>
      <style jsx>{ `
        .container { margin: 50px; }
        p { color: blue; }
      ` }</style>
    </div>
  );
}
export default Home;

この例ではコンポーネントのコンテナ要素と段落のためのスタイルを含めています。汎用的なセレクタを使っていても、これらのスタイルは他のコンポーネントの同名のクラスや <p> タグに影響しません。Styled JSXはスタイルをこのコンポーネントにのみスコープする(スタイルを適用する要素に追加のユニークなクラス名を付与する)ためです。

<style jsx> 属性を <style> 要素に追加するだけで、標準的なCSSを書け、ベンダープレフィックス付与やコンポーネント単位での自動スコープが行われます。<style jsx> 要素はコンポーネントのルート要素の中に置くべきです。

グローバルスタイルの追加

ほとんどのプロジェクトでは body 要素やリセット用のグローバルスタイルが必要になります。Styled JSXでは <style jsx global> を使ってグローバルスタイルを追加できます。例えば:

pages/index.js
function Home () {
  return (
    <div className="container">
      <h1>Hello Next.js</h1>
      <p>Let's explore different ways to style Next.js apps</p>
      <style jsx>{ `
        .container { margin: 50px; }
        p { color: blue; }
      ` }</style>
      <style jsx global>{ `
        p { font-size: 20px; }
      ` }</style>
    </div>
  );
}
export default Home;

この例ではこのページ内のすべての <p> タグに対して font-size: 20px が適用されます。アプリ内のすべてのページにグローバルスタイルを適用したい場合は、グローバルスタイルを含むレイアウトコンポーネントを作成し、すべてのページをそのレイアウトでラップするのが良い方法です。レイアウトコンポーネントを使うことで、あるページ群には特定のスタイルを適用しつつ、別のページには別のスタイルを与える柔軟性が得られます。

components/Layout.js
function Layout (props) {
  return (
    <div className="page-layout">
      {props.children}
      <style jsx global>{ `
        body {
          margin: 0;
          padding: 0;
          font-size: 18px;
          font-weight: 400;
          line-height: 1.8;
          color: #333;
          font-family: sans-serif;
        }
        h1 { font-weight: 700; }
        p { margin-bottom: 10px; }
      ` }</style>
    </div>
  );
}
export default Layout;

Next.jsでは pages/_app.js にカスタムAppコンポーネントを作成し、Layoutを読み込んでレンダーに追加することで、全ページでレイアウトを一度だけ読み込むことができます:

pages/_app.js
import React from 'react';
import App, { Container } from 'next/app';
import Layout from '../components/Layout';

class MyApp extends App {
  render () {
    const { Component, pageProps } = this.props;
    return (
      <Container>
        <Layout>
          <Component {...pageProps} />
        </Layout>
      </Container>
    );
  }
}
export default MyApp;

外部ファイルにスタイルを書く

コンポーネントの外部にスタイルを分離して書くこともできます。例えば、Layoutコンポーネントからグローバルスタイルを別ファイルに移動するには:

styles/global.js
import css from 'styled-jsx/css';
export default css.global `
  body {
    margin: 0;
    padding: 0;
    font-size: 18px;
    font-weight: 400;
    line-height: 1.8;
    color: #333;
    font-family: sans-serif;
  }
  h1 { font-weight: 700; }
  p { margin-bottom: 10px; }
`;

そしてそのスタイルをLayoutにインポートして使います:

components/Layout.js
import globalStyles from '../styles/global.js';
function Layout (props) {
  return (
    <div className="page-layout">
      {props.children}
      <style jsx global>{globalStyles}</style>
    </div>
  );
}
export default Layout;

一時的なグローバルセレクタ

<style jsx> でコンポーネントに追加したスタイルはそのコンポーネント内の要素にのみ影響し、子コンポーネントには影響を与えません。場合によっては子コンポーネントの特定のスタイルを上書きしたいことがあります。そのような場合、Styled JSXは :global() を提供しており、ワンオフのグローバルセレクタにアクセスできます。例えば、<Widget> コンポーネントに btn クラスのボタンがあり、ホームページ上でそのボタンの色だけを変えたい場合は次のようにします:

pages/index.js
import Widget from '../components/Widget';
function Home () {
  return (
    <div className="container">
      <h1>Hello Next.js</h1>
      <Widget />
      <style jsx>{ `
        .container { margin: 50px; }
        .container :global(.btn) { background: #000; color: #fff; }
      ` }</style>
    </div>
  );
}
export default Home;

この例では .container :global(.btn) により、Widget の内部にある .btn に対してのみスタイルを適用しています。

動的スタイル

コンポーネントのスタイルを props に基づいて変更できることはCSS-in-JSの大きな利点のひとつです。Styled JSXでは次のようにできます:

components/Alert.js
function Alert (props) {
  return (
    <div className="alert">
      {props.children}
      <style jsx>{ `
        .alert { display: inline-block; padding: 20px; border-radius: 8px; }
      ` }</style>
      <style jsx>{ `
        .alert { background: ${props.type == 'warning' ? '#fff3cd' : '#eee'}; }
      ` }</style>
    </div>
  );
}
export default Alert;

例えば <Alert type="warning">This is an important message</Alert> のように typewarning を渡すと、オレンジ色の背景になります。type を指定しない場合はデフォルトのグレー背景になります。

動的なスタイルは別の <style jsx> タグに分けて置くことを推奨します。これは必須ではありませんが、静的な部分と動的な部分を分離することで props が変化したときに再計算されるのを最小限にできます。

別のアプローチとして、props の値に応じて異なるクラス名を適用する方法もあります:

components/Alert.js
function Alert (props) {
  return (
    <div className={props.type == 'warning' ? 'alert warning' : 'alert'}>
      {props.children}
      <style jsx>{ `
        .alert { display: inline-block; padding: 20px; border-radius: 8px; background: #eee; }
        .alert.warning { background: #fff3cd; }
      ` }</style>
    </div>
  );
}
export default Alert;

サイトテーマの作成

テーマはアプリでよく使う変数をまとめたシンプルなオブジェクトにできます:

styles/theme.js
const theme = {
  fontFamily: {
    sansSerif: '-apple-system, "Helvetica Neue", Arial, sans-serif',
    mono: 'Menlo, Monaco, monospace',
  },
  colors: {
    text: '#333',
    background: '#fff',
    link: '#1eaaf1',
    linkHover: '#0d8ecf',
    border: '#ddd',
    warning: '#fff3cd',
    success: '#d4edda',
  },
};
export default theme;

このテーマファイルをコンポーネントでインポートし、ハードコードされた値を変数に置き換えます:

components/Layout.js
import theme from '../styles/theme';
function Layout (props) {
  return (
    <div className="page-wrapper">
      {props.children}
      <style jsx global>{ `
        body { background: ${theme.colors.background}; color: ${theme.colors.text}; font-family: ${theme.fontFamily.sansSerif}; }
      ` }</style>
      <style jsx global>{ `
        body { margin: 0; padding: 0; font-size: 18px; font-weight: 400; line-height: 1.8; }
        h1 { font-weight: 700; }
        p { margin-bottom: 10px; }
      ` }</style>
    </div>
  );
}
export default Layout;

components/Alert.js
import theme from '../styles/theme';
function Alert (props) {
  return (
    <div className="alert">
      {props.children}
      <style jsx>{ `
        .alert { display: inline-block; padding: 20px; border-radius: 8px; }
      ` }</style>
      <style jsx>{ `
        .alert { background: ${props.type == 'warning' ? theme.colors.warning : theme.colors.light}; }
      ` }</style>
    </div>
  );
}
export default Alert;

まとめ

本投稿ではStyled JSXの基本的な使い方を紹介しました。追加の機能について詳しくは、GitHub をチェックしてください。