スマートなメディアクエリ!少ない記述でブレイクポイントを設定しよう!!【SASSモジュール】

今回はSASSを使ってメディアクエリを作成していきます! メディアクエリはレスポンシブサイトには欠かせない存在となっていますが、記述が長い!! しかも、ブレイクポイントの数値を忘れてしまうと他のページから数値をピックアップして...。 と、そんな扱いが面倒なメディアクエリを[sp]や[pc] [tb]などの引数だけで制御できるようにしていきましょう!

はじめに(やりたいこと)

今回やりたいことは記述量の多い「通常のメディアクエリ」を記述量が少ない「スマートなメディアクエリ」にしていきます。
最終系も載せておくので、ぜひ盗んでいってください~

通常のメディアクエリ

// PCのとき
p
	font-size: 16px
	// TBのとき
	@media screen and (max-width: 1023px) and (min-width: 639px)
		p
			font-size: 14px
	// SPのとき
	@media screen and (max-width: 640px)
		p
			font-size: 12px

スマートなメディアクエリ

// PCのとき
p
	font-size: 16px
	// TBのとき
	+media_device('tb')
		p
			font-size: 14px
	// SPのとき
	+media_device('sp')
		p
			font-size: 12px

記事書いてて思ったけど・・・。

めっちゃ楽!!!

そして、最終系は↓↓になります。

_core.sass

$devices: "pc", "tb", "sp"
$break_point: 1023px, 640px

_module.sass

@import "./core"
=media_device($device)
	@for $i from 2 through length($devices)
		@if $device==nth($devices, $i)
			@if $i==length($devices)
				@media screen and (max-width: nth($break_point, length($break_point)))
					@content
			@else
				@media screen and (min-width: #{nth($break_point, $i) - 1px}) and (max-width: #{nth($break_point, $i - 1)})
					@content

ソースコードの解説

それでは、ソースコードの解説をしていきましょう!
まずは「_core.sass」の方を見ていきます。
「_core.sass」は色やコンテンツ幅などを定義するためのファイルになります。
ちなみにファイル名は何でもOKです!

今回はデバイスの種類を定義する$devicesと各デバイスのブレイクポイントとなる$break_pointを定義します。

_core.sass

$devices: "pc", "tb", "sp"
$break_point: 1023px, 640px

この例では対応デバイスの種類を「パソコン(pc)」「タブレット(tb)」「スマホ(sp)」の3つとしておきます。
デバイスが3つになるので、ブレイクポイントは2つになります。
仕様としては以下のようにしておきます。

  • PC:1024px ~
  • TB:641px ~ 1023px
  • SP:0px ~ 640px

$devicesには各デバイス名を定義します。
もちろん、デバイス名は何を指定してもOKです!
このデバイス名が関数を呼び出す際の引数になります。

$break_pointにはブレイクポイントを設定します。

_module.sass

次に「_module.sass」を解説していきます。

// 定義ファイルの読み込み
@import "./core"
// 関数の定義
=media_device($device)
	// 定義したデバイス分だけループ
	@for $i from 2 through length($devices)
		// 引数で受け取ったデバイス名と定義したデバイス名が一致した場合
		@if $device==nth($devices, $i)
			// デバイスが最後の場合
			@if $i==length($devices)
				// max-widthのみの形にする
				@media screen and (max-width: nth($break_point, length($break_point)))
					@content
			// デバイスが最後以外の場合
			@else
				// min-widthとmax-widthの形にする
				@media screen and (min-width: #{nth($break_point, $i) - 1px}) and (max-width: #{nth($break_point, $i - 1)})
					@content

各行にコメントを加えてみましたー。
大まかな流れを説明すると下のような感じになります。

  1. 先ほど定義した「_core.sass」の$devices配列をループする
    最初のデバイスはメディアクエリを適用する必要がないのでループは2から始めます
  2. 関数を呼び出す時に渡した引数($device)と定義している文字列が一致したときメディアクエリを適用する
  3. この時、$devicesの配列が最後だったらメディアクエリを「max-width」のみにする

それでは各処理ごとに説明します!

// 定義ファイルの読み込み
@import "./core"

先ほど設定した「_core.sass」を読み込んでいます。

// 関数の定義
=media_device($device)

関数名を定義しています。
私の場合は「media_device」にしていますが、ここは好きな名前でOKです!
引数には先ほど「_core.sass」の$devicesで設定した文字列のいずれかが入る想定です。

// 定義したデバイス分だけループ
@for $i from 2 through length($devices)

ここのfor文は$devicesの分だけループします。
ただし、CSSの構造上、一番最初のデバイスにメディアクエリを適用する必要はないので2つ目のデバイスからループさせています。

// 引数で受け取ったデバイス名と定義したデバイス名が一致した場合
@if $device==nth($devices, $i)

ここのif文は「引数」と「定義されてる値」が一致したときに処理を実行するようにしています。
この引数が渡されたらこのブレイクポイントにするという処理になります。
ちなみに、もし一致しなければ何も出力されない感じになりますね!

// デバイスが最後の場合
@if $i==length($devices)
	// max-widthのみの形にする
	@media screen and (max-width: nth($break_point, length($break_point)))
		@content
// デバイスが最後以外の場合
@else
	// min-widthとmax-widthの形にする
	@media screen and (min-width: #{nth($break_point, $i) - 1px}) and (max-width: #{nth($break_point, $i - 1)})
		@content

これで最後になります!
ここでのif文はデバイスの配列が最後だったらメディアクエリを「max-width」のみの形にします。
「max-width: XXXpx」の形にすれば適用範囲は実質0px ~ XXXpxのデバイス幅になります。

そして、@mediaでは$iの値を使って$break_pointからブレイクポイントの値を参照しています。
今回のコードでは「_core.sass」で定義したブレイクポイントを「max-width」に充てるような形にしてます。
この@mediaを弄れば仕様を変えることができるので、変えたい場合はぜひ変えちゃってください~

以上で解説は終わりになります!
SASSの連想配列なんか使えばもっとオシャレに実装できそうですが、今回はここまでにしようかなーって思います!

最後までありがとうございました!!!