14
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

PostCSSでCSSをSassに近づける

Last updated at Posted at 2022-12-14

この記事の概要

再現する対象

以下の7つの特徴を再現できるように挑みます。

  • Variables
  • Nesting
  • Partials
  • Modules
  • Mixins
  • Extend/Inheritance
  • Operators

こちらの特徴は、公式ドキュメントのガイドページを参照しています。

準備

まずはPostCSSのインストールからです。

npm i -D postcss postcss-cli

ひとまず空のpostcss.config.jsを作成します。

postcss.config.js
module.exports = {}

package.jsonに変換用のコマンドを追加します(コマンド名や書き出したCSSのファイル名は何でもOKです)。

package.json
{
//省略
  "scripts": {
    "css:watch": "postcss 変換前.css -o dist.css -w"
  },
}

あとはCSSを監視します。

npm run css:watch

Variables

Sassの変数とは違いますが、今やCSS純正のCustom Propertiesが使えるのでそちらを使います。
そのため、特別な設定は不要です。

Nesting

postcss-nestedを使います。

npm i -D postcss-nested

postcss.config.jsに設定を追加します。

postcss.config.js
  module.exports = {
+   plugins: [
+     require('postcss-nested')
+   ],
  }

あとは通常のSassと同じくネストして書けばOKです。
以下のコードもそうですが、例として示すコードはリポジトリに載っているコード(またはそれを多少いじったもの)です。

変換前
.phone {
  &_title {
    width: 500px;
    @media (max-width: 500px) {
      width: auto;
    }
    body.is_dark & {
      color: white;
    }
  }
  img {
    display: block;
  }
}

.title {
  font-size: var(--font);

  @at-root html {
    --font: 16px
  }
}
変換後
.phone_title {
  width: 500px;
}

@media (max-width: 500px) {
  .phone_title {
    width: auto;
  }
}

body.is_dark .phone_title {
  color: white;
}

.phone img {
  display: block;
}

.title {
  font-size: var(--font);
}

html {
  --font: 16px
}

Partials, Modules

分割するのとそれを読み込むのはセットなので、まとめて紹介します。
postcss-importを使います。

npm i -D postcss-import

postcss.config.jsに設定を追加します。

postcss.config.js
  module.exports = {
    plugins: [
      require('postcss-nested'),
+     require('postcss-import')
    ],
  }

あとはimportするだけです。
Sassだとimportが廃止になってuseに変わりましたが、こちらではimportのままです。

変換前1
/* base.cssというファイル名 */

body {
  font: 100% Helvetica, sans-serif;
  color: #333;
}
変換前2
@import "base.css";

.inverse {
  background-color: #333;
  color: white;
}
変換後
body {
  font: 100% Helvetica, sans-serif;
  color: #333;
}

.inverse {
  background-color: #333;
  color: white;
}

Mixins

postcss-mixinsを使います。

npm i -D postcss-mixins

postcss.config.jsに設定を追加します。

postcss.config.js
  module.exports = {
    plugins: [
      require('postcss-nested'),
      require('postcss-import'),
+     require('postcss-mixins')
    ],
  }

あとはmixinを定義して使うのですが、Sassとは微妙に書き方が違います。
mixinの定義時は@extendではなく@define-mixinで、使うときは@includeではなく@mixinです。
入れ替わっている感じが若干ややこしいですが、致し方ありません。

変換前
@define-mixin icon $network, $color: blue {
  .icon.is-$(network) {
    color: $color;
    @mixin-content;
  }
  .icon.is-$(network):hover {
    color: white;
    background: $color;
  }
}

@mixin icon twitter {
  background: url(twt.png);
}

@mixin icon youtube, red {
  background: url(youtube.png);
}
変換後
.icon.is-twitter {
  color: blue;
  background: url(twt.png);
}

.icon.is-twitter:hover {
  color: white;
  background: blue;
}

.icon.is-youtube {
  color: red;
  background: url(youtube.png);
}

.icon.is-youtube:hover {
  color: white;
  background: red;
}

Extend/Inheritance

postcss-extend-ruleを使います。

npm i -D postcss-extend-rule

postcss.config.jsに設定を追加します。

postcss.config.js
  module.exports = {
    plugins: [
      require('postcss-nested'),
      require('postcss-import'),
      require('postcss-mixins'),
+     require('postcss-extend-rule'),
    ],
  }

あとは通常のSassと同じように書けばOKです。

変換前
%thick-border {
  border: thick dotted red;
}

.serious-modal {
  font-style: normal;
  font-weight: bold;

  @media (max-width: 240px) {
    @extend .modal:hover;
  }
}

.modal {
  @extend %thick-border;
  color: red;
}

.modal:hover:not(:focus) {
  outline: none;
}
変換後
.serious-modal {
  font-style: normal;
  font-weight: bold;
}

@media (max-width: 240px) {
  .serious-modal:not(:focus) {
    outline: none;
  }
}

.modal {
  border: thick dotted red;
  color: red;
}

.modal:hover:not(:focus) {
  outline: none;
}

Operators

純正のcalc()が使えるので、特別な設定は不要です。
なんならSassの除算はmath.div(600px, 960px)といった書式のため、書きづらくなるまであります。

最後に

「最近のCSSは進化してるよなあ」とボンヤリと思っていたのですが、こうして調べてみるとより明確に感じました。
あえてSassを使わずともできることが増えているので、無理に導入する必要もないかもしれません。

今回の記事ではNestingにもPostCSSを使いましたがCSS Nesting Moduleの策定も進んでいるようですし、この記事がいつまで役に立つやら……という気持ちもあります。

しばらくの間、ちょっとした資料としてでも役立てば幸いです。


最後まで読んでくださってありがとうございます!
Twitterでも情報を発信しているので、良かったらフォローお願いします!

Devトークでのお話してくださる方も募集中です!

14
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?