やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

メディアクエリでCSS変数の初期値を振り分ける

 「1行あたりの字数」をCSS変数で定義し、スマホ20タブレット30、PC40にする。

成果物

概要

メディアクエリ

 CSSのメディアクエリでディスプレイの解像度に応じて分岐させる。

いくつ分岐させるべきか

 今回はスマホタブレット、PCの3つに分ける。

 最低でもPCとスマホは分けたい。あまりにも大きさが違うためレイアウト崩壊するから。

 細かくいうと無数に分類したくなる。たとえばアスペクト比、デバイスピクセル比、縦置き/横置き、対応APIなどデバイスや状態による差異を吸収した適切な表示を提供したい。けれどそれらを追求しだすと永久に終わらず、膨大な作業量となってしまう。そこで今回は大雑把に、スマホタブレット、PCの3つを解像度によって分けるだけにとどめる。

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

 メディアクエリの書き方は「PCファースト」と「モバイルファースト」に大別される。ここでは本と同じ表示を再現しやすい大型ディスプレイをベースに設計したいため、PCファーストを選択する。大きいサイズを上から順に書いていく。詳細はコード抜粋を参照。

基準値

 デバイスによって解像度が異なる。明確な閾値はない。目安をググると以下のデータが見つかった。概算にすぎないが、これを基準値とする。

横幅 px
スマホ(最小) 320
タブレット(最小) 600
タブレット(最大) 1024

コード抜粋

@charset "utf-8";
/* PC 13〜21インチ 1025px〜 */
:root {
    --line-of-chars:40;
}
/* タブレット 7〜13インチ 600〜1024px */
@media screen and (max-width: 1024px) {
:root {
    --line-of-chars:30;
}
}
/* スマホ 4〜7インチ 1〜599px  */
@media screen and (max-width: 599px) {
:root {
    --line-of-chars:20;
}

body {
    font-size: calc(100vw / (var(--line-of-chars)));
}

 なお、CSSファイルを分割することもできる。

<link rel='stylesheet' media='screen and (max-width: 599px)' href='css/smartphone.css' />
<link rel='stylesheet' media='screen and (max-width: 1024px)' href='css/tablet.css' />
<link rel='stylesheet' media='screen and (min-width: 1025px)' href='css/desktop.css' />

PCでスマホ再現する

 Chromiumならデベロッパーツールを使う。Ctrl+Shift+Iで表示する。コンボボックスからGalaxy S5などのデバイス名を選ぶと、そのサイズが再現される。これでメディアクエリのテストができる。

所感

 なーんか冗長なんだよなぁ。どの書き方をしてもDRYに書けない。重複しまくる。私は以下のように書きたい。

line-of-chars() {
    switch @max-width {
        599px => 20,
        1024px => 30,
        _ => 40
    }
}
body {
    font-size: calc(100vw / line-of-chars());
}

 もっと言えば以下くらい縮めたい。

body {
    font-size: 100vw / switch @max-width {
        599px => 20,
        1024px => 30,
        _ => 40
    };
}

 これなら1ファイルで済むし、サイズ分岐コードも1属性あたり1箇所で済む。まあ、こんな書き方はできないのだが。

 ググってみるとSassなどでは関数定義できるらしい。でもC#のパターンマッチswitch式のようには書けないし、そもそもCSS標準だけで実装したいんだよなぁ。

 レスポンシブ対応をもっと簡単にサクッと書きたい。これが中々難しい。調べると必然的に複雑化するためHTMLやCSSが汚くなるようだ。任意にブレイクポイントを決めることができて、自動的にそれに対応したコンテンツ(変数や画像ファイル)を選択してくれるようなフレームワークって無いの? 画像や動画があるならアスペクト比も考慮したいし。

横幅 任意変数値 画像/動画パス
〜599 20 {}-320x240
〜1024 30 {}-640x480
〜1279 40 {}-1024x768
〜1919 40 {}-1280x720
1920〜 40 {}-1920x1080

 そもそもレスポンシブ対応自体が面倒くさい。さらにいうと、スマホは通信量が従量制か上限ありなのでWebサイトをキャッシュしたくなることがある。タッチイベントの実装とかもあるし。デバイスごとの都合があまりに多岐にわたるため、考慮すべきことが多すぎて頭がパンクしそうになる。技術の進歩が早すぎる。SPAなどの概念が次々と出てくる。というわけで技術調査と、機能の洗い出しと、それを実装する/しないを決定するだけでも熟慮が必要であり、考えるだけでも多大な負担を強いられるのである。なのにスマホが普及したせいで必須の作業なのだ。苦行か?

対象環境

$ uname -a
Linux raspberrypi 5.4.51-v7l+ #1333 SMP Mon Aug 10 16:51:40 BST 2020 armv7l GNU/Linux