1. Open Propsとは

Open Propsは、CSS変数(カスタムプロパティ)ベースのCSSフレームワークです。従来のBootstrapやTailwind CSSとは異なり、「コンポーネント」を提供するのではなく、デザインシステムの構築に必要な「CSS変数」のコレクションを提供します。

特徴

  • デザイントークンを提供: 色、サイズ、アニメーション、シャドウなど、様々なデザイン要素をCSS変数として提供
  • 非指示的(Non-prescriptive): スタイルの適用方法を強制せず、自由度が高い
  • 一貫性のあるデザイン: 標準化されたデザイントークンにより、統一感のあるUIを作成可能
  • インクリメンタルな採用: 必要な部分だけを選んで使うことができる
  • カスタマイズ可能: プロジェクトの要件に合わせて変更可能

State of CSS 2023では、Tailwind CSSを抑えて人気No.1のCSSフレームワークとなりました。

2. インストールと導入方法

CDN経由での利用

HTMLやCSSファイルにCDN経由でインポートするだけで使用できます。

<!-- HTMLでの読み込み -->
<link rel="stylesheet" href="https://unpkg.com/open-props"/>

<!-- オプションの機能拡張 -->
<link rel="stylesheet" href="https://unpkg.com/open-props/normalize.min.css"/>
<link rel="stylesheet" href="https://unpkg.com/open-props/buttons.min.css"/>

または、CSSファイル内でインポートする場合:

/* メインのスタイル変数 */
@import "https://unpkg.com/open-props";

/* オプションのコンポーネント */
@import "https://unpkg.com/open-props/normalize.min.css";
@import "https://unpkg.com/open-props/buttons.min.css";

/* 特定のカテゴリだけをインポート */
@import "https://unpkg.com/open-props/colors.min.css";
@import "https://unpkg.com/open-props/sizes.min.css";

npm経由でのインストール

プロジェクトにnpmを使用している場合は、以下のコマンドでインストールできます。

npm install open-props

インストール後、CSSファイルでインポートします:

/* メインのスタイル変数 */
@import "open-props/style";

/* オプションのコンポーネント */
@import "open-props/normalize";
@import "open-props/buttons";

/* 特定のカテゴリだけをインポート */
@import "open-props/colors";
@import "open-props/sizes";

3. 主要な機能と変数

Open Propsは多岐にわたるデザイン要素をカバーしています。ここでは主要なカテゴリを紹介します。

カラー

/* グレースケール */
--gray-0, --gray-1, ..., --gray-12

/* 基本色 */
--red-0, --red-1, ..., --red-12
--blue-0, --blue-1, ..., --blue-12
--green-0, --green-1, ..., --green-12
/* その他多くの色 */

サイズ

/* 基本サイズ */
--size-1, --size-2, ..., --size-15

/* 流動的なサイズ(レスポンシブ対応) */
--size-fluid-1, --size-fluid-2, ..., --size-fluid-10

タイポグラフィ

/* フォントサイズ */
--font-size-1, --font-size-2, ..., --font-size-8
--font-size-fluid-1, --font-size-fluid-2, --font-size-fluid-3

/* フォントウェイト */
--font-weight-1, --font-weight-2, ..., --font-weight-9

/* モダンフォントスタック */
--font-sans, --font-serif, --font-mono
--font-system-ui, --font-transitional, --font-old-style
/* 他多数 */

アニメーションとイージング

/* イージング関数 */
--ease-1, --ease-2, ..., --ease-5
--ease-in-1, --ease-in-2, ..., --ease-in-5
--ease-out-1, --ease-out-2, ..., --ease-out-5
/* 他多数 */

/* アニメーション */
--animation-fade-in, --animation-fade-out
--animation-slide-in-up, --animation-slide-out-down
/* 他多数 */

シャドウ

/* 外側シャドウ */
--shadow-1, --shadow-2, ..., --shadow-6

/* 内側シャドウ */
--inner-shadow-0, --inner-shadow-1, ..., --inner-shadow-4

メディアクエリ

PostCSSプラグインを使用することで、名前付きメディアクエリも利用可能です:

@custom-media --portrait (orientation: portrait);
@custom-media --landscape (orientation: landscape);

@custom-media --md-only (480px <= width < 768px);
@custom-media --md-n-above (width >= 768px);
@custom-media --md-n-below (width < 768px);

4. 実践的な活用例

基本的なコンポーネントのスタイリング

カードコンポーネントのスタイリング例:

.card {
  background: var(--surface-2);
  border: var(--border-size-1) solid var(--surface-3);
  border-radius: var(--radius-2);
  padding: var(--size-4);
  box-shadow: var(--shadow-2);
  transition: transform 0.2s var(--ease-3);
}

