webデザイナーによるCSS（DartSass/BEM）学び直し

紙ものデザイナーからwebデザイナーになったMariettiです。
社内勉強会でCSS学び直しの機会がありましたので勉強会+αの内容をこちらにまとめようと思います！
CSSの学び直しと言いつつDartSassがメインの内容となっています。
おまけとして最近知ってから多様しているものを紹介します！


## Sassとは
Sassとは、CSSの拡張メタ言語の中で現状最もポピュラーなものになります。
メタ言語とはある言語に別のルールを定義するために使われる言語のことで、拡張言語と呼ばれることもあります。
CSSをより効率的に書くことができます。

**関数**や**変数**を利用することができ、ヒューマンエラーの防止や効率化が望めます。

### Sassのメリット１：ネスト構造で書くことができる
一番の強みはここになるかと思います。
昨今CSSでもネスト構造を使うことはできますが、予期せぬ表示崩れ[^※]につながることもあります
ネスト構造でCSSを書くことによって、セクションごとにある程度の塊となるので管理が楽になります。
また、管理同様に保守運用の面でもコードが探しやすく扱いやすいです。

### Sassのメリット2：変数が利用できる
こちらもかなりの強み。
よく使うカラーやコンテナ幅などを変数にしておくことで、効率的な記述ができるようになります。
サイトの色々な場所に配置されているカラーや数値も、変数の定義元を編集することにより１発で全ての配置先の数値を変更することができます。

### Sassのメリット3：ミックスイン（mixin）を利用できる
ミックスインは、定義したCSSのスタイルを別の部分でも使えるようにする機能です。
例えば`btn-1`と`btn-2`で設定したCSSが複数あり、色意外が全て同一だったとします。
その場合`@mixin btn`として同一の設定を書き、`@include btn`として出力します。
そうすることで共通のコードの記述量を減らし、効率的なコーディング作業ができます。

### Sassのメリット4：ファイル分割して管理しやすくできる
例えばファイルを`header.scss`,`footer.scss`,`base.scss`,`btn.scss`...のように分割し、
ディレクトリに分けながら整理することで、管理がとても楽になります！
この方法を使う際は`@use`を使ってまとめるのが良いかと思います！
詳しくは以前書いた下記記事を参照ください。
https://qiita.com/marietti/items/7f317b88a7255dbfda6e


### Sassのメリット5：エラーが表示される
Sassでは、文法を間違えた場合はエラーが出ます。
何がメリットかと思う方も居るかもしれませんが、エラーが出ることにより**どこが間違った箇所なのかすぐわかる**というところです。
通常のCSSで書いた場合では間違った記述があっても、どこが間違えているかなど自力で探さねばわかりません。ですのでエラーが出るということはとても便利な点なのです。


[^※]:実務にて通常のCSSでネスト構造を用いて書いたところ、iPhoneSEやminiなど画面の小さな端末で表示崩れが起きてしまいました。原因が全然わからなくて肝を冷やしました。。

## Sassのコンパイル
Sass（拡張子としては`.scss`）はそのままhtmlで読み込んでも、ブラウザに認識されません。
なのでコンパイルをしてcssを出力、その出力されたcssをhtmlで読み込む必要があります。
方法はいくつかありますが、簡単にできるものを紹介します。

### Live Sass Compilerでコンパイル
Live Sass CompilerというVSCodeの拡張機能を使ってコンパイルを行う方法です。
https://xn--marketplace-zb4j.visualstudio.com/items?itemName=glenn2223.live-sass
使い方としては、
- インストールする
- VSCodeの画面右下にある、「Watch Sass」というボタンをクリック
![アートボード 2111-100.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3081960/e3c52f2d-7ab6-a9b4-c791-b1e98a548bc0.jpeg)
- ボタンが「Watching...」という状態になったらSass（scss）の監視が行われ、コンパイルが走ります
![アートボード 2-100.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3081960/8c2572fb-10f2-1dca-f510-ddf47dbd8bac.jpeg)
- この状態になることで、リアルタイムで編集したscssの内容がコンパイル先のcssに反映されます。

