Agent Skills by ALSEL
Anthropic Claudeソフトウェア開発⭐ リポ 0品質スコア 50/100

postcss-best-practices

モダンなCSS処理と最適化のためのPostCSSベストプラクティスおよび設定ガイドラインを提供します。PostCSSの導入・設定・プラグイン選定に迷った際に活用でき、効率的なCSSビルドパイプラインの構築をサポートします。

description の原文を見る

PostCSS best practices and configuration guidelines for modern CSS processing and optimization

SKILL.md 本文

PostCSS ベストプラクティス

PostCSS、CSS処理パイプライン、モダン CSS ツーリングの専門家です。

主要な原則

  • PostCSS を用途別プラグインを備えたモジュール式 CSS プロセッサとして使用する
  • 適切なトランスパイルを備えたモダン構文を使用して将来対応の CSS を記述する
  • ミニフィケーションと自動プレフィックス付けを使って本番環境用に CSS 出力を最適化する
  • プラグイン設定はシンプルで目的志向的に保つ

PostCSS とは

PostCSS は JavaScript プラグインで CSS を変換するツールです。プリプロセッサ (Sass/Less) とは異なり、PostCSS は以下の特徴があります:

  • モジュール式 - 必要な機能だけを追加
  • 標準 CSS を解析・変換可能
  • 将来の CSS 構文を今すぐ実現
  • 出力を最適化・ミニフィケーション可能
  • あらゆるビルドツールで動作

プロジェクトセットアップ

インストール

# Core PostCSS
npm install postcss postcss-cli --save-dev

# Common plugins
npm install autoprefixer cssnano postcss-preset-env --save-dev

# Optional plugins
npm install postcss-import postcss-nested postcss-custom-media --save-dev

設定ファイル

// postcss.config.js
module.exports = {
  plugins: [
    require('postcss-import'),
    require('postcss-preset-env')({
      stage: 2,
      features: {
        'nesting-rules': true,
        'custom-media-queries': true,
        'custom-properties': true,
      },
    }),
    require('autoprefixer'),
    require('cssnano')({
      preset: ['default', {
        discardComments: { removeAll: true },
      }],
    }),
  ],
};

ビルドツール統合

Webpack

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          'style-loader',
          'css-loader',
          'postcss-loader',
        ],
      },
    ],
  },
};

Vite

// vite.config.js
import { defineConfig } from 'vite';

export default defineConfig({
  css: {
    postcss: './postcss.config.js',
  },
});

Next.js

// postcss.config.js (auto-detected)
module.exports = {
  plugins: {
    'postcss-import': {},
    'tailwindcss/nesting': {},
    tailwindcss: {},
    autoprefixer: {},
  },
};

必須プラグイン

postcss-preset-env

モダン CSS 機能をポリフィルで実現します:

// postcss.config.js
module.exports = {
  plugins: [
    require('postcss-preset-env')({
      stage: 2, // Stage 2 の機能は安定している
      features: {
        'nesting-rules': true,
        'custom-media-queries': true,
        'custom-selectors': true,
        'gap-properties': true,
        'logical-properties-and-values': true,
      },
      autoprefixer: { grid: true },
      browsers: 'last 2 versions',
    }),
  ],
};

autoprefixer

ベンダープレフィックスを自動的に追加します:

// postcss.config.js
module.exports = {
  plugins: [
    require('autoprefixer')({
      grid: 'autoplace', // グリッドプレフィックスを有効化
      flexbox: true,
    }),
  ],
};

// Input CSS
.element {
  display: flex;
  user-select: none;
}

// Output CSS
.element {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-user-select: none;
     -moz-user-select: none;
      -ms-user-select: none;
          user-select: none;
}

cssnano

本番環境用に CSS をミニフィケーション・最適化します:

// postcss.config.js
const isProduction = process.env.NODE_ENV === 'production';

module.exports = {
  plugins: [
    require('autoprefixer'),
    isProduction && require('cssnano')({
      preset: ['default', {
        discardComments: { removeAll: true },
        normalizeWhitespace: true,
        minifyFontValues: true,
        minifyGradients: true,
        reduceIdents: false, // アニメーション名を保持
        mergeRules: true,
        mergeLonghand: true,
      }],
    }),
  ].filter(Boolean),
};

postcss-import

@import ステートメントをインライン化します:

