SASSにおける継承

SASSにおける継承

この記事ではSASSにおける継承について説明します。

SASSにおける継承について実際的なサンプルを含めて解説します。

YouTube Video

SASSにおける継承

SASS の継承(@extend)は、あるセレクタのスタイルを別のセレクタに重複せずに適用する仕組みです。マークアップ上で複数の要素に同じスタイルを「結合」して出力するので、生成されるCSSが冗長になりにくい一方で、使い方を誤ると意図しないセレクタ合成を生みます。

基本:@extend の使い方

以下は、.btn のスタイルを .btn--primary が継承する基本例です。@extend は、対象のセレクタを拡張する命令です。

 1// Base button styles
 2.btn {
 3  padding: 0.5rem 1rem;
 4  border-radius: 4px;
 5  border: 1px solid #ccc;
 6  background: white;
 7  color: #333;
 8}
 9
10/* Primary button extends the base .btn */
11.btn--primary {
12  @extend .btn;
13  background: #007bff;
14  color: white;
15}
  • .btn--primary@extend によって .btn の基本スタイルを引き継ぎ、必要な部分だけ上書きしています。

生成されるCSS

 1.btn, .btn--primary {
 2  padding: 0.5rem 1rem;
 3  border-radius: 4px;
 4  border: 1px solid #ccc;
 5  background: white;
 6  color: #333;
 7}
 8
 9.btn--primary {
10  background: #007bff;
11  color: white;
12}

ベストプラクティス:プレースホルダ(%placeholder)の利用

プレースホルダセレクタ(%name)は、CSSには出力されないセレクタです。継承専用として安全に扱えるため、特に複数コンポーネント間で共通スタイルを共有したい場面で広く利用されます。

 1// %placeholder will not be output directly
 2%card-base {
 3  padding: 1rem;
 4  border-radius: 6px;
 5  box-shadow: 0 1px 3px rgba(0,0,0,0.08);
 6  background: #fff;
 7}
 8
 9/* Components extend the placeholder */
10.card {
11  @extend %card-base;
12  border: 1px solid #eee;
13}
14
15.panel {
16  @extend %card-base;
17  border: 1px solid #ddd;
18}
  • .card.panel%card-base を継承し、共通スタイルを共有しつつ必要な部分だけ個別に追加しています。

生成されるCSS

 1.card, .panel {
 2  padding: 1rem;
 3  border-radius: 6px;
 4  box-shadow: 0 1px 3px rgba(0,0,0,0.08);
 5  background: #fff;
 6}
 7
 8.card {
 9  border: 1px solid #eee;
10}
11
12.panel {
13  border: 1px solid #ddd;
14}

