[Rails6][webpacker]CSS の擬似要素::before, ::after で Font Awesome を使うと □(四角) が表示される場合の対処法

# はじめに

Font Awesome 便利ですよね。インストールして HTML に記述するだけで簡単にアイコンを Web サイトで使えるようになります。
例えばこのように HTML を記述すれば

```html
<i class="fas fa-star"></i>
キラキラ
<i class="fas fa-star"></i>
```

こんな風に表示されます。

<img width="118" alt="スクリーンショット 2019-10-30 14.50.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449905/0ceee43c-4d5b-785e-c85e-cca0f560fc91.png">

このアイコンは CSS の擬似要素(::before, ::after)でも使用できるのですが、この時にアイコンが □(四角)で表示されてしまいました。今回はその対処法を記事にします。

# 環境

- ruby 2.6.3
- rails 6.0.0
- webpacker 4.0.7
- yarn 1.17.3

# Font Awesome の導入

まずは Font Awesome を導入しましょう。

## yarn でインストール

[Font Awesome の公式](https://fontawesome.com/how-to-use/on-the-web/setup/using-package-managers)に`yarn`を使用したインストールの方法が記載されているのでこちらを参考にします。

```bash
# @fo「n」tawesome ではなく@fo「r」tawesome なので注意！！！
$ yarn add @fortawesome/fontawesome-free
```

成功すれば`node_modules`フォルダに`@fortawesome/fontawesome-free`フォルダが生成されています。この中に`yarn`でインストールした Font Awesome のファイルが格納されています。

<img width="258" alt="スクリーンショット 2019-10-30 16.11.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449905/81588776-1b26-cea4-2a4d-00381939213a.png">

## エントリーファイルの記述

次に Web ブラウザが読み込む js ファイル(エントリーファイル)の記述をしていきます。
`app/javascripts/pack/application.js`に以下の記述を追加します。

```app/javascripts/pack/application.js
import "@fortawesome/fontawesome-free/js/all";
import "../src/application";
```

## application.scss の作成

先ほど

```js
import "../src/application";
```

を記述したので、`app/javascripts/src/application.scss`を作成します。

```bash
$ mkdir app/javascripts/src
$ touch app/javascripts/src/application.scss
```

`app/javascripts/src/application.scss`に以下のコードを記述します。

```app/javascripts/src/application.scss
@import "~@fortawesome/fontawesome-free/scss/fontawesome";
```

## HTML の<head>から記述した js, scss ファイルの呼び出し

`app/views/layouts/application.erb.html`の

```app/views/layouts/application.erb.html
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> -->
```

というコードを

```app/views/layouts/application.erb.html
<%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> -->
```

に変更します。
以上で導入は完了です。あとは[Font Awesome の公式サイト](https://fontawesome.com/icons?d=gallery)から好きなアイコンを検索して HTML を記述していけば使えます。

# 問題

この方法で冒頭で紹介したような` i タグ`での使用はできるのですが、CSS の擬似要素で使用する際に □(四角)が表示されてしまいます。

例えば以下のような`HTML`と`scss`を記述した場合、

```html
<span class="kirakira">キラキラ</span>
```

```application.scss
// class="kirakira"のテキストの最初と最後に★が追加されるコード
// application.scssの一番下に記述

.kirakira {
  &::before {
    font-family: "Font Awesome 5 Free";
    font-weight: 900;
    content: "\f005";
    color: red;
  }

  &::after {
    font-family: "Font Awesome 5 Free";
    font-weight: 900;
    content: "\f005";
    color: blue;
  }
}
```

このように表示されてしまいました。

<img width="119" alt="スクリーンショット 2019-10-30 16.13.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449905/232027ac-1b06-9da5-bbf1-c01bd370a67d.png">

`content`の Unicode を間違えたのか、`font-weight`の値を間違えたのか、色々調べたのですが…

# 原因

[application.scss の作成]の項目で記述した

```app/javascripts/src/application.scss
@import "~@fortawesome/fontawesome-free/scss/fontawesome";
```

というコードは`node_modules`フォルダ内の`@fortawesome/fontawesome-free/scss/fontawesome`ファイルを参照しています。

<img width="249" alt="スクリーンショット 2019-10-30 16.15.04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449905/dae73e81-c069-267a-af7f-78c0447d6daa.png">

[ドキュメント](https://fontawesome.com/how-to-use/on-the-web/using-with/sass)ではメインのファイルであるというような紹介がされていますが、内部では同じファイル内の `scss` ファイルを色々と`@import`しています。

```node_modules/@fortawesome/fontawesome-free/scss/fontawesome.scss
/*!
 * Font Awesome Free 5.10.2 by @fontawesome - https://fontawesome.com
 * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
 */
@import 'variables';
@import 'mixins';
@import 'core';
@import 'larger';
@import 'fixed-width';
@import 'list';
@import 'bordered-pulled';
@import 'animated';
@import 'rotated-flipped';
@import 'stacked';
@import 'icons';
@import 'screen-reader';
```

上の画像とこのコードを見比べてみるとわかるのですが、

- `brands.scss`
- `regular.scss`
- `solid.scss`

が`@import`されていません。(`v4-shims.scss`も`@import`されていませんが、ここでは割愛させていただきます。)
これらのファイルは、内部で`@font-face`を使って`Font Awesome 5 Free`または`Font Awesome 5 Brands`という font-family を定義していました。

```regular.scss
/*!
 * Font Awesome Free 5.10.2 by @fontawesome - https://fontawesome.com
 * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
 */
@import 'variables';

@font-face {
  font-family: 'Font Awesome 5 Free';
  font-style: normal;
  font-weight: 400;
  font-display: $fa-font-display;
  src: url('#{$fa-font-path}/fa-regular-400.eot');
  src: url('#{$fa-font-path}/fa-regular-400.eot?#iefix') format('embedded-opentype'),
  url('#{$fa-font-path}/fa-regular-400.woff2') format('woff2'),
  url('#{$fa-font-path}/fa-regular-400.woff') format('woff'),
  url('#{$fa-font-path}/fa-regular-400.ttf') format('truetype'),
  url('#{$fa-font-path}/fa-regular-400.svg#fontawesome') format('svg');
}

.far {
  font-family: 'Font Awesome 5 Free';
  font-weight: 400;
}
```

これを`@import`すれば使えるのでは？

# 対処法

という訳で`application.scss`を以下のように記述します。

```application.scss
@import "~@fortawesome/fontawesome-free/scss/fontawesome";
// 各アイコンのスタイルの参照
@import "~@fortawesome/fontawesome-free/scss/regular";
@import "~@fortawesome/fontawesome-free/scss/solid";
@import "~@fortawesome/fontawesome-free/scss/brands";

.kirakira {
  // …中略
}
```

すると以下のようなエラーメッセージが出てコンパイルエラーが出ました。

```
Module not found: Error: Can't resolve '../webfonts/fa-brands-400.eot'
```

`../webfonts/fa-brands-400.eot`なんて無いよ！と怒られたので`regular.scss`のコードをもう一度よく見てみます。

```regular.scss
/*!
 * Font Awesome Free 5.10.2 by @fontawesome - https://fontawesome.com
 * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
 */
@import 'variables';

@font-face {
  font-family: 'Font Awesome 5 Free';
  font-style: normal;
  font-weight: 400;
  font-display: $fa-font-display;
  src: url('#{$fa-font-path}/fa-regular-400.eot');
  src: url('#{$fa-font-path}/fa-regular-400.eot?#iefix') format('embedded-opentype'),
  url('#{$fa-font-path}/fa-regular-400.woff2') format('woff2'),
  url('#{$fa-font-path}/fa-regular-400.woff') format('woff'),
  url('#{$fa-font-path}/fa-regular-400.ttf') format('truetype'),
  url('#{$fa-font-path}/fa-regular-400.svg#fontawesome') format('svg');
}

.far {
  font-family: 'Font Awesome 5 Free';
  font-weight: 400;
}
```

色々書かれていますが、`@font-face`で指定されている url に`$fa-font-path`という変数が使用されています。
この変数の定義元は同じフォルダ内の`_variables.scss`にありました。

```_variables.scss
$fa-font-path:         "../webfonts" !default;
```

この値が`../webfonts`なので`../webfonts/fa-brands-400.eot`が url として指定されたようです。
この値を上書きすれば正しく参照されそうです！

```application.scss
@import "~@fortawesome/fontawesome-free/scss/fontawesome";
// @face-fontがnode_modulesフォルダにインストールされたfontawesomeのwebfontを参照するように値を変更
$fa-font-path: "~@fortawesome/fontawesome-free/webfonts";

@import "~@fortawesome/fontawesome-free/scss/regular";
@import "~@fortawesome/fontawesome-free/scss/solid";
@import "~@fortawesome/fontawesome-free/scss/brands";

.kirakira {
  // …中略
}
```

結果はこちらです。

<img width="119" alt="スクリーンショット 2019-10-30 16.12.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449905/d4deabfc-9b31-378e-64da-294cc72778b7.png">

うまく表示されました！

# まとめ

`Font Awesome 5 Free`を定義しているファイルを参照していないために起きたエラーでした。
今回調べても中々同じような対処をしている記事をみつけられなかったので記事にしました。一人でも助けになれば幸いです。
しかしまあ手軽で便利ですね〜。ホント(font) Awesome。

何か直すべき点、間違った記述があればコメント等で指摘していただければと思います。