// postcss.config.js
module.exports = {
  plugins: [
    require('postcss-import')({
      path: ['src/styles'],
    }),
  ],
};
/* main.css */
@import 'variables.css';
@import 'base.css';
@import 'components/buttons.css';
@import 'components/cards.css';

postcss-nested

Sass のようなネストを可能にします:

// postcss.config.js
module.exports = {
  plugins: [
    require('postcss-nested'),
  ],
};
/* Input */
.card {
  background: white;

  &__header {
    padding: 16px;
  }

  &__body {
    padding: 16px;
  }

  &:hover {
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
  }

  @media (min-width: 768px) {
    display: flex;
  }
}

/* Output */
.card {
  background: white;
}
.card__header {
  padding: 16px;
}
.card__body {
  padding: 16px;
}
.card:hover {
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
@media (min-width: 768px) {
  .card {
    display: flex;
  }
}

モダン CSS 機能

CSS ネスティング (ネイティブ)

/* モダンブラウザはネイティブネストに対応 */
.card {
  background: white;
  border-radius: 8px;

  & .card-header {
    padding: 1rem;
    border-bottom: 1px solid #eee;
  }

  & .card-body {
    padding: 1rem;
  }

  &:hover {
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
  }

  @media (min-width: 768px) {
    display: flex;
  }
}

カスタムプロパティ (CSS 変数)

:root {
  /* Colors */
  --color-primary: #3498db;
  --color-primary-light: color-mix(in srgb, var(--color-primary), white 20%);
  --color-primary-dark: color-mix(in srgb, var(--color-primary), black 20%);
  --color-text: #333333;
  --color-background: #ffffff;
  --color-border: #e0e0e0;

  /* Typography */
  --font-family-base: 'Helvetica Neue', Arial, sans-serif;
  --font-size-base: 1rem;
  --line-height-base: 1.5;

  /* Spacing */
  --spacing-unit: 8px;
  --spacing-sm: calc(var(--spacing-unit) * 1);
  --spacing-md: calc(var(--spacing-unit) * 2);
  --spacing-lg: calc(var(--spacing-unit) * 3);
  --spacing-xl: calc(var(--spacing-unit) * 4);

  /* Transitions */
  --transition-base: 0.3s ease;

  /* Shadows */
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
  --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.1);
}

.button {
  padding: var(--spacing-sm) var(--spacing-md);
  background: var(--color-primary);
  color: white;
  transition: background var(--transition-base);
}

.button:hover {
  background: var(--color-primary-dark);
}

カスタムメディアクエリ

/* カスタムメディアクエリを定義 */
@custom-media --viewport-sm (min-width: 576px);
@custom-media --viewport-md (min-width: 768px);
@custom-media --viewport-lg (min-width: 992px);
@custom-media --viewport-xl (min-width: 1200px);

@custom-media --motion-ok (prefers-reduced-motion: no-preference);
@custom-media --dark-mode (prefers-color-scheme: dark);

/* 使用例 */
.element {
  width: 100%;
}

@media (--viewport-md) {
  .element {
    width: 50%;
  }
}

@media (--viewport-lg) {
  .element {
    width: 33.333%;
  }
}

@media (--motion-ok) {
  .element {
    transition: transform 0.3s ease;
  }
}

カスタムセレクタ

/* 再利用可能なセレクタを定義 */
@custom-selector :--heading h1, h2, h3, h4, h5, h6;
@custom-selector :--button button, [type="button"], [type="submit"];
@custom-selector :--enter :hover, :focus;

/* 使用例 */
:--heading {
  font-family: var(--font-family-heading);
  line-height: 1.2;
  margin-bottom: 1rem;
}

:--button {
  cursor: pointer;
  font-family: inherit;
}

.link:--enter {
  color: var(--color-primary);
  text-decoration: underline;
}

論理プロパティ

/* 国際化のために論理プロパティを使用 */
.element {
  /* margin-left/right の代わりに */
  margin-inline: auto;

  /* padding-top/bottom の代わりに */
  padding-block: var(--spacing-md);

  /* width/height の代わりに */
  inline-size: 100%;
  block-size: auto;

  /* border-left の代わりに */
  border-inline-start: 2px solid var(--color-primary);

  /* text-align: left の代わりに */
  text-align: start;
}

コンテナクエリ

/* モダンなコンテナクエリ */
.card-container {
  container-type: inline-size;
  container-name: card;
}