.card:hover {
  transform: translateY(var(--size-1-negative));
  box-shadow: var(--shadow-3);
}

.card__title {
  font-size: var(--font-size-4);
  margin-bottom: var(--size-3);
  color: var(--text-1);
}

.card__description {
  font-size: var(--font-size-2);
  color: var(--text-2);
  line-height: var(--font-lineheight-3);
}

ダークモード対応

Open Propsを使うと、ダークモード対応が簡単です:

/* ライトモード(デフォルト) */
:root {
  --brand: var(--brand-light);
  --text-1: var(--text-1-light);
  --text-2: var(--text-2-light);
  --surface-1: var(--surface-1-light);
  --surface-2: var(--surface-2-light);
}

/* ダークモード */
@media (prefers-color-scheme: dark) {
  :root {
    --brand: var(--brand-dark);
    --text-1: var(--text-1-dark);
    --text-2: var(--text-2-dark);
    --surface-1: var(--surface-1-dark);
    --surface-2: var(--surface-2-dark);
  }
}

これにより、コンポーネント側では単に var(--text-1)var(--surface-1) といった変数を使うだけで、自動的にテーマに応じた色が適用されます。

レスポンシブデザイン

流動的なサイズを使用することで、簡単にレスポンシブデザインを実現できます:

.hero-title {
  font-size: var(--font-size-fluid-3);
  padding: var(--size-fluid-2);
  max-width: var(--size-content-3);
}

.content {
  display: grid;
  gap: var(--size-fluid-1);
}

アニメーションの活用

.fade-in {
  animation: var(--animation-fade-in) forwards;
  animation-duration: 0.5s;
  animation-timing-function: var(--ease-3);
}

.button {
  transition: transform 0.2s var(--ease-out-3);
}

.button:hover {
  transform: scale(1.05);
}

5. フレームワークとの統合

Next.jsでの使用方法

Next.jsのApp Routerを使用する場合:

  1. Open Propsをインストール: npm install open-props
  2. グローバルCSSファイル (app/globals.css) で変数をインポート:
/* メインのスタイル変数 */
@import "open-props/style";

/* オプションのコンポーネント */
@import "open-props/normalize";
@import "open-props/buttons";

:root {
  /* カスタム変数の上書き */
  --blue-6: #1e40af; /* 例:プライマリカラーの上書き */
}
  1. ルートレイアウト (app/layout.tsx) でCSSをインポート:
import './globals.css';

export default function RootLayout({ children }) {
  return (
    <html lang="ja">
      <body>{children}</body>
    </html>
  );
}
  1. CSSモジュールでOpen Propsを活用:
/* Button.module.css */
.button {
  border-radius: var(--radius-2);
  padding: var(--size-2) var(--size-4);
  background-color: var(--blue-6);
  color: var(--gray-0);
  font-weight: var(--font-weight-5);
  transition: background-color 0.2s var(--ease-3);
}

.button:hover {
  background-color: var(--blue-7);
}

VS Codeでの開発効率化

VS Codeでの開発効率を高めるには、以下の拡張機能と設定が役立ちます:

  1. CSS Var Complete 拡張機能をインストール
  2. .vscode/settings.json に以下の設定を追加:
{
  "cssvar.files": [
    "./node_modules/open-props/open-props.min.css"
  ],
  "cssvar.ignore": [],
  "cssvar.extensions": [
    "css", "postcss", "jsx", "tsx"
  ]
}

これにより、CSS変数の入力補完が効くようになります。

6. 実践的なプロジェクト例

ブログサイトのデザインシステム構築

ブログサイトの主要コンポーネントをOpen Propsで構築する例:

/* 基本テーマ設定 */
:root {
  --brand: var(--indigo-6);
  --text-1: var(--gray-9);
  --text-2: var(--gray-7);
  --surface-1: var(--gray-0);
  --surface-2: var(--gray-1);
  --surface-3: var(--gray-2);
  --link: var(--indigo-7);
  --link-visited: var(--purple-7);
}

/* ダークモード */
@media (prefers-color-scheme: dark) {
  :root {
    --brand: var(--indigo-3);
    --text-1: var(--gray-1);
    --text-2: var(--gray-3);
    --surface-1: var(--gray-9);
    --surface-2: var(--gray-8);
    --surface-3: var(--gray-7);
    --link: var(--indigo-3);
    --link-visited: var(--purple-3);
  }
}

/* ベースレイアウト */
body {
  font-family: var(--font-sans);
  color: var(--text-1);
  background-color: var(--surface-1);
  line-height: var(--font-lineheight-3);
}

/* タイポグラフィ */
h1 {
  font-size: var(--font-size-fluid-3);
  font-weight: var(--font-weight-7);
  line-height: var(--font-lineheight-1);
  max-width: var(--size-header-2);
}

