SCSSの書き方をまとめてみた

SCSSの書き方をまとめてみました。

実際のHTML、SCSS、コンパイル後のCSSを例として記述しています。

SCSSの公式サイトはこちら

子孫要素

基本入れ子で書くだけですが、ブラウザのマッチ判定回数が増えてページ速度が遅くなるので後で記載しているBEM記法とかで要素にクラスを指定した方がいいと思います。

要素で指定

<div>
  <p>テスト</p>
</div>
div {
  p {
    font-weight: bold;
  }
}
div p {
  font-weight: bold;
}

クラス名で指定

<div class="class1">
  <p class="class2">テスト</p>
</div>
.class1 {
  .class2 {
    font-weight: bold;
  }
}
.class1 .class2 {
  font-weight: bold;
}

複数クラス

クラス名を入れ子にして「&.class」とすれば複数のクラスのセレクタになります。

<div class="class1 class2">
  <p>テスト</p>
</div>
.class1 {
  &.class2 {
    border: 1px solid #000;
  }
}
.class1.class2 {
  border: 1px solid #000;
}

擬似要素

複数クラスのときのように入れ子にして「&::疑似要素」とすればOKです。

<div>
  <p>テスト</p>
</div>
p {
  &::before {
    content: "★";
  }
}
p::before {
  content: "★";
}

擬似クラス、擬似要素

これも複数クラスのときのように入れ子にして「&:疑似クラス」「&::擬似要素」とすればOKです。

擬似クラス

<div>
  <a href="#">テスト</a>
</div>
a {
  &:hover {
    background: #000;
    color: #fff;
  }
}
a:hover{
  background: #000;
  color: #fff;
}

擬似要素

<ul>
  <li>リスト1</li>
  <li>リスト2</li>
  <li>リスト3</li>
</ul>
li {
  &::before {
    content: '・';
  }
}
li::before {
  content: '・';
}

変数

SCSSでは変数が使えます。

使い方は「$変数名: 値」で変数を宣言し、使用するときは「プロパティ: $変数名」とします。

例えばエラーメッセージの色コードなど共通化したいものを変数にしておけば変更が一箇所で済みます。

<div>
  <p>テスト</p>
</div>
$error: #f00;
div {
  p {
    color: $error;
  }
}
div p {
  color: red;
}

関数

「@function 関数名(引数) {}」とすれば関数を定義でき、「プロパティ名: 関数名(引数の値)」で関数を呼び出せます。

横幅の計算などサイト全体で共通のルールがある場合などに関数を定義しておけばもしルールの変更があった場合も修正が楽になります。

関数内ではifで条件分岐、forでループ処理も行えます。

<div>
  <p>テスト</p>
</div>
@function calc_width($base, $ratio) {
  @return $base * $ratio
}

div {
  p {
    border: 1px solid #000;
    width: calc_width(1200, 0.5);
  }
}
div p {
  border: 1px solid #000;
  width: 600;
}

継承

SCSSではクラスの継承ができます。

ベースとなるスタイルの定義があって、基本的にはそのスタイルで一部だけ文字色を変えたいみたいな場合に使えます。

使い方は「%セレクタ名 { プロパティ: 値 }」として継承するスタイルを定義しておき、「@extend セレクタ名」とすればスタイルを継承できる。

<div>
  <p class="class1">クラス1</p>
  <p class="class2">クラス2</p>
</div>
%base-text {
  color: #000;
  font-style: 2em;
  font-weight: bold;
}

.class1 {
  @extend %base-text;
  color: #f00;
}

.class2 {
  @extend %base-text;
  color: #00f;
}
.class1,.class2 {
  color: #000;
  font-style: 2em;
  font-weight: bold;
}

.class1 {
  color: #f00;
}

.class2 {
  color: #00f;
}

スタイルの継承は下記のように「.base-text」として通常のクラスとしてスタイルを定義してそのクラスを継承することもできますが、「.base-text」自体の定義は不要なので上記のように「%base-text」と定義したほうがCSSの不要な記述が少なくなります。

<div class="class1">
  <p class="class2">テスト</p>
</div>
.base-text {
  color: #000;
  font-style: 2em;
  font-weight: bold;
}

.class1 {
  @extend .base-text;
  color: #f00;
}

.class2 {
  @extend .base-text;
  color: #00f;
}
.base-text,
.class1,
.class2 {
  color: #000;
  font-style: 2em;
  font-weight: bold;
}
.class1 {
  color: #f00;
}
.class2 {
  color: #00f;
}

BEM記法

SCSSだとBEM記法も書きやすいです。

ただ、このやり方だとクラス名を分割することでクラス名でgrepしたときに検索に引っかからなくなるので書きやすいですがメンテナンス性は悪いかもです。

<div class="overview">
  <h1 class="overview__title">見出し1</h1>
  <h2 class="overview__title--red">見出し2</h2>
</div>
.overview {
  border: 1px solid #000;
  padding: 2em;
  &__title {
    font-size: 2em;
    font-weight: bold;
    &--red {
      color: #f00;
    }
  }
}
.overview__title,
.overview__title--red {
  font-size: 2em;
  font-weight: bold;
}
.overview {
  border: 1px solid #000;
  padding: 2em;
}
.overview__title--red {
  color: #f00;
}

レスポンシブ(メディアクエリ)

レスポンシブ(メディアクエリ)では下記のように書きます。

mixin、map-get、inlucdeなどの記述についてはこちらの記事がわかりやすいと思います。

<h1 class="title">見出し1</h1>
$breakpoints: {
  'sm': 'screent and (min-width:400px)',
  'md': 'screent and (min-width:768px)',
  'lg': 'screent and (min-width:1000px)',
  'xl': 'screent and (min-width:1200px)',
}

@mixin mq(&breakpoint: md) {
  @media #{map-get($breakpoints, &breakpoint)} {
    @content;
  }
}

.title {
  font-size: 1.5rem;
  @include mq(md) {
    font-size: 1.8rem;
  }
}
.title {
  font-size: 1.5rem;
}

@media screen and (min-width: 768px) {
  .title {
    font-size: 1.8rem;
  }
}