やってみる

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

CSSでグローバル変数を定義する(CustomProperty)

 CSSで変数を使いたいときはカスタムプロパティを使おう。

成果物

情報源

目的・背景

 横書きのとき、1行あたりの字数を変数で指定したい。

 日本語では40字/行が適切だ。作文用紙がそうだし、文庫本でも大凡そのとおりだから。けれどスマホなど物理ディスプレイのサイズが小さいときは文字が小さくなりすぎて読めなくなってしまう。ググってみるとスマホでは最大20字が目安とあった。そこで環境により、1行あたりの字数を変数にしたかった。物理サイズが大きいときは40字/行、小さいときは20字/行などにすると、デバイスごとに見やすい大きさに調整できるだろう。

カスタムプロパティ

 --line-of-charsという変数を定義・参照した例。

style.css

@charset "utf-8";
:root {
    --line-of-chars:20;
}
body {
    font-size: calc(100vw / var(--line-of-chars));
}

main.js

window.addEventListener('DOMContentLoaded', (event) => {
    const root = document.querySelector(':root');
    console.log(`before: ${root.style.getProperty('--line-of-chars')}`);
    root.style.setProperty('--line-of-chars', '10');
    console.log(`after: ${root.style.getProperty('--line-of-chars')}`);
});

定義

--変数名: 値;

 上記フォーマットにて任意の変数を定義できる。変数を定義する箇所はCSSセレクタによって決まる。たとえば以下のようにroot疑似クラスを使えば、HTML要素全体に適用される。すなわちグローバル変数となる。

:root {
    --変数名: 値;
}

参照(from CSS

var(--変数名)

計算(from CSS

calc(式)

 たとえばフォントサイズを計算により算出するときは以下。

font-size: calc(100px + 20px);
font-size: calc(2em * 3);
font-size: calc(100vw / var(--line-of-chars));

 詳細はcalc()参照。

単位

 CSSの値と単位参照。

絶対値

単位 名前 概要
cm センチメートル 1cm = 96px/2.54
mm ミリメートル 1mm = 1/10cm
Q クォータミリメートル 1Q = 1/40cm
in インチ 1in = 2.54cm = 96px
pc イカ 1pc = 1/6in
pt ポイント 1pt = 1/72in
px ピクセル 1px = 1/96in

相対値

単位 概要
em 親要素のフォントサイズ
ex その要素のフォントの文字 "x" の高さ
ch その要素のフォントの文字 "0" の幅
rem ルート要素のフォントサイズ
lh その要素のline-hightプロパティと同じ
vw ビューポート幅の 1%
vh ビューポート高さの 1%
vmin ビューポート幅と高さの小さい方の 1%
vmax ビューポート幅と高さの大きい方の 1%

 このうちv系はレスポンシブでよく使う。

ビューポート

 ビューポートとは表示領域である。全画面のときはディスプレイのサイズと同じ。

 単位vwは表示領域の百分率をあらわす。つまり以下のとき、フォントサイズは表示領域の横幅サイズの5%である。100/20=5/1=5%。5%は全体の1/20。つまり、20字/行。1字を横に並べたとき、1行あたり20字が入るサイズになる。

--line-of-chars:20;
font-size: calc(100vw / var(--line-of-chars));

蛇足

1行あたりの字数

 よく1行あたりの字数という単位が欲しくなる。たとえば作文用紙なら1行あたり40字である。日本語において読みやすいのは1行あたり何文字か。25〜45字/行が相場。文庫本A6サイズなら約40字/行。

  • 日本語である
  • ディスプレイ
    • 形式(PDF)
    • 書籍化(文庫本A6などサイズ規格から逆算)

情報源

レスポンシブ

 スマホなどデバイスごとに解像度が異なる。それに応じて適切な配置をしたい。それを「レスポンシブ」と呼ぶ。

viewport

画面拡大できない

index.html

<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no">

画面拡大できる

<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, user-scalable=yes">

@media

@media screen and (max-width: 959px) {
    /* 959px以下に適用されるCSS(タブレット用) */
}
@media screen and (max-width: 480px) {
    /* 480px以下に適用されるCSS(スマホ用) */
}

問題点

 解像度だけでは適切な表示サイズにできない。デバイスによって1インチあたりの画素数が異なるから。画素数はハードウェアやその技術力によって差が出る。一般的に液晶ディスプレイは画素数が多く、紙に印刷するプリンタは画素数が少ない。よってPCを使いディスプレイ上に高解像度の画像データを作成・表示したとしても、同じ大きさの紙に印刷すると画素数が少なくなる。

 また、おなじPC用の液晶ディスプレイであっても古いものは解像度が1024768だが、最近のは19201080だったりする。さらにスマホなどモバイル系デバイスは解像度が低く、PCなど据え置き型は解像度が高い。

 ディスプレイの物理画面サイズは大抵インチで表現される。1インチ=2.54cm。縦横の対角線の長さでインチを測るため、横幅でも縦幅でもない。大抵スマホは7インチ以下である。厄介なことにインチと解像度は比例しない。

物理サイズ|解像度| ---------| 640480 19201080

素数を表す単位にppidpiがある。ディスプレイはppiであり、印刷プリンタはdpiを使う。

 画像は色のついた点(画素)で表現されている。狭い範囲に多数の点を含めることができればキレイ(高画質、高解像度)に表示される。それは液晶ディスプレイ、印刷プリンタ、いずれも同じだ。画像の最小単位は点である。ただしこの点をどう実装するかはそれぞれのハードウェアによって異なる。液晶ディスプレイの点とレーザープリンタの点は、別々の媒体によって実装される。液晶ディスプレイは。それぞれにハードウェアの事情が異なるから、その

 これらは1インチあたり何ピクセル/何ドット打てるか、というものだ。古いディスプレイはこの値が少ない。1インチあたりのピクセルやドット数が少ないと、ギザギザで粗い画面になる。

 ディスプレイの物理画面サイズは大抵インチで表現される。1インチ=2.54cm。縦横の対角線の長さでインチを測るため、横幅でも縦幅でもない。大抵スマホは7インチ以下である。

所感

 

対象環境

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