h2 {
  font-size: var(--font-size-fluid-2);
  font-weight: var(--font-weight-6);
  line-height: var(--font-lineheight-1);
}

p {
  font-size: var(--font-size-2);
  max-width: var(--size-content-3);
}

a {
  color: var(--link);
  transition: color 0.2s var(--ease-3);
}

a:hover {
  color: var(--brand);
}

/* コンポーネント */
.blog-card {
  display: grid;
  gap: var(--size-3);
  padding: var(--size-4);
  border-radius: var(--radius-2);
  background-color: var(--surface-2);
  box-shadow: var(--shadow-1);
  transition: transform 0.2s var(--ease-3), box-shadow 0.2s var(--ease-3);
}

.blog-card:hover {
  transform: translateY(var(--size-1-negative));
  box-shadow: var(--shadow-3);
}

.button {
  background-color: var(--brand);
  color: var(--gray-0);
  padding: var(--size-2) var(--size-4);
  border-radius: var(--radius-2);
  font-weight: var(--font-weight-5);
  transition: background-color 0.2s var(--ease-3);
}

.button:hover {
  background-color: var(--indigo-7);
}

7. CSS設計との組み合わせ

Open Propsは、単なるCSS変数の集合であるため、既存のCSS設計手法と組み合わせて使用できます。

BEMとの組み合わせ

/* BEMの命名規則とOpen Propsの組み合わせ */
.card {
  background-color: var(--surface-2);
  padding: var(--size-4);
}

.card__title {
  font-size: var(--font-size-4);
  color: var(--text-1);
}

.card__content {
  color: var(--text-2);
}

.card--featured {
  background-color: var(--brand);
  color: var(--gray-0);
}

CSSモジュールとの組み合わせ

CSSモジュールはOpen Propsとの相性が特に良く、カプセル化されたスタイルとグローバルなデザイントークンの良いバランスを提供します。

/* Button.module.css */
.button {
  background-color: var(--brand);
  padding: var(--size-2) var(--size-4);
  border-radius: var(--radius-2);
}

.primary {
  background-color: var(--blue-6);
}

.secondary {
  background-color: var(--purple-6);
}
import styles from './Button.module.css';

function Button({ children, variant = 'primary' }) {
  return (
    <button className={`${styles.button} ${styles[variant]}`}>
      {children}
    </button>
  );
}

8. パフォーマンス最適化

必要な変数だけをインポートする

すべての変数を一度にインポートするのではなく、必要な変数だけをインポートすることでパフォーマンスを向上させることができます。

/* 全変数のインポート(避けるべき) */
@import "open-props/style";

/* 必要な変数だけをインポート(推奨) */
@import "open-props/colors";
@import "open-props/sizes";
@import "open-props/animations";

PostCSS JIT Propsプラグインの使用

postcss-jit-propsプラグインを使用すると、実際に使用されている変数だけをスタイルシートに含めることができます。

npm install postcss-jit-props

postcss.config.js:

const postcssJitProps = require('postcss-jit-props');
const OpenProps = require('open-props');

module.exports = {
  plugins: [
    postcssJitProps(OpenProps),
    // 他のプラグイン
  ]
}

9. よくある質問と解決策

既存プロジェクトへの導入方法

段階的に導入することをお勧めします:

  1. まず、基本的な変数(色、サイズなど)だけを導入
  2. 新しいコンポーネントでOpen Propsの変数を使用
  3. 既存のコンポーネントを徐々に移行

ブラウザの互換性について

CSS変数は、すべてのモダンブラウザでサポートされています。IE11などの古いブラウザをサポートする必要がある場合は、フォールバック値を提供するか、PostCSSプラグインを使用して変換することを検討してください。

.element {
  /* フォールバック値 */
  background-color: #3498db;
  /* CSS変数 */
  background-color: var(--blue-6);
}

カスタマイズ方法

Open Propsの変数は、通常のCSS変数と同様に上書きできます:

:root {
  /* Open Propsの変数を上書き */
  --blue-6: #1e40af;
  --radius-2: 8px;
}

10. まとめ

Open Propsは、CSS変数を活用した新しいタイプのCSSフレームワークです。従来のフレームワークとは異なり、コンポーネントではなくデザイントークンを提供することで、より柔軟で一貫性のあるデザインシステムの構築を可能にします。

特に以下のような場合に効果を発揮します:

  • デザインシステムを構築したい場合
  • CSSに精通している開発者やデザイナー
  • フレキシブルなスタイリングが必要な場合
  • レスポンシブで一貫性のあるUIを構築したい場合

Open Propsは、CSS変数の力を最大限に活用し、Web開発における新しいアプローチを提供しています。適切に使用することで、開発効率の向上とデザインの一貫性維持の両方を実現できます。


参考資料

カテゴリー: CSSWEB