複数継承(複数の @extend

複数のプレースホルダやクラスを同時に継承できます。スタイルの再利用性が高まりますが、どのルールがどのセレクタと結合されるかを把握しておく必要があります。

 1%btn-base {
 2  display: inline-block;
 3  padding: 0.5rem 1rem;
 4  border-radius: 3px;
 5}
 6
 7%btn-large {
 8  padding: 0.75rem 1.5rem;
 9  font-size: 1.125rem;
10}
11
12/* Composite button that extends both placeholders */
13.btn--lg {
14  @extend %btn-base;
15  @extend %btn-large;
16  background: #222;
17  color: #fff;
18}
  • ボタンに対して「ベース」と「サイズ」の二つのプレースホルダを継承する例です。
  • .btn--lg%btn-base%btn-large の両方を継承して、基本のレイアウトと大きめのサイズ設定を組み合わせています。

生成されるCSS

1.btn--lg {
2  display: inline-block;
3  /* %btn-large overrides the padding from %btn-base */
4  padding: 0.75rem 1.5rem;
5  border-radius: 3px;
6  font-size: 1.125rem;
7  background: #222;
8  color: #fff;
9}

@extend の挙動(マージの仕組み)と「セレクタ爆発」の注意点

@extend は該当するすべてのセレクタを合成して出力するため、意図しない多数のセレクタ結合が生まれることがあります。

次の例は、複数の場所で同じベースクラスを拡張すると、出力がどのように増えるかを示します。

 1/* Many components extend .utility */
 2/* A generic utility class */
 3.utility {
 4  margin-bottom: 1rem;
 5}
 6
 7/* Nested selectors that extend .utility */
 8.header {
 9  @extend .utility;
10  .title {
11    font-weight: bold;
12  }
13}
14
15.footer {
16  @extend .utility;
17  .note {
18    color: #888;
19  }
20}
21
22.article {
23  @extend .utility;
24  .content {
25    line-height: 1.6;
26  }
27}
28
29.sidebar {
30  @extend .utility;
31  .section {
32    padding: 1rem;
33  }
34}
  • 複数のコンポーネントが .utility を継承するとセレクタが1つに統合され、規模が大きい場合はCSSが膨張しやすくなります。

生成されるCSS

 1.utility,
 2.header,
 3.footer,
 4.article,
 5.sidebar {
 6  margin-bottom: 1rem;
 7}
 8
 9.header .title {
10  font-weight: bold;
11}
12
13.footer .note {
14  color: #888;
15}
16
17.article .content {
18  line-height: 1.6;
19}
20
21.sidebar .section {
22  padding: 1rem;
23}

@extend.class vs 要素セレクタ(タグ) — 優先順位と副作用

@extend はクラスだけでなく要素セレクタにも適用できますが、要素を拡張すると影響範囲が広くなり、意図しない箇所にルールが適用されてしまうリスクが高まります。

以下は、要素セレクタを拡張した例と、それがもたらす影響を示します。

 1/* Extending an element selector (not recommended) */
 2h1 {
 3  font-size: 2rem;
 4  margin-bottom: 0.5rem;
 5}
 6
 7/* If you extend h1, the resulting selector will include your class with h1 */
 8.title {
 9  @extend h1;
10  color: #333;
11}
12
13/* Output becomes:
14h1, .title { font-size: 2rem; margin-bottom: 0.5rem; }
15*/
  • この例は、要素セレクタ h1 を継承すると、.titleh1 と同じスタイルに結合されることを示しています。
  • 小規模な範囲であれば便利に見えるものの、大規模になると h1 のルールが意図せず .title と結合し、スタイルが複雑化して保守性が低下します。そのため、クラスやプレースホルダを中心にスタイルを設計する方が、保守しやすくなります。

生成されるCSS

1h1,
2.title {
3  font-size: 2rem;
4  margin-bottom: 0.5rem;
5}
6
7.title {
8  color: #333;
9}

@extend!optional の使いどころ

@extendに、!optionalを指定すると、継承対象が存在しない場合にエラーを抑えることができます。特に、ライブラリ的なコードや、プレースホルダが条件によって定義されるケースで便利です。

以下は、存在しないかもしれないクラスを !optional 付きで安全に継承しようとする例です。

1/* Try to extend a class that might not exist */
2.component {
3  @extend .maybe-existing !optional;
4  padding: 1rem;
5}
  • .maybe-existing がなければ何も起きずにスキップされます。安全に拡張を試みたいときに使えます。

生成されるCSS

1.component {
2  padding: 1rem;
3}

@extend と Mixin(@mixin / @include)の比較

@extend@mixin は目的が被ることがありますが、出力と用途が異なります。

  • @extend

    • 出力されるCSSはセレクタのマージで冗長性を減らす。
    • 生成後のCSS が合成されるため、意図せぬ結合が起きる可能性がある。
    • パラメータを渡せない(ただしプレースホルダの組み合わせで代用可)。
  • @mixin / @include

    • 呼び出すたびにスタイルが複製される(重複出力)。
    • パラメータを受け取り、条件分岐やループなどのロジックを含められる。
    • 出力は予測しやすいが、サイズは増える。

以下は、同じボタンのスタイルを @mixin@extend で実装した比較例です。

 1/* Mixin approach */
 2@mixin btn-styles($bg, $color) {
 3  display: inline-block;
 4  padding: 0.5rem 1rem;
 5  background: $bg;
 6  color: $color;
 7  border-radius: 4px;
 8}
 9
10/* Use mixin */
11.btn {
12  @include btn-styles(white, #333);
13}
14
15.btn--primary {
16  @include btn-styles(#007bff, white);
17}
18
19/* Extend approach (shared placeholder) */
20%btn-base {
21  display: inline-block;
22  padding: 0.5rem 1rem;
23  border-radius: 4px;
24}
25
26.btn2 {
27  @extend %btn-base;
28  background: white;
29  color: #333;
30}
31
32.btn2--primary {
33  @extend %btn-base;
34  background: #007bff;
35  color: white;
36}
  • @mixin は柔軟にスタイルを挿入でき、@extend は出力をまとめて効率化できるため、用途に応じて使い分けることができます。

生成されるCSS

@mixin の出力
 1.btn {
 2  display: inline-block;
 3  padding: 0.5rem 1rem;
 4  background: white;
 5  color: #333;
 6  border-radius: 4px;
 7}
 8
 9.btn--primary {
10  display: inline-block;
11  padding: 0.5rem 1rem;
12  background: #007bff;
13  color: white;
14  border-radius: 4px;
15}
@extend の出力
 1.btn2,
 2.btn2--primary {
 3  display: inline-block;
 4  padding: 0.5rem 1rem;
 5  border-radius: 4px;
 6}
 7
 8.btn2 {
 9  background: white;
10  color: #333;
11}
12
13.btn2--primary {
14  background: #007bff;
15  color: white;
16}

実践的なガイドライン

SASSの継承はスタイルの再利用性を高めるための強力な機能です。しかし、使い方を誤るとスタイルの結合が複雑になり、保守性が低下してしまいます。以下に、安全かつ効率的に継承を利用するためのポイントをいくつか紹介します。

  • コンポーネント共通の純粋なスタイル(構造やレイアウト)には、プレースホルダーを活用します。また、動的なパラメータ化が必要な場合には @mixin を使用できます。
  • h1などのHTML要素を直接継承することは避けるべきです。意図しないセレクタ結合が発生し、予期しない CSS が生成される可能性があります。
  • BEM などの命名規則や明確なプレフィックスを活用し、各プレースホルダが何を担うのかを一目でわかるようにしておくと安全です。
  • @extend は同じファイル内で利用するほうが安全です。特に、大規模なプロジェクトでは、継承関係を追跡しやすくするため、継承をコンポーネント単位のスコープに収めるよう設計できます。

まとめ

SASS の @extend は、共通スタイルを効率よく再利用し、デザインの一貫性を保つための便利な機能です。しかし、セレクタ同士の結合が複雑化しやすいため、使用範囲は慎重に絞る必要があります。プレースホルダセレクタ(%placeholder)で共有スタイルをまとめ、動的なパラメータが必要な部分は @mixin で補うことで、シンプルで保守しやすい設計を維持できます。

YouTubeチャンネルでは、Visual Studio Codeを用いて上記の記事を見ながら確認できます。 ぜひYouTubeチャンネルもご覧ください。

YouTube Video