大まかな流れはこのようになります。
また、cssのコンパイル先などの細かい設定をしたい場合は**setting.json**に設定を追記します。
必要であれば下記の公式ドキュメントや、調べて記述すればOKです！
https://github.com/ritwickdey/vscode-live-sass-compiler/blob/master/docs/settings.md
この方法が一番とっつきやすく導入が簡単かと個人的には思います！

### sassコマンドでコンパイル
お次はターミナルでsassコマンドを使ってコンパイルする方法です。
基本的なコマンドは下記になります！
```shell-session
$ sass hoge foo
（hoge→sassのファイルまでのパス、foo→cssを出力したいファイルパス）
```
オプションとして頻出しそうなものがこちら
- `--watch`
sassファイルを監視して、自動でコンパイルしてくれる
- `--no-souse-map`
オプションなしだと生成されてしまうソースマップを生成しなくなる
- `--style compressed`
圧縮した状態でコンパイルされる（cssファイルからインデントやコメント、改行などを全て削除し、１行にまとめることができる）

こちらも公式ドキュメントを参照すると詳しくわかります！
https://sass-lang.com/documentation/cli/dart-sass/


GUIが大好きな私は拡張機能でのコンパイルばかりしていますが、
CLIの記事を書いたからにはたまにはsassコマンドも導入したいところ。。
https://qiita.com/marietti/items/ab4cb8835b1b3a733502

## 分割したファイルを読み込む方法
かつてSassでは分割したファイルの読み込みに`@import`を使っていましたが、以下の理由は廃止予定で`@use`を使うことになりました。
- Sass使っていた`@import`が、CSSでもアットルールとして使われるようになった
- $で定義した名前が被ってしまうことがある

### `@use`でできること

#### 別のscssの読み込み
例えば今書いているscssに、別のscssを読み込んで関数を使用することができます。
```scss:hoge
@use "foo" as *;
```
こう書けば、今書いている`hoge.scss`内で同ディレクトリ内にある`foo.scss`内のすべての要素を使うことができます。
また、`@use`で読み込んだファイル（foo.scss）の`$fuga`で定義されたものは、**hoge.$fuga**で呼び出すこともできます。

#### メディアクエリの呼び出し
こうすればメディアクエリも呼び出せます
```scss:foo.scss（定義するscss）
//map型(key: value)でブレイクポイントを定義する。
$breakpoints: (
  "sp": "screen and (max-width: 800px)",
  "tb": "screen and (max-width: 900px)",
  "pc": "screen and (min-width: 901px)",
);

@mixin breakPoint($key) {
  @media #{map-get($breakpoints, $key)} {
    @content;
  }
}
```
```scss:hoge.scss（呼び出すscss）
@use 'foo';
  @include var.breakPoint("sp") {
    ...
  }
  @include var.breakPoint("tb") {
    ...
  }
  @include var.breakPoint("pc") {
    ...
  }
```
このように記述することで、効率的にブレイクポイントの設定をすることができます！

再びの登場となってしまいますが、`@use`の分割ファイルの読み込みでの使い方はディレクトリ構成を含め以前記事化しましたのでこちらも参照いただけるとありがたいです！
https://qiita.com/marietti/items/7f317b88a7255dbfda6e

### `@foward`でできること
`@foward`では、`@use`でできない2段階でのscssを読み込みができます。
例えば、
```scss:base.scss
$theme-color: #ffd700;
```
```scss:foo.scss
@forward "base"; 
```
```scss:hoge.scss
@use 'foo';
 
.hoge {
  color: foo.$theme-color;
}
```
このように書くことで、コンパイルし出力されるファイルが以下のようになります
```scss:hoge.scss
.hoge {
  color: #ffd700;
}
```
`@forward`は、`@use`と違い要素を参照するのではなく**転送することができます**。
`@forward`と`@use`を使い分けて、管理しやすいscssにできるといいなと思います。


## CSSの命名規則（BEM）
CSSには、BEM（Block Element Modifier）という命名規則があり、数ある命名規則の中でもかなり厳格なルールです。
巨大化してもサポートしやすく、コードの再利用がしやすいという利点があります。
class名は命名規則に倣って命名しましょう！
公式ドキュメントはこちら
https://en.bem.info/methodology/quick-start/