.card {
  display: block;
}

@container card (min-width: 400px) {
  .card {
    display: flex;
  }
}

@container card (min-width: 600px) {
  .card {
    gap: 2rem;
  }
}

ファイル構成

ディレクトリ構造

src/
├── styles/
│   ├── base/
│   │   ├── reset.css
│   │   ├── typography.css
│   │   └── base.css
│   ├── components/
│   │   ├── buttons.css
│   │   ├── cards.css
│   │   ├── forms.css
│   │   └── navigation.css
│   ├── layout/
│   │   ├── header.css
│   │   ├── footer.css
│   │   └── grid.css
│   ├── utilities/
│   │   ├── spacing.css
│   │   ├── colors.css
│   │   └── display.css
│   ├── variables.css
│   └── main.css
├── postcss.config.js
└── package.json

メインエントリーポイント

/* main.css */

/* 変数を最初にインポート */
@import 'variables.css';

/* リセットと基本スタイル */
@import 'base/reset.css';
@import 'base/typography.css';
@import 'base/base.css';

/* レイアウト */
@import 'layout/grid.css';
@import 'layout/header.css';
@import 'layout/footer.css';

/* コンポーネント */
@import 'components/buttons.css';
@import 'components/cards.css';
@import 'components/forms.css';
@import 'components/navigation.css';

/* ユーティリティ (詳細度のため最後) */
@import 'utilities/spacing.css';
@import 'utilities/colors.css';
@import 'utilities/display.css';

本番環境設定

環境別設定

// postcss.config.js
const isProduction = process.env.NODE_ENV === 'production';

module.exports = {
  plugins: [
    // 常に実行
    require('postcss-import'),
    require('postcss-preset-env')({
      stage: 2,
      features: {
        'nesting-rules': true,
        'custom-media-queries': true,
      },
    }),
    require('autoprefixer'),

    // 本番環境のみ
    isProduction && require('cssnano')({
      preset: ['default', {
        discardComments: { removeAll: true },
        reduceIdents: false,
        zindex: false,
      }],
    }),

    isProduction && require('@fullhuman/postcss-purgecss')({
      content: [
        './src/**/*.html',
        './src/**/*.js',
        './src/**/*.jsx',
        './src/**/*.tsx',
      ],
      safelist: {
        standard: [/^is-/, /^has-/, /^js-/],
        deep: [/modal/, /tooltip/],
      },
    }),
  ].filter(Boolean),
};

ブラウザサポート

// package.json
{
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not dead",
    "not ie 11"
  ]
}

// または .browserslistrc
> 1%
last 2 versions
not dead
not ie 11

有用なプラグイン設定

postcss-custom-media

require('postcss-custom-media')({
  importFrom: [
    {
      customMedia: {
        '--viewport-sm': '(min-width: 576px)',
        '--viewport-md': '(min-width: 768px)',
        '--viewport-lg': '(min-width: 992px)',
        '--viewport-xl': '(min-width: 1200px)',
      },
    },
  ],
});

postcss-mixins

require('postcss-mixins')({
  mixins: {
    'flex-center': {
      display: 'flex',
      'align-items': 'center',
      'justify-content': 'center',
    },
    'visually-hidden': {
      position: 'absolute',
      width: '1px',
      height: '1px',
      overflow: 'hidden',
      clip: 'rect(0, 0, 0, 0)',
    },
  },
});

postcss-simple-vars

require('postcss-simple-vars')({
  variables: {
    'color-primary': '#3498db',
    'spacing-unit': '8px',
  },
});

パフォーマンスのコツ

  • プラグインを正しく順序付ける:import、preset-env/nesting、autoprefixer、cssnano
  • 本番環境で未使用スタイルを削除するために PurgeCSS を使用
  • 開発環境でのみソースマップを有効化
  • 可能な場合、ビルドツール内で PostCSS の結果をキャッシュ
  • 不要なプラグインを避ける - 各プラグインは処理時間を追加
  • browserslist を使用して必要なブラウザのみをターゲット

一般的なプラグイン組み合わせ

ミニマルセットアップ

module.exports = {
  plugins: [
    require('autoprefixer'),
    require('cssnano'),
  ],
};

モダン CSS 機能

module.exports = {
  plugins: [
    require('postcss-import'),
    require('postcss-preset-env')({ stage: 2 }),
    require('autoprefixer'),
    require('cssnano'),
  ],
};

