Sassのメディアクエリmixinの決定版ライブラリ「Sass MQ」
以前、Sassの変数(Map)とmixinでメディアクエリを管理する記事を書きました。
Sassの変数とmixinで変更に強いメディアクエリをつくる
単純なmixinで導入はしやすいですが、min-width
とmax-width
のどちらも使いたい場合は変数とmixinを増やす必要があったり、@media (min-width: 768px) and (max-width: 1023px)
のような条件には対応していませんでした。
「Sass MQ」はこれらの機能を備えている高機能で軽量なライブラリです。
「inuitcss」で採用されていたり、「Sass Guidelines」で紹介されていたりしています。GitHubで1578のスターも付けられています(記事執筆時点)。
Sass MQをインストールする
npm・yarn・Bowerからインストールできます。
bower install sass-mq --save
npm install sass-mq --save
yarn add sass-mq
_mq.scssのようにパーシャルファイルを作成して、How to use itに用意されているテンプレートをペーストして設定をしていきます。
他の変数ファイルの前後でインポートしておきます。
// To enable support for browsers that do not support @media queries,
// (IE <= 8, Firefox <= 3, Opera <= 9) set $mq-responsive to false
// Create a separate stylesheet served exclusively to these browsers,
// meaning @media queries will be rasterized, relying on the cascade itself
$mq-responsive: true;
// Name your breakpoints in a way that creates a ubiquitous language
// across team members. It will improve communication between
// stakeholders, designers, developers, and testers.
$mq-breakpoints: (
mobile: 320px,
tablet: 740px,
desktop: 980px,
wide: 1300px,
// Tweakpoints
desktopAd: 810px,
mobileLandscape: 480px
);
// Define the breakpoint from the $mq-breakpoints list that should
// be used as the target width when outputting a static stylesheet
// (when $mq-responsive is set to 'false').
$mq-static-breakpoint: desktop;
// If you want to display the currently active breakpoint in the top
// right corner of your site during development, add the breakpoints
// to this list, ordered by width. For example: (mobile, tablet, desktop).
$mq-show-breakpoints: (mobile, mobileLandscape, tablet, desktop, wide);
// If _mq.scss is in your project:
@import 'path/to/mq';
// With eyeglass:
@import 'sass-mq';
// With webpack (and boilerplates such as create-react-app)
@import '~sass-mq';
下記もsass-mqのインポートの前に設定しておくといいかなと思います。
/// Base font size on the `<body>` element
/// @type Number (unit)
$mq-base-font-size: 16px !default;
/// Customize the media type (for example: `@media screen` or `@media print`)
/// By default sass-mq uses an "all" media type (`@media all and …`)
///
/// @type String
/// @link https://github.com/sass-mq/sass-mq#changing-media-type Full documentation and examples
$mq-media-type: all !default;
ここから6つの変数とインポート方法について説明します。
詳しい仕様は公式サイトのVariablesを確認してください。
$mq-base-font-size
/// Base font size on the `<body>` element
/// @type Number (unit)
$mq-base-font-size: 16px !default;
ルート要素のフォントサイズを10px
にしている場合などは$mq-base-font-size: 10px !default;
にします。デフォルトは16px
です。
$mq-media-type
/// Customize the media type (for example: `@media screen` or `@media print`)
/// By default sass-mq uses an "all" media type (`@media all and …`)
///
/// @type String
/// @link https://github.com/sass-mq/sass-mq#changing-media-type Full documentation and examples
$mq-media-type: all !default;
メディアクエリの条件を@media print, screen and (min-width: 768px)
のようにしている場合は$mq-media-type: print, screen !default;
のようにします。デフォルトはall
です。
$mq-responsive
// To enable support for browsers that do not support @media queries,
// (IE <= 8, Firefox <= 3, Opera <= 9) set $mq-responsive to false
// Create a separate stylesheet served exclusively to these browsers,
// meaning @media queries will be rasterized, relying on the cascade itself
$mq-responsive: true;
メディアクエリに対応していない古いブラウザ用の設定です。基本的にtrue
のままで大丈夫です。
$mq-breakpoints
// Name your breakpoints in a way that creates a ubiquitous language
// across team members. It will improve communication between
// stakeholders, designers, developers, and testers.
$mq-breakpoints: (
mobile: 320px,
tablet: 740px,
desktop: 980px,
wide: 1300px,
// Tweakpoints
desktopAd: 810px,
mobileLandscape: 480px
);
ブレイクポイントのpx値と、keyになるキーワードを設定します。
このpx値がmin-width
として使用され、max-width
の時は0.01em引いた数値が自動で計算されます。
keyはsp
やpc
でもいいですし、sm
やmd
(SmallとMedium)などでもOKです。チームメンバーと相談をして、ユビキタス言語(同意を得た用語)を設定してくださいと説明されています。
個人的にデバイスではなく、相対的な名前をよく使っているので、以下のようにしています。
$mq-breakpoints: (
sm: 375px,
md: 768px,
lg: 1024px,
xl: 1440px,
);
$mq-static-breakpoint
// Define the breakpoint from the $mq-breakpoints list that should
// be used as the target width when outputting a static stylesheet
// (when $mq-responsive is set to 'false').
$mq-static-breakpoint: desktop;
$mq-responsive
をtrue
にしている場合は、変更の必要は必要ありません。
$mq-show-breakpoints
// If you want to display the currently active breakpoint in the top
// right corner of your site during development, add the breakpoints
// to this list, ordered by width. For example: (mobile, tablet, desktop).
$mq-show-breakpoints: (mobile, mobileLandscape, tablet, desktop, wide);
Sass MQではブレイクポイントをmq-px2em()
でpxからemに変換されています。デベロッパーツールでブレイクポイントのpx値が判断しにくい場合は、$mq-show-breakpoints: (sm, md, lg, xl);
のようにkeyを渡すとbody
セレクタにCSSが追加されて、画面の右上にmd ≥ 768px (48em)
のようなラベルが表示されるようになります。
以下は出力されるCSSのサンプルです。
body:before {
background-color: #fcf8e3;
border-bottom: 1px solid #fbeed5;
border-left: 1px solid #fbeed5;
color: #c09853;
font: small-caption;
padding: 3px 6px;
pointer-events: none;
position: fixed;
right: 0;
top: 0;
z-index: 100
}
@media (min-width:23.4375em) {
body:before {
content: "sm ≥ 375px (23.4375em)"
}
}
@media (min-width:48em) {
body:before {
content: "md ≥ 768px (48em)"
}
}
@media (min-width:64em) {
body:before {
content: "lg ≥ 1024px (64em)"
}
}
@media (min-width:90em) {
body:before {
content: "xl ≥ 1440px (90em)"
}
}
@import
// If _mq.scss is in your project:
@import 'path/to/mq';
// With eyeglass:
@import 'sass-mq';
// With webpack (and boilerplates such as create-react-app)
@import '~sass-mq';
テンプレートの上記の箇所で、Sass MQをインポートする3つの方法があげられています。
- ローカルのnode_modulesのファイルをインポートする(
@import 'path/to/mq';
) - eyeglassというツールを使ってインポートする(
@import 'sass-mq';
) - webpackの記法でインポートする(
@import '~sass-mq';
)
いずれかの方法でインポートします。使わないものは削除してしまって大丈夫です。
ここではローカルのファイルを相対パスでインポートしています。
@import "../../../../../node_modules/sass-mq/_mq.scss";
Sass MQの機能
Sass MQはいくつかのfunctionとmixinのライブラリですが、ここではメディアクエリのmixinであるmq()
の使い方を説明します。
詳しい仕様は公式サイトのmq()を確認してください。
4つの引数($from
、$until
、$and
、$media-type
)の組み合わせによって出力が変わります。使う頻度が少なそうなので、今回は$and
の使い方は載せていません。
Name | parameterDescription | parameterType | parameterDefault value |
---|---|---|---|
$from |
(false) - One of $mq-breakpoints | String or Boolean |
—none |
$until |
(false) - One of $mq-breakpoints | String or Boolean |
—none |
$and |
(false) - Additional media query parameters | String or Boolean |
—none |
$media-type |
($mq-media-type) - Media type: screen, print… | String |
— |
$from
はmin-width
、$until
はmax-width
と読み替えてください。
$from
と$until
の「parameterDescription」を見ると、初期値はfalse
になっていることが分かります(実際のコードはこちら)。$from
か$until
、あるいは両方を指定することで出力も変わります。
($from: md)
md
をmin-width
で出力($until: md)
md
を(0.01em引いた)max-width
で出力($from: md, $until: lg)
md
のmin-width
とlg
のmax-width
をand
で繋げて出力
@media (min-width: em)
Sass MQはモバイルファーストで設計されているので、min-width
の場合は第一引数にkeyを渡すだけです($from: md
などとする必要はありません)。
.min-width {
@include mq(md) {
content: "@media (min-width:48em)";
}
}
@media (min-width: 48em) {
.min-width {
content: "@media (min-width:48em)"
}
}
@media (max-width: em)
max-width
の場合は、mq($until: md)
のように$until
に直接渡すか、mq(false, md)
のようにして第二引数に渡します。
.max-width {
@include mq($until: md) {
content: "@media (max-width:47.99em)";
}
}
.max-width {
@include mq(false, md) {
content: "@media (max-width:47.99em)";
}
}
@media (max-width:47.99em) {
.max-width {
content: "@media (max-width:47.99em)"
}
}
@media (min-width: em) and (max-width: em)
以上と未満を組み合わせる場合は、第一引数に「以上」を、第二引数に「未満」を渡します。
下記のmq(md, lg)
は引数の順番を変えていないので、mq($from: md, $until: lg)
と指定しているのと同じことになります。
.min-and-max-width {
@include mq(md, lg) {
content: "@media (min-width:48em) and (max-width:63.99em)";
}
}
@media (min-width:48em) and (max-width:63.99em) {
.min-and-max-width {
content: "@media (min-width:48em) and (max-width:63.99em)"
}
}
@media print、@media screen and (-ms-high-contrast: active), print
印刷時や、印刷時とハイコントラストモードの場合は$media-type
に条件を直接渡します。
.print {
@include mq($media-type: "print") {
content: "@media print";
}
}
.screen-and-high-contrast-and-print {
@include mq($media-type: "screen and (-ms-high-contrast: active), print") {
content: "@media screen and (-ms-high-contrast:active), print";
}
}
@media print {
.print {
content: "@media print"
}
}
@media screen and (-ms-high-contrast:active), print {
.screen-and-high-contrast-and-print {
content: "@media screen and (-ms-high-contrast:active), print"
}
}
emではなくpxを使うには
PX, EM or REM Media Queries?という記事で検証されているように、メディアクエリの単位はemを使うことがベターとされています。
検証結果は以下のようなものでした。
- pxは、ズームしている時とユーザーがフォントサイズを変更している時にSafariでズレる。
- remは、
html { font-size: 200%; }
などとした時にSafariでズレる(モバイルも含む)。
Sass MQもそれにならってpxではなくemを使っています。どうしてもpxを使いたい場合は、emの代わりにpxを使用しているforkを使うことを推奨しています(Issueはこちら)。