基本的な記法は下記になります。
```
.block__element-—modifier
```
### Block（ブロック）
Blockとは、**どのページでも使い回すことができるパーツ**です。
menuやbuttonなど、それが何であるかわかる名前にします。
英単語が2つ以上の場合はハイフンケースで繋げて書きます。


### Element（要素）
Elementとは、**Blockを構成する要素で、Blockの外では独立して使用できないもの**です。
Blockの名前を継承して`__（アンダースコア2つ）`を書いた後にElementの名前をつけます。
CSSを記述する際は詳細度を均一にし、特定のコンテキストに依存しないような記述とします。
例えば、`.block .block__element`とclass指定するのではなく、`.block__element`としてレイアウトが変わっても柔軟に対応できるようにします。
またElementは常にBlockの一部であり、独立して存在することはありません。

### Modifier（モディファイア）
Modifierとは装飾子という意味で、**BlockやElementの見た目、状態、振る舞いを定義するもの**です。
BlockやElementの名前を継承し、`--（ハイフン2つ）`を書いた後にModifierの名前をつけます。
大まかに3種類あります。
- **見た目** - どんなサイズか？どんな色か？　ex.)small,coution
- **状態** - 他のBlockまたはElementと比べて何が違うか？　ex.)active
- **振る舞い** - それがどのように振る舞う（動作する）か？　ex.)bottom-right

また、Modifierは一つのBlockやElementに対して複数使えます。

この３つの要素に分けて考え、保守管理しやすいCSSを書きたいところですね。
classの指定はどうしても人によってなんとなく個性がでがちなところなのでそちらも少し気をつけていき、常に**誰が見てもわかりやすいコード**というのを目指していきたいです！
余談ですが、会社での仕事は**いつ私が消えても回るようになっている**ことが理想だと思っているので、どのデータも誰が見ようと編集しやすくなっているということをモットーにデータ作成しています。

## おまけ：最近学んだCSSあれこれ
### 理論上絶対に崩れない角丸
```css
border-radius: calc(1px / 0);
```
calcを使うことで、理論上絶対に崩れない角丸を実装することができます。
99pxを使うよりはスマートそう？なので私は最近導入しています！
buttonとかで実装するheightの50%角丸に使えます。

### メディアクエリ
```css
@media (800px <= width < 1200px)
```
私が知らなかっただけかもしれませんが、従来のように`@media screen and(max-width: 800px)`のようにせずとも不等号で表現できるという知見を得てからはこの記法を使っています。
`max-width`や`min-width`よりも直感的にわかりやすいかと思います。
MDNの範囲構文というところでも紹介されています！
https://developer.mozilla.org/ja/docs/Learn/CSS/CSS_layout/Media_queries

### CSSの優先度
CSSの優先度は、詳細度の点数が設定されておりこの点数が高いほど優先して反映されます。
| セレクタの指定 | 詳細度（点数） | 例 |
|:-:|:-:|:-:|
| ユニバーサルセレクタ  | 0 | *  |
|  要素名（タグ） |  1 |  pタグやliタグなど |
|  擬似要素 | 1  | :before,:afterなど  |
|  属性セレクタ | 10  | a[href="hoge"]  |
|  classセレクタ | 10  |  .header |
|  IDセレクタ | 100  | #header  |
|  タグのStyle属性で指定 | 1,000  | style="color: #FFF"  |

どうしてもスタイルが適応されない際に使う`!important`ですが、これは最終奥義のようなものなのでどうしてもという時以外は使わないようにしましょう...！


### おわりに
今回の記事化で、学び直し+αで`@use`と`@forward`の使い方をより詳しく知ることができました！
コーディングしていると、意外と知ったような気持ちになり「ここはこういうものだ、こういう使い方をするものだ」という認識が頭の中で出来上がってしまい、ついいつもと同じように書いてしまうように感じます。
常にアップデートし続けて、ケースに適した書き方をしていきたいです！