こんにちは!運営者のハックです。
今回は以前学習したSassについて、書籍「Sassの教科書」によりさらに詳しく機能を学習しましたので、その内容について紹介します。
書籍「Sass」の教科書でさらにSassの機能を深掘りして学習しました。
Sassの基本的な文法やルールについてはWeb制作コース初級編Day23「CSSの上位互換!Sassを学習しよう」の会で学びましたが、今回はSassについて書籍「Sassの教科書」でさらに便利な機能について学習しました。その内容について紹介します。
ハイフンがあるプロパティはすべてネストできる
Sassでは、ハイフンを含むCSSプロパティ(例えば font-weight や background-color など)を簡単に管理できる特別な機能があります。関連するプロパティをまとめて記述することで、より整理されたスタイルシートを作成するのに役立ちます。
具体的には、ベースとなるプロパティ名からハイフン以降をブロック内にネストして記述します。これにより、コードがスッキリとし、同じプロパティ群に対する変更や更新が簡単になります。
例えば、font
関連のプロパティをネストする場合、以下のように書けます。
.selector {
font: {
weight: bold;
size: 14px;
family: sans-serif;
}
z: {
index:5;
}
}
font-weightとかfont-sizeなどのハイフン以下をまとめて記述できるのは楽なのにゃ。
でも「z-index」ってネストする意味がないのにエラーにならないのかにゃ?
書籍によると『未知のプロパティに対応するためだと思われますが、単にプログラムがチェックしていないだけかも』とのことです。
ネストしているセレクタをルートに戻せる@at-root
@at-rootは記述した場所より親のセレクタや@mediaなどを除外し、ルートに戻すことができる機能です。特定のスタイルが親セレクタから独立しているべき場合に特に便利な機能です。
//Sass
.block {
.element-A {
color: black;
}
@at-root .element-B {
color: blue;
}
}
/* CSS(コンパイル後) */
.block .element-A {
color:black;
}
.element-B {
color:blue;
}
.element-A はネストしているのでコンパイル後のCSSでは.block .element-A となっていますが、@at-rootを使った.element-Bはルートから書き出されていることが確認できます。
@at-rootのオプション(withoutとwith)
@at-root には without と with という二つのオプションがあります。これらのオプションを使うことで、ルートレベルに出力する際の条件を更に細かく制御することができます。
without オプション
without オプションは、特定の種類のルールやディレクティブをルートレベルに出力する際に除外するために使用します。つまり、指定した種類の要素だけを保持して、他の要素をルートレベルに出力します。
//Sass
.parent {
@at-root without (media) {
.child {
color: blue;
}
@media (min-width: 500px) {
.child { color: red; }
}
}
}
/* CSS(コンパイル後) */
.child {
color: blue;
}
@media (min-width: 500px) {
.parent .child {
color: red;
}
}
この例では、@at-root without (media) が使用されています。これにより、@media ブロックを除いて .child セレクタがルートレベルに出力されます。
with オプション
with オプションは without の逆で、指定した種類の要素のみをルートレベルに出力します。未指定の要素は通常どおりのネスト位置に残ります。
//Sass
.parent {
@at-root with (media) {
.child {
color: blue;
}
@media (min-width: 500px) {
.child { color: red; }
}
}
}
/* CSS(コンパイル後) */
.parent .child {
color: blue;
}
@media (min-width: 500px) {
.child {
color: red;
}
}
この場合、@at-root with (media) は @media ブロックのみをルートレベルに出力し、.child はネストされた位置に残ります。
制御構文で条件分岐や繰り返し処理を行うことができる!
Sassではプログラミング言語のように条件分岐や繰り返し処理を行うことができます。これにより、スタイルシートの動的な生成が可能になり、効率的なCSSの管理が行えるようになります。
(条件分岐とか繰り返し処理ができるって、SassってもはやRubyとかJavaみたいなバックエンドの言語なんじゃにゃいの?)
条件分岐(@if, @else if, @else)
Sassの@ifディレクティブは、指定した条件がtrueの場合に特定のスタイルを適用します。@else ifと@elseはオプショナルで、複数の条件をチェックする際や、どの条件にも当てはまらなかった場合のスタイルを定義します。
//Sass
$theme: "dark";
body {
@if $theme == "dark" {
background-color: black;
color: white;
} @else if $theme == "light" {
background-color: white;
color: black;
} @else {
background-color: gray;
color: darkgray;
}
}
この例では、$theme変数の値に応じて背景色とテキスト色が変わります。
繰り返し処理(@for, @each, @while)
Sassには3種類のループ構文があります: @for, @each, そして @whileです。
@for
@forは指定した回数だけスタイルルールを繰り返します。
@for $i from 1 through 3 {
.item-#{$i} { width: 100px * $i; }
}
このコードは、.item-1, .item-2, .item-3に対してそれぞれwidthを100px, 200px, 300pxと設定します。
@each
@eachはリストやマップの各要素に対して繰り返し処理を行います。
$colors: (red: #f00, green: #0f0, blue: #00f);
@each $key, $color in $colors {
.#{$key}-text { color: $color; }
}
このコードは、各色に対応するクラス(.red-text, .green-text, .blue-text)に色を設定します。
@while
@whileは指定した条件がtrue
である間、コンテンツを繰り返し出力します。
$i: 1;
@while $i <= 3 {
.item-#{$i} { width: 100px * $i; }
$i: $i + 1;
}
@forループの例と同様の出力を生成しますが、条件を基にループが回ります。
関数を使って様々な処理を実行できる!
Sassでは多くの組み込み関数を利用することができ、CSSの生成をより効率的かつ動的に行うことが可能です。以下に、Sassでよく使用されるいくつかの関数とその具体例を紹介します。
(関数も使えるのにゃ?やっぱSassってバックエンド言語なんじゃ…)
1. 色関連の関数
lighten() と darken()
lighten() 関数と darken() 関数は、色を明るくまたは暗くするのに使用します。
.element {
background-color: lighten($base-color, 20%); // 基本色を20%明るく
color: darken($base-color, 20%); // 基本色を20%暗く
}
mix()
mix() 関数は、二つの色を指定した比率で混合します。
.element {
background-color: mix($color1, $color2, 50%); // $color1と$color2を50%の割合で混合
}
2. 数値計算関数
percentage()
percentage() 関数は、数値をパーセンテージ形式(0-100%)に変換します。
.element {
width: percentage(5/10); // 0.5をパーセンテージに変換 -> 50%
}
round(), ceil(), floor()
これらの関数は数値を整数に丸めるために使用します。round() は最も近い整数に、ceil() は上への丸め、floor() は下への丸めを行います。
.element {
padding: round(1.67em); // 2emに丸める
margin: ceil(1.01em); // 2emに丸める(上へ)
border-width: floor(1.99em); // 1emに丸める(下へ)
}
3. 文字列関数
str-slice()
str-slice() 関数は、文字列の指定された範囲の部分文字列を返します。
.element:before {
content: str-slice("Hello World", 1, 5); // 'Hello'を抽出
}
4. リスト関数
nth()
nth() 関数はリストから指定された位置の要素を取得します。
$list: 10px, 15px, 20px;
.element {
padding: nth($list, 2); // 15pxを取得
}
5. マップ関数
map-get()
map-get() 関数はマップ(連想配列)から指定されたキーに関連付けられた値を取得します。
$colors: (primary: blue, secondary: green);
.element {
color: map-get($colors, primary); // 'blue'を取得
}
テストやデバックで使えるディレクティブ@debug,@warn,@errorもある
Sassでは、コードのテストやデバッグのプロセスをサポートするために@debug、@warn、そして@errorという特別なディレクティブが用意されています。これらは開発中にコードの問題を診断しやすくするために非常に便利です。
デイトラJavaコース中級編で学んだテスティングフレームワークを思い出すのにゃ。
@debug
@debug は、変数の値や計算結果などをコンソールに出力します。これは問題の特定や変数の値が期待通りであるかどうかをチェックするのに使用します。
$base-color: green;
@debug "The base color is " + $base-color; // コンソールに "The base color is green" を出力
@warn
@warn は、開発者に警告を通知するために使用します。これは使用してはいけない古いスタイルや推奨されない方法がコード内で使用されている場合に役立ちます。
@mixin add-deprecated-feature {
@warn "This feature will be deprecated soon. Please update your code.";
border-radius: 10px;
}
.box {
@include add-deprecated-feature; // コンパイル時に警告メッセージが表示される
}
@error
@error は、致命的なエラーを発生させ、コンパイルを停止します。これは変数が期待される型でない場合や必須の引数が欠けている場合に特に有用です。
@function calculate-margin($size) {
@if type-of($size) != 'number' {
@error "Expected a number, but got a #{type-of($size)}.";
}
@return $size * 1.5;
}
.container {
margin: calculate-margin("big"); // エラー: Expected a number, but got a string.
}
インターポレーションを使って変数が参照できない場所でも使用できるように
インターポレーション(Interpolation)は、変数や式の結果を文字列の中に動的に埋め込む機能です。これにより、変数の値をプロパティ名、セレクタ、または値として使用することができます。特に、セレクタやプロパティ名に変数を使いたい場合に有効です。
基本的な使い方
インターポレーションは #{}
という構文を使用します。インターポレーションを使うことで、Sassの変数や式の結果を文字列中に展開することができます。
例1.変数をセレクタに含める
//Sass
$animal: penguin;
.#{$animal}-icon {
background-image: url("/images/#{$animal}.png");
}
/* CSS(コンパイル後) */
.penguin-icon {
background-image: url("/images/penguin.png");
}
例2.変数をプロパティ名に使用
//Sass
$property: margin;
.box {
#{$property}-top: 10px;
#{$property}-bottom: 20px;
}
/* CSS(コンパイル後) */
.box {
margin-top: 10px;
margin-bottom: 20px;
}
これならインター何とかを使わなくても直接「margin-top」とかって書いちゃえばいいんじゃないかにゃ?
もし名前を「margin」から変更したくなった場合、インターポレーションで指定していると「$property: margin;」の「margin」を変更するだけで済みます。
インターポレーションのメリット
- 動的なセレクタやプロパティ名:インターポレーションを使用すると、プログラム的にセレクタ名やプロパティ名を生成できるため、より動的で再利用可能なコードが書けます。
- カスタマイズ可能なテーマ:テーマの色やフォントサイズなどを変数として定義し、それをサイト全体にわたってインターポレーションを使って適用することで、一元的にスタイルを管理しやすくなります。
- 保守性と拡張性の向上:変数の値を変えるだけで、関連するすべてのスタイルが更新されるため、コードの保守が簡単になり、変更に強い設計が可能です。
使用時の注意
インターポレーションは強力な機能ですが、過度に使用するとコードが複雑になる可能性があります。特に、プロパティ名やセレクタ名に頻繁に使用すると、生成されるCSSが予測しにくくなることがあります。そのため、必要な場合にのみ使用し、コードの可読性を保つよう心掛けることが重要です。
変数の振る舞いをコントロールする !defaultと!globalを学ぼう
Sassでは変数のスコープやデフォルト値を管理するために!defaultと!globalフラグが用意されています。これらは変数の振る舞いを柔軟にコントロールするために非常に便利です。
「!default」って確かデイトラWeb制作コース初級編Day23「CSSの上位互換!Sassを学習しよう」の回で「@mixin」の説明で紹介していたコードに使われていたのにゃ。
ねこ奈よく覚えてましたね、偉い!
(私はすっかり忘れていました…)
!default
!defaultフラグは、変数にデフォルト値を設定するために使用されます。このフラグが付けられた変数は、その変数が未定義、つまり以前に値が設定されていない場合にのみ値が割り当てられます。これはテーマやライブラリのような再利用可能なコードで特に有用で、ユーザが独自の値を提供しなかった場合のフォールバック値として機能します。
$base-color: black !default; // デフォルト値としてblackが設定される
// 他のスタイルシートやユーザ定義の値によって上書き可能
$base-color: red; // この行が先に読み込まれれば、$base-colorはredになる
body {
color: $base-color; // 使用する値
}
使用上の注意点
- 上書きの順序: !default で設定された変数は、それより前に同じ変数に値が割り当てられていない限り、その値が適用されます。そのため、ファイルの読み込み順序や変数の定義順序に注意が必要です。
- 明示的な再定義: ユーザがカスタム値を設定したい場合は、!default が指定された変数を明示的に再定義する必要があります。
!global
!globalフラグは、ローカルスコープ内で定義された変数をグローバルスコープに強制的に割り当てるために使用します。このフラグを使用することで、モジュールや関数の内部で値を更新し、その更新がローカルスコープに留まらずに全体に影響を及ぼすようにすることができます。
(Javaの「public」化に近いものを感じるのにゃ。)
$color: blue; // グローバルスコープでの定義
.some-selector {
$color: red !global; // !globalを使用してグローバル変数を更新
background-color: $color; // red
}
// グローバル変数$colorはredに更新されている
.other-selector {
color: $color; // red
}
使用上の注意点
- スコープの管理: !global はグローバルスコープに影響を及ぼすため、使用する際は慎重に行う必要があります。不用意にグローバル変数を変更すると、予期しない箇所でスタイルの不具合が起こる可能性があります。
- コードの可読性: !global を多用すると、どの変数がグローバルで影響を与えているのか追跡しにくくなることがあります。適切なコメントやドキュメントを残すことで、この問題を緩和できます。
まとめ 知識を知っておくと後で思い出せる
今回はSassについて書籍「Sassの教科書」で学んだ便利な機能について紹介しましたが、書籍で学んだ内容はこれだけではありません。後日、「現場で使える実践的なテクニック」についても紹介する予定です。
今回学んだ知識の中には初学者である私には、まだ使いこなせないものもあると思います。
それでも、知っていれば後から調べて実装することが可能です。
将来現場で使用できるように、今は学習によりインプットとアウトプットを繰り返して知識を増やしていきたいと思います。
以上で今回の学習記録を終えます。
ここまでご覧いただきありがとうございました。
コメント