PostCSS Utility Libraryが物凄く使える

最近、PostCSSを使い始めていますが、PostCSS Utility Libraryが物凄く使えるので紹介します。
PostCSSを使うなら必ず入れておきたいパッケージです。

## PostCSS Utility Libraryとは

* [公式サイト](https://ismamz.github.io/postcss-utilities/)
* [パッケージサイト](https://www.npmjs.com/package/postcss-utilities)

公式によると

>postcss-utilities is a PostCSS plugin that have the most used mixins, shortcuts and helpers to use as @util rules in yours stylesheets.

google翻訳すると
「postcss-utilitiesはあなたのスタイルシートで@utilルールとして使うために最もよく使われるmixins、ショートカット、ヘルパーを持つPostCSSプラグインです。」
って翻訳されました。そういうことです。

要するに「@util ～」って書けば便利なものが使えるパッケージですね。
始めて公式サイトのドキュメントを確認した時に超絶便利すぎて椅子から転げ落ちるかと思いました。
小技的なものもあるので勉強にも良いと思います。

## 準備
PostCSSの環境構築については[PostCSSとstylelintの環境構築](http://qiita.com/buchiya4th/items/01b4ad050b7c59b48539)をご参照ください。これ通りにやればpostcss-utilitiesも入っているので記事読みながらやればすぐ使えるようになります。


## @utilを使う
公式ドキュメントでの掲載順がアルファベット順で把握しづらかったので、使いそうな頻度順で紹介します。

## よく使いそうなもの

### Clearfix
clearfix
https://ismamz.github.io/postcss-utilities/docs#clear-fix

```css:postcss
.cfx {
  @util clearfix;
}
```
```css:css
.cfx:after {
  content: '';
  display: block;
  clear: both;
}
```

言わずと知れたfloat解除の技ですね。

### 余白
#### margin
https://ismamz.github.io/postcss-utilities/docs#margin

```css:postcss
.foo {
  @util margin(1em null 20px 3%);
}
```
```css:css
.foo {
  margin-top: 1em;
  margin-bottom: 20px;
  margin-left: 3%;
}
```
なんと指定しない部分は`null`指定で一行で書けてしまいます。こういうのが欲しかった。単位指定の縛りもなく、上下のみ指定なら「10px null」と個数も通常のCSSと同じように書けるので便利です。

#### padding
https://ismamz.github.io/postcss-utilities/docs#padding

```css:postcss
.foo {
  @util padding(1em null 20px 3%);
}
```
```css:css
.foo {
  padding-top: 1em;
  padding-bottom: 20px;
  padding-left: 3%;
}
```

こちらはpadding版ですね。CSSの仕様に入れて欲しいレベルです。


### リスト
### reset-list
https://ismamz.github.io/postcss-utilities/docs#reset-list

```css:postcss
ul {
  @util reset-list;
  background-color: #fff;
}
```
```css:css
ul {
  background-color: #fff;
  margin-top: 0;
  margin-bottom: 0;
  padding-left: 0;
}

li {
  list-style: none;
}
```

リストの初期スタイルをリセットしてくれるものです。
横並びにしたいリストの時に活躍してくれます。


### 位置、大きさ
#### position
https://ismamz.github.io/postcss-utilities/docs#position

```css:postcss
.foo {
  @util position(absolute, 0 null null 10em);
}
```
```css:css
.foo {
  top: 0;
  left: 10em;
  position: absolute;
}
```

ポジション指定と位置指定を一行で書けます。位置を指定しないものはmarignと同じくnull指定です。値をmarginと同じく2つ・3つにできますが、基本的に「左上」や「右下」などの指定が多いのではないでしょうか。そうなるとnull指定で4つ書いていたほうがわかりやすそうです。

#### size
https://ismamz.github.io/postcss-utilities/docs#size

```css:postcss
a {
  @util size(2em);
}

b {
  @util size(auto, 10em);
}

c {
  @util size(200px, 100px);
}
```
```css:css
a {
  width: 2em;
  height: 2em;
}

b {
  width: auto;
  height: 10em;
}

c {
  width: 200px;
  height: 100px;
}
```

横幅と高さを同時に指定したい時に便利そうです。固定させてしまいたい時やautoも使用する場合などに使えそうです。

center
https://ismamz.github.io/postcss-utilities/docs#center

```css:postcss
.child {
  @util center;
}
```
```css:css
.child {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
```

コンテンツを中心に配置する指定を一行で書けます。
オプション指定で`{ centerMethod: 'flexbox' }`を追加すればFlexboxもいけるみたいで試したんですが、やりかたがよくなかったのかうまく反映されませんでした。また機会をみて挑戦してみようと思います。

center-block
https://ismamz.github.io/postcss-utilities/docs#center-block

```css:postcss
.center {
  @util center-block;
}
```
```css:css
.center {
  display: block;
  margin-left: auto;
  margin-right: auto;
}
```

コンテンツの横位置を中央に寄せたい時に使えます。`width`指定も必要なのでお忘れなく。

## たまに使いそうなもの

### 図形
#### circle
https://ismamz.github.io/postcss-utilities/docs#circle

```css:postcss
.circle {
  @util circle(200px, #268BD2);
}
```
```css:css
.circle {
  height: 200px;
  width: 200px;
  border-radius: 50%;
  background-color: #268BD2;
}
```

円形を一行で書けるものです。プロフィール写真とかの画像を丸く表示させたい時とかのコンテンツを円形にする時にさっと一行で書けるのは良いですね。
※ドキュメント側の`color`は試してみたら`background-color`でした。

#### triangle
https://ismamz.github.io/postcss-utilities/docs#triangle

```css:postcss
.triangle-up {
  @util triangle(20px, blue, up);
}
```
```css:css
.triangle-up {
  display: inline-block;
  height: 0;
  width: 0;
  border-left: 20px solid transparent;
  border-right: 20px solid transparent;
  border-bottom: 20px solid blue;
}
```

三角形を一行で書けます。スマホのリンク一覧の右側に入れたりアコーディオンの開閉の装飾として使えそうです。
ただし、ドキュメントを見てもらえばわかる通りこのまま使うより微調整したほうが良さそうです。例えば正三角形にする、とかですね。
以下のように`transform: scaleX(1.65);`と指定すれば汎用的に使えそうです。
※1.65は目分量で指定したので適宜調整してください。

```css:postcss
.itemList {
  & li {
    &:after {
      /* ...省略... */
      @util triangle(10px, blue, right);
      transform: scaleX(1.65);
    }
  }
}
```


### テキスト
#### truncate
https://ismamz.github.io/postcss-utilities/docs#truncate

```css:postcss
.truncate {
  @util truncate;
}
```
```css:css
.truncate {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
```

テキストを切り捨てて、オーバーフローを表す省略記号を追加してくれます。
複数行もいけるみたいですが、各ブラウザ・デバイスで確認したほうが良いかもしれません。

#### text-stroke
https://ismamz.github.io/postcss-utilities/docs#text-stroke

```css:postcss
.stroke {
  @util text-stroke(1px, #d50200);
}
```
```css:css
.stroke {
  text-shadow: -1px -1px 0 #d50200,
               -1px 0 0 #d50200,
               -1px 1px 0 #d50200,
               0 -1px 0 #d50200,
               0 0 0 #d50200,
               0 1px 0 #d50200,
               1px -1px 0 #d50200,
               1px 0 0 #d50200,
               1px 1px 0 #d50200;
}
```

テキストストロークを一行で書けます。文字のアウトラインに色をつけるアレですね。


#### word-wrap
https://ismamz.github.io/postcss-utilities/docs#word-wrap

```css:postcss
.foo {
  @util word-wrap;
}

.bar {
  @util word-wrap(normal);
}
```
```css:css
.foo {
  overflow-wrap: break-word;
  word-break: break-all;
  word-wrap: break-word;
}

.bar {
  overflow-wrap: normal;
  word-break: normal;
  word-wrap: normal;
}
```

テキストの折り返しを調整したい時に良さそうです。
この辺りは結構ややこしいので参考記事を載せておきます。

参考：[word-breakとword-wrapはややこしい](https://w3g.jp/blog/confusing_word-break_word-wrap)


#### reset-text

```css:postcss
.foo {
  @util reset-text;
}
```
```css:css
.foo {
  font-family: sans-serif;
  font-style: normal;
  font-weight: normal;
  letter-spacing: normal;
  line-break: auto;
  line-height: 1.5;
  text-align: left;
  text-align: start;
  text-decoration: none;
  text-shadow: none;
  text-transform: none;
  white-space: normal;
  word-break: normal;
  word-spacing: normal;
  word-wrap: normal;
}
```

テキストの既定のスタイルを削除したい時用です。
これを使う時はあまり良くない時な気がします。「どうしてもここだけは一切のしがらみをなくしたい！」っていう時でしょうか。そういう時は大体破綻の道を進んでいる可能性が高いので設計を改めて確認してみてください。


### アスペクト比
aspect-ratio
https://ismamz.github.io/postcss-utilities/docs#aspect-ratio

```css:postcss
.box-16-9 {
  @util aspect-ratio(16:9);
}
```
```css:css
.box-16-9 {
  position: relative;
  display: block;
  height: 0;
  padding: 0;
  overflow: hidden;
  padding-bottom: 56.25%;
}
```

Youtubeなどの動画を入れるのに良さそうです。こちらも参考記事を載せておきます。

参考：[Youtube (iframe) をレスポンシブ対応に](http://www.webdesignleaves.com/wp/htmlcss/639/)


### 非表示
#### hide-visually
https://ismamz.github.io/postcss-utilities/docs#hide-visually

```css:postcss
.hide-visually {
  @util hide-visually;
}
```
```css:css
.hide-visually {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  border: 0;
}
```

スクリーンリーダーにのみコンテンツを表示します。
用途としては、広告タグだと思います。下の方に仕込むことが多いですがフッターの下に謎の余白があって「なんじゃこりゃあ！！」ってなってよくよく調べたら広告タグのimgが表示されてましたてへぺろみたいなことがあります。imgはインライン要素なので1x1でも高さはfont-sizeやline-heightなどが効くので気を付けたいところです。


### 境界線
borderの個別指定をラクにしてくれるものたちです。borderを駆使するようなページでは使えるかもしれないです。頻度は少なそうなのでまとめて載せます。

```css:postcss
/* ボックスの特定の辺でボーダー幅をターゲットにする簡単な方法 */
.foo {
  @util border-width(1em null 20px 3%);
}
/* ボックスの特定の辺でボーダースタイルをターゲットにする簡単な方法 */
.foo {
  @util border-style(solid null dotted dashed);
}
/* ボックスの特定の辺で境界線の色をターゲットにする簡単な方法 */
.foo {
  @util border-color(#fff null #000 red);
}
/* 角丸をまとめて指定する方法 */
.foo {
  @util border-top-radius(1px);
}
.foo {
  @util border-right-radius(2px);
}
.foo {
  @util border-bottom-radius(3px);
}
.foo {
  @util border-left-radius(4px);
}
```
```css:css
/* @util border-width(1em null 20px 3%); */
.foo {
  border-top-width: 1em;
  border-bottom-width: 20px;
  border-left-width: 3%;
}

/* @util border-style(solid null dotted dashed); */
.foo {
  border-top-style: solid;
  border-bottom-style: dotted;
  border-left-style: dashed;
}

/* @util border-color(#fff null #000 red); */
.foo {
  border-top-color: #fff;
  border-bottom-color: #000;
  border-left-color: red;
}

/* @util border-top-radius(1px); */
.foo {
  border-top-left-radius: 1px;
  border-top-right-radius: 1px;
}
/* @util border-right-radius(2px); */
.foo {
  border-bottom-right-radius: 2px;
  border-top-right-radius: 2px;
}
/* @util border-bottom-radius(3px); */
.foo {
  border-bottom-left-radius: 3px;
  border-bottom-right-radius: 3px;
}
/* @util border-left-radius(4px); */
.foo {
  border-bottom-left-radius: 4px;
  border-top-left-radius: 4px;
}
```


### ブラウザ・デバイス対応
#### no-hover
https://ismamz.github.io/postcss-utilities/docs#no-hover

```css:postcss
.box {
  background-color: #000;
}

@util no-hover {
  .box {
    background-color: #666;
  }
}
```
```css:css
.box {
  background-color: #000;
}

.no-hover .box {
  background-color: #666;
}
```

ホバー機能がないデバイスに対応させるためのものです。デスクトップとスマホ・タブレットで出し分けたい場合を想定していると思います。具体的な使うシーンは想像できないですが、たぶん使うシーンがあるんでしょう。
※ブラウザまたはデバイスがホバーをサポートしていない場合は、htmlタグに.no-hoverクラスを追加する必要があります。


#### no-js
https://ismamz.github.io/postcss-utilities/docs#no-js

```css:postcss
.box {
  color: #666;
}

@util no-js {
  .box {
    color: #000;
  }
}
```
```css:css
.box {
  color: #666;
}

.no-js .box {
  color: #000;
}
```

JavaScriptをサポートしていない場合の出し分けですね。
Modernizrとセットで使うと良いでしょう。
※ブラウザまたはデバイスがJavaScriptをサポートしていない場合は、htmlタグに.no-jsクラスを追加する必要があります。

#### hd breakpoint
https://ismamz.github.io/postcss-utilities/docs#hd-breakpoint

```css:postcss
@util hd {
  .foo {
    float: right;
  }
}

@util hd(192dpi) {
  .bar {
    float: left;
  }
}
```
```css:css
@media print,
       (min-resolution: 1.25dppx),
       (min-resolution: 120dpi) {
  .bar {
    border: 0;
  }
}

@media print,
       (min-resolution: 2dppx),
       (min-resolution: 192dpi) {
  .bar {
    float: left;
  }
}
```

高解像度デバイスのスタイル調整です。メディアクエリをあまり使いすぎたくはないですが、のっぴきならない理由がある場合は使うと良いと思います。




### 固定フッター
#### sticky-footer
https://ismamz.github.io/postcss-utilities/docs#sticky-footer

```css:postcss
footer {
  @util sticky-footer(100px);
}
```
```css:css
body {
  margin-bottom: 100px;
}

footer {
  position: absolute;
  left: 0;
  bottom: 0;
  height: 100px;
  width: 100%;
}
```

コンテンツが不足している場合でも、フッターがビューポートの下部に維持されるようにします。
ただし、footerの高さを決めてしまうので拡張性が気になるところです。

## バッドプラクティス
#### hr
https://ismamz.github.io/postcss-utilities/docs#horizontal-rule

```css:postcss
hr {
  @util hr(#000, 20px);
}
```
```css:css
hr {
  height: 1px;
  border: 0;
  border-top: 1px solid #000;
  margin: 20px 0;
  display: block;
}
```

水平線の要素をつくるものです。hr要素は意味があるので、装飾のために使う場合にこちらを使う想定だと思います。しかし`height: 1px;`となるので中身は表示されないです。装飾のためだけの要素はSEO的にあまり好ましくないので、こちらをなるべく使わないように他でスタイルを設定したほうが望ましいでしょう。

#### text-hide
https://ismamz.github.io/postcss-utilities/docs#text-hide

```css:postcss
.text-hide {
  @util text-hide;
}
```
```css:css
.text-hide {
  overflow: hidden;
  text-indent: 101%;
  white-space: nowrap;
}
```

画像置換のためのセットです。こちらもSEO的に好ましくないので積極的に使うのは避けたほうが良いでしょう。

## さいごに
PostCSSは便利なものがあって良いですね。Sassよりも便利です。良いものは積極的に取り入れていきたいですね。
学習コストは若干気になるものの、フロントエンドエンジニアであればいずれ覚えるべき小技もあるので、これを機にさわっておくと良いと思います。