CodePen で学ぶ SCSS 実践

## はじめに

本記事は社内勉強会資料として作成しています

前回記事の続編で SCSS を CodePen で実践します

https://qiita.com/RyoWakabayashi/items/fd0d6813e4b0f3763d99

## CodePen

Web の学習にピッタリのサービス

https://codepen.io/

![スクリーンショット 2022-07-15 17.10.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/3d3acde4-59d0-c35e-8f07-b319fa839700.png)

SCSS も使える

![スクリーンショット 2022-07-15 17.13.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/5b1103fa-0559-fe16-24ff-34d67c90a0df.png)

## SCSS 基礎

### メタ言語

ある言語を記述するための言語

### Sass

Sass = Syntactically Awesome StyleSheet = 素晴らしい文法のスタイルシート

階層構造、四則演算、変数、関数が使える

Sass をビルドすることで CSS が生成される

Sass を直接ブラウザが読むことはできない

Sass の方が記述しやすく、直感的で機能的になっている

### SASS

Sass = 言語

SASS = 記法

拡張子は `.sass`

`{}` や `;` を書かない

```sass
.main-body
  color: red
  font-size: 1em
```

### SCSS

SCSS = Sassy CSS = Sass 的 CSS

Sass を CSS と同じ記法で記述できる

拡張子は `.scss`

`{}` や `;` を書く

```scss
.main-body {
  color: red;
  font-size: 1em;
}
```

SCSS　を CSS に変換できるサイト

https://www.sassmeister.com/

## 階層構造

