ReactでSCSSを使う


この記事はほぼ以下記事の写経です
本家を読んでもらった方が身につくと思います

https://qiita.com/ayumiueda_/items/4edfde9c58f7d87887fc#%E5%9F%BA%E6%9C%AC%E7%9A%84%E3%81%AA%E5%A4%89%E6%95%B0%E3%81%AE%E4%BD%BF%E3%81%84%E6%96%B9


# やりたいこと


なんとなくで書いてきたSCSSを一度ちゃんと勉強しておきたい


# SCSSとは


CSSでは出来なかった変数の利用、ネストや継承などのモダンで良さげな書き方ができる仕組みとしてSassが登場しましたが、CSSとは異なるインデントで書く方法が嫌気されたようで、その後登場したSassの機能を取り入れたSCSSが主流となったようです。実際、フロントエンドフレームワークの公式ドキュメントやQiitaの記事でも見かけるのはSCSSが中心で、Sassを見かけることは少ないので実感としてもそう感じられます


ちなみに、React＋Vite環境でSCSSを使っているとSassのdeprecation Warningが出たりしますので、実装上は中身が共通だったりするようです


# トランスパイルについて


ブラウザはSCSSに対応していないので、実装としてはトランスパイラでCSSにしてブラウザに届ける必要があります。ReactやVueの場合はトランスパイラが入る前提ですからビルド時にSCSSをトランスパイルしてCSSにすれば良いですし、PHPやPythonなどのバックエンドでトランスパイルしてCSSを届ける実装にする例もあるようです。CSS Modulesとの相性も良いので、上手く組み合わせればコードの整備性が高めつつ、適切な適用スコープ管理を実現することが出来るようです


# 今回の使い方


今回はReact Router v7で利用します


## 1. インストール


React Router v7プロジェクト内でnpm installすれば入ります


```terminal:terminal
npm install scss
```


## 2. ネスト


以下のように、a要素内の要素やクラス、hoverなどの状態に適用したいケースはよくありますが、CSSではそれぞれに対して指定してく書き方になります


```css:css
a {
    font-size: 16px;
}
a:hover {
    opacity: 0.5;
}
a span {
    color: red;
}
```


SCSSでは以下のようにネストすることで記述範囲を分かりやすく書けます


```scss:scss
a {
    font-size: 16px;
    &:hover: opacity: 0.5;
    span {
        color: red;
        }
}
```


## 3. 変数


変数を定義して、計算や文字列作成に使ったり、CSSの指定に使ったりできます


```scss:scss
$hoge: 16px;

p {
    font-size: $hoge;
}
```


計算もできます
pxとか付いてても計算できちゃう


```scss:scss
$hoge: 16px;

p {
    font-size: $hoge + 2px;
}
```


Javascriptっぽく文字列処理もできます


```scss:scss
$変数名 + "文字列";
"#{$変数名}文字列";
```


## 4. extend


<hoge>@</hoge>extendでクラス名などを指定すると継承できます


```scss:scss
.base-border {
  border: 1px solid #000;
  border-radius: 16px;
}

.box1 {
  @extend .base-border;
  width: 100%;
}
```


以下と同じになります


```css:css
.base-border {
  border: 1px solid #000;
  border-radius: 16px;
}

.box1 {
  border: 1px solid #000;  /* ここが継承されている */
  border-radius: 16px;  /* ここが継承されている */
  width: 100%;
}
```


### 継承専用にしたい場合


%から書き出すようにすると、継承専用のプレースホルダーとして処理してくれます


```scss:scss
%base-border {
  border: 1px solid #000;
  border-radius: 16px;
}
.box1 {
  @extend .base-border;
  width: 100%;
}
```


トランスパイルすると以下のようになります


```css:css
.box1 {
  border: 1px solid #000;  /* ここが継承されている */
  border-radius: 16px;  /* ここが継承されている */
  width: 100%;
}
```


## 5. mixin


mixinを使うと一部を引数で指定して継承することができます


```scss:scss
@mixin baseBox($width, $height) {
  padding: 16px;
  width: $width;
  height: $height;
}

.box1 {
  @include baseBox(300px, 200px);
}
```


トランスパイルすると以下のようになります


```css:css
.box1 {
  padding: 16px;
  width: 300px;
  height: 200px;
}
```


## 6. 条件分岐


変数を使って条件分岐もできます


```scss:scss
$hoge = true

@if $hoge == true {
        color: blue;
    } @else {
        color: red;
    }
```


## 7. 繰り返し処理


繰り返し処理なんてのも出来るようです


### for


```scss:scss
@for $i from 12 through 14 {
    .fs#{$i} {font-size: #{$i}px;}
}
```


トランスパイルすると以下のようになります


```css:css
.fs12 {
  font-size: 12px;
}
.fs13 {
  font-size: 13px;
}
.fs14 {
  font-size: 14px;
}
```


### while


上記をwhileで書くと以下のようになります


```scss:scss
@while $i <=14 {
    .fs#{$i} {font-size: #{$i}px;}
    $i: $i + 1;
}
```


### each


for eachも書けます


```scss:scss
@each $i in 12, 13, 14 {
    .fs#{$i} {font-size: #{$i}px;}
}
```


## 8. 関数


### 自作する


関数も作れます


```scss:scss
@function hello($key){
  @return $key + ",world";
}
.sample{
  content: hello("hello");  
}
```


```css:css
.sample{
  content: "hello,world";
}
```


### 用意されている関数を使う


色を明るくするなど、デフォルトで用意されている関数がいろいろあります


```scss:scss
.my-class {
  background-color: lighten(#333333, 20%); // #595959 に変わる
  color: lighten(blue, 30%);              // 明るい青に変わる
}
```


トランスパイルすると以下のようになります


```css:css
.my-class {
  background-color: #595959`;
  color: #99ccff;
}
```


用意されている関数には以下のようなものがあります


```scss:色の操作
lighten($baceColor, 20%); ：明度を上げる
darken($baceColor, 20%); ：明度を下げる
saturate($baseColor, 20%); ：彩度を上げる
desaturate($baceColor, 20%); ：彩度を下げる
adjust-hue($baceColor, 50deg); ：色相を変える
invert($baceColor); ：色を反転する
grayscale($baceColor); ：グレースケールにする
complement($baceColor); ：補色に変える
mix(#fff, #000, 50%); ：2つのカラーコードの中間色にする
rgba($baceColor, 0.5); ：透明度を変える
```


```scss:数値の操作
round($number) ：四捨五入
ceil($number) ：小数点以下を切り上げ
floor($number) ：小数点以下を切捨て
abs($number) ：絶対値（正の値）を返す
percentage($number) ：パーセント形式に変換
min($numbers…) ：引数で渡した値の中から最も小さい値を返す
max($numbers…) ：引数で渡した値の中から最も大きい値を返す
```


```scss:その他
random() ：0〜1までのランダムな数値を返す（値に数値を入れると、1〜入れた数値の間でランダムな数値を返す）
nth(n) ：配列からn番目の値を返す
quote() ：入れた値をダブルクオーテーションで囲って出力する
```


## 9. ファイルを分割する


別のSCSSファイルからimportして使うこともできます


```scss:scss
@import "settings";
@import "function";
```



## 10. コメント


SCSSでは/* */だけでなく、//でもコメントが書けます


```scss:scss
// ほげほげ
```


# まとめ


ここまでパワフルとは思っていなかったので一通りやってみて驚きました
色々試しながら上手い使い方を身に着けたいです