0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SASS / SCSS おさらい - media-breakpoint-down で学ぶレスポンシブ

0
Posted at

背景

  • SP 画面でテーブルレイアウトが崩れていたので SCSS で修正することになった

  • 修正コードを書く中で @include media-breakpoint-down(tab) という Bootstrap 5 互換の mixin に出会ったが、そもそも @mixin / @include / @content の理解が曖昧だった。せっかくなので SASS の基本からまとめ直すことにした

SASS / SCSS の基本

SASS は CSS の拡張言語で、ビルド時に 素の CSS に変換される。CSS にはない変数や mixin、ネスト記法といった機能が使える

SCSS と SASS の違い

  • SCSS(.scss)は SASS の CSS 風記法。{ } ベースで書ける
  • SASS(.sass)はインデントベースの記法
  • 多くのプロジェクトで「SASS」と呼ばれているのは実は SCSS

実用上は SCSS を採用するケースが多い。CSS と互換性があるので学習コストが低い

ネスト記法

.card {
  padding: 16px;

  .title {
    font-size: 20px;
  }

  &:hover {
    background-color: #f5f5f5;
  }
}

ビルド後:

.card { padding: 16px; }
.card .title { font-size: 20px; }
.card:hover { background-color: #f5f5f5; }

& は親セレクタを参照する記法で、&:hover のように擬似クラスと組み合わせるときに使う

変数

$xxx 形式で値に名前を付けて再利用できる仕組み

定義と参照

$primary-color: #3498db;
$base-padding: 16px;

.button {
  background-color: $primary-color;
  padding: $base-padding;
}

.alert {
  border: 1px solid $primary-color;
}

ビルド後:

.button { background-color: #3498db; padding: 16px; }
.alert { border: 1px solid #3498db; }

どんなときに使うか

  • 色・サイズ・余白などの定数: ブランドカラーや基本フォントサイズなど、プロジェクト全体で統一したい値
  • 計算の元になる値: $base-padding * 2 のように演算できる
  • 意味付け: #3498db より $primary-color の方が読み手に意図が伝わる

Bootstrap も $grid-breakpoints$primary などを変数で持っており、テーマカスタマイズはこれらの変数を上書きすることで行う

mixin と @include

スタイルのテンプレートを定義して再利用する仕組み

  • @mixin 名前 { ... } = スタイルテンプレートの 定義
  • @include 名前; = テンプレートを 呼び出し

@mixin で定義する

@mixin button-base {
  display: inline-block;
  padding: 8px 16px;
  border-radius: 4px;
  cursor: pointer;
}

@include で呼び出す

.primary-button {
  @include button-base;
  background-color: blue;
  color: white;
}

.secondary-button {
  @include button-base;
  background-color: gray;
}

ビルド後、button-base の中身が各セレクタに展開される

.primary-button {
  display: inline-block;
  padding: 8px 16px;
  border-radius: 4px;
  cursor: pointer;
  background-color: blue;
  color: white;
}
.secondary-button {
  display: inline-block;
  padding: 8px 16px;
  border-radius: 4px;
  cursor: pointer;
  background-color: gray;
}

引数を取る mixin

@mixin button-variant($bg, $color) {
  background-color: $bg;
  color: $color;
}

.primary-button {
  @include button-variant(blue, white);
}

引数を取れることで、似ているが少しだけ違うパターンを汎用化できる

@content — 呼び出し側のスタイルを差し込む

mixin の中で「呼び出し側の { } の中身」を展開する仕組み。これがレスポンシブ mixin の鍵

仕組み

@mixin sp-only {
  @media (max-width: 767.98px) {
    @content;   // ← 呼び出し側のスタイルがここに入る
  }
}

// 使う側
.title {
  font-size: 32px;

  @include sp-only {
    font-size: 20px;  // この行が @content の位置に展開される
  }
}

ビルド後:

.title { font-size: 32px; }

@media (max-width: 767.98px) {
  .title { font-size: 20px; }
}

@include の後に { } を付けて中身を渡すと、mixin 内の @content の位置に展開される

@content が活きる主なケース

// 1. レスポンシブ
@mixin sp-only {
  @media (max-width: 767.98px) { @content; }
}

// 2. 擬似クラス
@mixin on-hover {
  &:hover { @content; }
}

// 3. 親セレクタ条件
@mixin within-modal {
  .modal & { @content; }
}

使い方:

.btn {
  color: black;

  @include on-hover {
    color: blue;
  }
}

「条件(メディアクエリ・擬似クラス・親セレクタ)」と「その中身のスタイル」を分離して書けるのが @content の本質

レスポンシブ mixin の実例:media-breakpoint-down

Bootstrap 5 互換の mixin で、指定したブレークポイント名 未満 の viewport にスタイルを適用する

media-breakpoint-down(tab) の正体

@include media-breakpoint-down(tab) {
  // スタイル
}

これは内部的に以下のように展開される

@media (max-width: 1023.98px) {
  // スタイル
}

仕組み:

  • $grid-breakpoints というマップ(連想配列)からブレークポイント名に対応する値を引く
  • そこから 0.02px 引いた値を max-width として @media クエリを生成
  • 0.02 引くのは Bootstrap の慣習で、min-width 側との境界が重ならんように隙間を作るため

このプロジェクトでは独自に tab: 1024px$grid-breakpoints に追加して、SP/PC 境界として運用している

Bootstrap 5 の mixin

mixin 意味 出力例 (tab: 1024px の場合)
media-breakpoint-up(tab) 以上 (≥1024px) @media (min-width: 1024px)
media-breakpoint-down(tab) 未満 (<1024px) @media (max-width: 1023.98px)
media-breakpoint-only(tab) 該当区間のみ @media (min-width and max-width)
media-breakpoint-between(sm, tab) 範囲 @media (min-width and max-width)

PC ファーストとモバイルファースト

  • PC ファースト: PC スタイルを基底とし、down(tab) で SP に上書き
  • モバイルファースト: SP スタイルを基底とし、up(tab) で PC に上書き

Bootstrap 公式はモバイルファースト推奨だが、業務系 SaaS は PC が主役のケースが多いので、PC ファーストもアリな選択肢

mixin はどんなケースで使うか

mixin が威力を発揮するのは、「条件(メディアクエリ・擬似クラス・親セレクタなど)」と「その中身のスタイル」を分離したいとき

よくあるケース

ケース 効果
レスポンシブ @include sp-only { ... } メディアクエリの記述を 1 箇所に集約
擬似クラスの統一 @include on-hover { ... } hover の挙動をプロジェクト全体で揃える
親セレクタ条件 @include within-modal { ... } 「モーダル内では」のような文脈を簡潔に
ボタン・カードなどのコンポーネント @include button-base 共通スタイルを使い回す
ブラウザ別の hack @include only-safari { ... } ベンダープレフィックスを隠蔽

まとめ

  • SASS は CSS の拡張言語。変数・mixin・ネスト記法でスタイルの DRY を実現する
  • @mixin でテンプレートを定義し、@include で呼び出す
  • @content を使うと「呼び出し側の { } の中身」を mixin 内に差し込める。これがレスポンシブ mixin の鍵
  • media-breakpoint-down(tab) は Bootstrap 5 互換の mixin で、内部的には @media (max-width: 1023.98px) を生成している
  • mixin は「条件とスタイルを分離する」用途で威力を発揮する。同じパターンが 2 回以上出たら mixin 化を検討

感想

  • @include media-breakpoint-down(tab) を見て「謎の関数呼び出し」に見えてたけど、@mixin@content の仕組みを理解すると「ただのメディアクエリの薄いラッパー」だった
  • 久しぶりにcss周り調査したな

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?