<p class="codepen" data-height="825" data-default-tab="css,result" data-slug-hash="ExErYVb" data-user="ryowakabayashi" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/ryowakabayashi/pen/ExErYVb">
  SCSS Cascade</a> by Ryo Wakabayashi (<a href="https://codepen.io/ryowakabayashi">@ryowakabayashi</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

`{}` の内側にネストすることで子孫要素（CSS でのスペース区切り）を表す

__SCSS__
```scss
.a {
  .b {
    color: red;
  }

  .c {
    color: blue;
  }
}
```

__CSS__
```css
.a .b {
  color: red;
}

.a .c {
  color: blue;
}
```

ネスト時、先頭に `&` を付けると、CSS でくっついているのと同じになる

__SCSS__
```scss
.a {
  &.b {
    color: red;
  }

  &:hover {
    color: blue;
  }

  &::after {
    color: green;
  }
}
```

__CSS__
```css
.a.b {
  color: red;
}

.a:hover {
  color: red;
}

.a::after {
  color: red;
}
```

メディアクエリ(`@media`)をネストの中に入れることもできる

__SCSS__
```scss
.a {
  color: red;

  @media print {
    display: none;
  }
}
```

__CSS__
```css
.a {
  color: red;
}

@media print {
  .a {
    display: none;
  }
}
```

## 変数

<p class="codepen" data-height="780" data-default-tab="css,result" data-slug-hash="rNdoXbj" data-user="ryowakabayashi" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/ryowakabayashi/pen/rNdoXbj">
  SCSS Variables</a> by Ryo Wakabayashi (<a href="https://codepen.io/ryowakabayashi">@ryowakabayashi</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

`$変数名: 値;` で変数を定義する

`$変数名` で変数を参照する

`#{$変数名}` で変数を展開する

__SCSS__
```scss
$color-main: #f80;
$unit-spacing: 8px;

.a {
  color: $color-main;
  padding: $unit-spacing;
}

.b {
  color: $color-main;
  padding: 2 * $unit-spacing;
}
```

__CSS__
```css
.a {
  color: #f80;
  padding: 8px;
}

.b {
  color: #f80;
  padding: 16px;
}
```

## 継承（extend）

<p class="codepen" data-height="480" data-default-tab="css,result" data-slug-hash="XWEOrMz" data-user="ryowakabayashi" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/ryowakabayashi/pen/XWEOrMz">
  SCSS Extend</a> by Ryo Wakabayashi (<a href="https://codepen.io/ryowakabayashi">@ryowakabayashi</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

`%プレースホルダ名` で、プレースホルダを定義する

`@extend %プレースホルダ名` でプレースホルダのスタイルを継承する

ビルドすると、各 Selector の or になる

__SCSS__
```scss
%x {
  font-size: 24px;
  background-color: black;
}

.a {
  @extend %x;
  color: red;
}

.b {
  @extend %x;
  color: blue;
}
```

__CSS__
```css
.a,
.b {
  font-size: 24px;
  background-color: black;
}

.a {
  color: red;
}

.b {
  color: blue;
}
```

## mixin

<p class="codepen" data-height="850" data-default-tab="css,result" data-slug-hash="qBogBZe" data-user="ryowakabayashi" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/ryowakabayashi/pen/qBogBZe">
  SCSS Mixin</a> by Ryo Wakabayashi (<a href="https://codepen.io/ryowakabayashi">@ryowakabayashi</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

`@mixin mixin名($変数名: 初期値, ...)`　で mixin を定義する

`@include mixin名($変数名: 値, ...)` で mixin を参照する

変数がない場合、 `()` を省略できる

変数に初期値がある場合、変数の指定を省略できる

ビルドすると、各 Selector の中に展開される

__SCSS__
```scss
@mixin x($color) {
  font-size: 24px;
  background-color: black;
  color: $color;
}

.a {
  @include x($color: red);
}

.b {
  @include x($color: blue);
}
```

__CSS__
```css
.a {
  font-size: 24px;
  background-color: black;
  color: red;
}

.b {
  font-size: 24px;
  background-color: black;
  color: blue;
}
```

## 関数（function）

<p class="codepen" data-height="300" data-default-tab="css,result" data-slug-hash="zYWeYZb" data-user="ryowakabayashi" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/ryowakabayashi/pen/zYWeYZb">
  SCSS Function</a> by Ryo Wakabayashi (<a href="https://codepen.io/ryowakabayashi">@ryowakabayashi</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

`@function 　関数名($変数名: 初期値, ...)`　で関数を定義する

`@return 値` で戻り値を定義する

`関数名($変数名: 値, ...)` で関数を参照し、戻り値を取得する

mixin は複数の `Property: Value` の組み合わせを返すのに対し、
function は単一の値を返す

## リスト

<p class="codepen" data-height="450" data-default-tab="css,result" data-slug-hash="oNqmgee" data-user="ryowakabayashi" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/ryowakabayashi/pen/oNqmgee">
  SCSS List</a> by Ryo Wakabayashi (<a href="https://codepen.io/ryowakabayashi">@ryowakabayashi</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

`$変数名: 値, 値, ...;` でリスト変数を定義する

`@each $値 in $変数名 {}` でリスト内をループする

__SCSS__
```scss
$color-list: red, blue, green;

@each $color in $color-list {
  .color-#{$color} {
    color: $color;
  }
}
```

__CSS__
```css
.color-red {
  color: red;
}

.color-blue {
  color: blue;
}

.color-green {
  color: green;
}
```

## マップ

<p class="codepen" data-height="450" data-default-tab="css,result" data-slug-hash="bGvzNXb" data-user="ryowakabayashi" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/ryowakabayashi/pen/bGvzNXb">
  SCSS Map</a> by Ryo Wakabayashi (<a href="https://codepen.io/ryowakabayashi">@ryowakabayashi</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>


`$変数名: (キー: 値, キー: 値, ...);` でマップ変数を定義する

`@each $キー, $値 in $変数名 {}` でマップ内をループする

__SCSS__
```scss
$color-map: (red: #f10, blue: #0f1, green: #10f);

@each $color, $value in $color-map {
  .color-#{$color} {
    color: $value;
  }
}
```

__CSS__
```css
.color-red {
  color: #f10;
}

.color-blue {
  color: #0f1;
}

.color-green {
  color: #10f;
}
```

## 条件分岐

<p class="codepen" data-height="800" data-default-tab="css,result" data-slug-hash="VwXgLrR" data-user="ryowakabayashi" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/ryowakabayashi/pen/VwXgLrR">
  SCSS Condition</a> by Ryo Wakabayashi (<a href="https://codepen.io/ryowakabayashi">@ryowakabayashi</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

`@if 条件 { ... } @else if 条件 { ... } @else { ... }` で条件分岐が記述できる

mixin と併用して使うことが多い


__SCSS__
```scss
$list: a, b, c;

@each $value in $list {
  .box-#{$color} {
    padding: 8px;
    @if $value == a {
      color: red;
    } @else if $value == b {
      font-weight: bold;
    } @else {
      display: none;
    }
  }
}
```

__CSS__
```css
.box-a {
  padding: 8px;
  color: red;
}

.box-b {
  padding: 8px;
  font-weight: bold;
}

.box-c {
  padding: 8px;
  display: none;
}
```

## 実装例

https://github.com/tokyo-metropolitan-gov/covid19/blob/development/assets/monitoringItemsTableCommon.scss