Sass のような機能

module.exports = {
  plugins: [
    require('postcss-import'),
    require('postcss-mixins'),
    require('postcss-simple-vars'),
    require('postcss-nested'),
    require('autoprefixer'),
    require('cssnano'),
  ],
};

Tailwind CSS を使用

module.exports = {
  plugins: {
    'postcss-import': {},
    'tailwindcss/nesting': {},
    tailwindcss: {},
    autoprefixer: {},
    ...(process.env.NODE_ENV === 'production' ? { cssnano: {} } : {}),
  },
};

デバッグ

ソースマップを有効化

// postcss.config.js
module.exports = {
  map: process.env.NODE_ENV !== 'production'
    ? { inline: false }
    : false,
  plugins: [
    // ...plugins
  ],
};

詳細出力

# 詳細出力付きの CLI
postcss src/main.css -o dist/main.css --verbose

プラグイン順序を確認

スタイルが期待通りに動作しない場合:

  1. プラグイン順序を確認 (他の前に import)
  2. preset-env のステージ設定を検証
  3. browserslist の設定を確認
  4. cssnano のオプションを確認 (過度な最適化の可能性)

ライセンス: Apache-2.0(寛容ライセンスのため全文を引用しています) · 原本リポジトリ

詳細情報

作者
mindrally
リポジトリ
mindrally/skills
ライセンス
Apache-2.0
最終更新
不明

Source: https://github.com/mindrally/skills / ライセンス: Apache-2.0

関連スキル

汎用ソフトウェア開発⭐ リポ 39,967

doubt-driven-development

重要な判断はすべて、本番環境への展開前に新しい視点から対抗的レビューを実施します。速度より正確性が重要な場合、不慣れなコードを扱う場合、本番環境・セキュリティに関わるロジック・取り消し不可の操作など影響度が高い場合、または後でバグを修正するよりも今検証する方が効率的な場合に活用してください。

by addyosmani
汎用ソフトウェア開発⭐ リポ 1,175

apprun-skills

TypeScriptを使用したAppRunアプリケーションのMVU設計に関する総合的なガイダンスが得られます。コンポーネントパターン、イベントハンドリング、状態管理(非同期ジェネレータを含む)、パラメータと保護機能を備えたルーティング・ナビゲーション、vistestを使用したテストに対応しています。AppRunコンポーネントの設計・レビュー、ルートの配線、状態フローの管理、AppRunテストの作成時に活用してください。

by yysun
OpenAIソフトウェア開発⭐ リポ 797

desloppify

コードベースのヘルスチェックと技術負債の追跡ツールです。コード品質、技術負債、デッドコード、大規模ファイル、ゴッドクラス、重複関数、コードスメル、命名規則の問題、インポートサイクル、結合度の問題についてユーザーが質問した場合に使用してください。また、ヘルススコアの確認、次の改善項目の提案、クリーンアップ計画の作成をリクエストされた際にも対応します。29言語に対応しています。

by Git-on-my-level
汎用ソフトウェア開発⭐ リポ 39,967

debugging-and-error-recovery

テストが失敗したり、ビルドが壊れたり、動作が期待と異なったり、予期しないエラーが発生したりした場合に、体系的な根本原因デバッグをガイドします。推測ではなく、根本原因を見つけて修正するための体系的なアプローチが必要な場合に使用してください。

by addyosmani
汎用ソフトウェア開発⭐ リポ 39,967

test-driven-development

テスト駆動開発により実装を進めます。ロジックの実装、バグの修正、動作の変更など、あらゆる場面で活用できます。コードが正常に動作することを証明する必要がある場合、バグ報告を受けた場合、既存機能を修正する予定がある場合に使用してください。

by addyosmani
汎用ソフトウェア開発⭐ リポ 39,967

incremental-implementation

変更を段階的に実施します。複数のファイルに影響する機能や変更を実装する場合に使用してください。大量のコードを一度に書こうとしている場合や、タスクが一度では完結できないほど大きい場合に活用します。

by addyosmani
本サイトは GitHub 上で公開されているオープンソースの SKILL.md ファイルをクロール・インデックス化したものです。 各スキルの著作権は原作者に帰属します。掲載に問題がある場合は info@alsel.co.jp または /takedown フォームよりご連絡ください。
原作者: mindrally · mindrally/skills · ライセンス: Apache-2.0