定義しておくべき基本的なCSS変数とその命名規則

ウェブデザインに一貫性と統一感を持たすためには、設計段階でCSS変数 (CSSカスタムプロパティ) を定義しておき、イレギュラーな値を極力使用しないというアプローチが良いかと思います。

今回は、個人的に定義しているCSS変数を紹介してみようと思います。

CSS変数を定義する際に注意した点

CSS変数で定義すべき値は、プロパティの値に large, small といったキーワードが用意されていないけど繰り返し使用する値、もしくは、キーワードはあるものの独自に定義しておきたい値などです。

値のバリエーションが複数あるものは、後から追加したCSS変数と混ざらないように、接頭辞 (プレフィクス) を付けるようにしています。「なにが」「どうなるのか」を明確に分けるためにアンダーバー (_) を使って「--[なにが]_[どうなるのか]」のように定義しています。この「--[なにが]_」が接頭辞になります。

繰り返し使用するCSS変数なので、「どうなるのか」の部分は可能な限り短くしています。例えば、「x-large」は「xl」、「x-small」は「xs」、「extra-low」は「el」、「extra-high」は「eh」のようにしています。

一方で、「--[なにが]_1」「--[なにが]_2」のように数字で表すのは避けています。「どうなるのか」が最大何パターンあって、その数字がどの程度なのか推測しにくいためです。数字を使う場合は、0-10 や 0-100 といった割合やパーセンテージに限定すべきだと思います。

フォント

font-familyプロパティで使用するCSS変数で、「--font_」という接頭辞で定義しています。この定義例ではHTMLの各要素の既定値として使用するフォントを設定しています。

/* 定義例 */
:root {
  --font_serif: "Hiragino Mincho ProN", "Noto Serif CJK JP", "Noto Serif JP", ui-serif, serif;
  --font_sans: "Hiragino Sans", "Hiragino Kaku Gothic ProN", "Noto Sans CJK JP", "Noto Sans JP", ui-sans-serif, sans-serif;
  --font_mono: "Noto Sans Mono CJK JP", "Noto Sans Mono JP", ui-monospace, monospace;
  --font_default: var(--font_sans);
}

/* 使用例 */
html {
  font-family: var(--font_default);
}
blockquote {
  font-family: var(--font_serif);
}
pre, code, samp, kbd {
  font-family: var(--font_mono);
}

フォントサイズ

font-sizeプロパティで使用するCSS変数で、この定義例では親要素との相対的なフォントサイズになります。

文字のサイズ (1em) を設定するので「--em_」 という接頭辞を使い、見出しサイズと汎用サイズの2種類を定義しています。汎用サイズはfont-sizeプロパティのキーワード値にならい、xxs から xxxl までの計8サイズを用意しています。

/* 定義例 */
:root {
  /* 見出しサイズ */
  --em_h1: calc(1em * 12 / 6);
  --em_h2: calc(1em * 12 / 7);
  --em_h3: calc(1em * 12 / 8);
  --em_h4: calc(1em * 12 / 9);
  --em_h5: calc(1em * 12 / 10);
  --em_h6: calc(1em * 12 / 11);

  /* 汎用サイズ */
  --em_xxs: calc(1em * 6 / 9); /* Double Extra Small */
  --em_xs: calc(1em * 6 / 8); /* Extra Small */
  --em_s: calc(1em * 6 / 7); /* Small */
  --em_m: calc(1em * 6 / 6); /* Medium */
  --em_l: calc(1em * 6 / 5); /* Large */
  --em_xl: calc(1em * 6 / 4); /* Extra Large */
  --em_xxl: calc(1em * 6 / 3); /* Double Extra Large */
  --em_xxxl: calc(1em * 6 / 2); /* Triple Extra Large */
}

/* 使用例 */
h1 {
  font-size: var(--em_h1);
}
h2 {
  font-size: var(--em_h2);
}
h3 {
  font-size: var(--em_h3);
}
h4 {
  font-size: var(--em_h4);
}
h5 {
  font-size: var(--em_h5);
}
h6 {
  font-size: var(--em_h6);
}
small {
  font-size: var(--em_s);
}
rt, rp, sub, sup {
  font-size: var(--em_xs);
}

余白

border-spacingプロパティ、row-gapプロパティ、column-gapプロパティ、marginプロパティ、paddingプロパティなどで使用するCSS変数です。

 ,  ,   といった文字実体参照で馴染みのある、スペース (space) を意味する「--sp_」という接頭辞で定義しています

参考: 余白 (デジタル庁)

/* 定義例 */
:root {
  --sp_xxs: calc(1rem / 8); /* Double Extra Small */
  --sp_xs: calc(1rem / 4); /* Extra Small */
  --sp_s: calc(1rem / 2); /* Small */
  --sp_m: 1rem; /* Medium */
  --sp_l: calc(1rem * 2); /* Large */
  --sp_xl: calc(1rem * 4); /* Extra Large */
  --sp_xxl: calc(1rem * 8); /* Double Extra Large */
}

/* 使用例 */
* {
  margin: 0;
}
article, section, nav, aside, h1, h2, h3, h4, h5, h6, hgroup, header, footer, address,
p, hr, pre, blockquote, ol, ul, menu, dl, figure, main, search, div:where([class], [style]),
table, form, fieldset, details {
  &:where(& ~ *) {
    margin-block-start: var(--sp_l);
  }
  :is(article, section, nav, aside, h1, h2, h3, h4, h5, h6, hgroup, header, footer, hr, main):where(& ~ *) {
    margin-block-start: var(--sp_xl);
  }
  :is(article, section, nav, aside, header, footer, hr, main):where(:has(~ &)) {
    margin-block-end: var(--sp_xl);
  }
}
button {
  padding-block: var(--sp_s);
  padding-inline: var(--sp_l);
}

不透明度・混合量

opacityプロパティ、rgb関数やhsl関数のアルファチャネルの透過値、color-mix関数の混合量などで使用するCSS変数です。

opacityプロパティの値とアルファチャネルの透過値は共に alpha-value に分類される値を使用することから「--alpha_」という接頭辞で定義しています。color-mix関数で使用できるよう percentage で設定しています。

/* 定義例 */
:root {
  --alpha_el: 10%; /* Extra Low */
  --alpha_l: 30%; /* Low */
  --alpha_m: 50%; /* Middle */
  --alpha_h: 70%; /* High */
  --alpha_eh: 90%; /* Extra High */
}

/* 使用例 */
mark {
  background: color-mix(in srgb, transparent, var(--yellow) var(--alpha_m));
  color: inherit;
}
:is(input, button, select, textarea):where(:disabled) {
  opacity: var(--alpha_m);
}

エレベーション

box-shadowプロパティで使用するCSS変数で、要素の視覚的な高度になります。高度が低い (Low) と影は小さくなり、高い (High) と影は大きくなります。エレベーション (Elevation) を略した「--elev_」という接頭辞で定義しています。

参考: エレベーション (デジタル庁)

/* 定義例 */
:root {
  --elev_el: 0 0.0625rem 0.25rem -0.125rem; /* Extra Low */
  --elev_l: 0 0.125rem 0.5rem -0.25rem; /* Low */
  --elev_m: 0 0.25rem 1rem -0.5rem; /* Middle */
  --elev_h: 0 0.5rem 2rem -1rem; /* High */
  --elev_eh: 0 1rem 4rem -2rem; /* Extra High */
}

/* 使用例 */
button:where(:not(:active)):where(:hover, :focus-visible) {
  box-shadow: var(--elev_m) var(--black);
}

線の幅

border-widthプロパティ、outline-widthプロパティなどで使用するCSS変数です。

線の幅は line-width に分類される値を使用することから「--line_」という接頭辞で定義し、幅は万年筆の太さを表す Fine (細), Medium (中), Broad (太) で表しています。

/* 定義例 */
:root {
  --line_ef: 0.0625rem; /* Extra Fine */
  --line_f: 0.125rem; /* Fine */
  --line_m: 0.25rem; /* Medium */
  --line_b: 0.5rem; /* Broad */
  --line_eb: 1rem; /* Extra Broad */
}

/* 使用例 */
button {
  border: solid var(--line_ef);
}

半径

border-radiusプロパティで使用するCSS変数で、半径を意味する「--radius_」という接頭辞で定義しています。

参考: 角の形状 (デジタル庁)

/* 定義例 */
:root {
  --radius_xs: 0.125rem; /* Extra Small */
  --radius_s: 0.25rem; /* Small */
  --radius_m: 0.5rem; /* Medium */
  --radius_l: 1rem; /* Large */
  --radius_xl: 2rem; /* Extra Large */
  --radius_max: calc(1px * infinity);
}

/* 使用例 */
button {
  border-radius: var(--radius_m);
}

colorプロパティ、background-colorプロパティ、border-colorプロパティ、box-shadowプロパティなどで使用するCSS変数です。

良く使用される赤, 黄, 緑, 青, 灰, 黒, 白の7色を基本色として定義しています。使用するプロパティ毎に色を用意すると膨大な数になり、メンテナンス性が損なわれるため、基本色をlight-dark関数とcolor-mix関数を組み合わせてバリエーションを増やしています。

/* 定義例 */
:root {
  /* 基本色: 主に文字色・ボーダー色で使用 */
  --red: #f65;
  --yellow: #c80;
  --green: #3a0;
  --blue: #58f;
  --gray: #909090;
  --black: #202020;
  --white: #fff;

  /* color-schemeプロパティで反転する黒と白: 主にcolor-mix関数の下地色で使用 */
  --black-white: light-dark(var(--black), var(--white));
  --white-black: light-dark(var(--white), var(--black));

  /* 薄い文字色: 主にform要素内のボーダー色・placeholder属性・disabled属性で使用 */
  --pale: color-mix(in srgb, var(--white-black), currentcolor var(--alpha_h));
  --paler: color-mix(in srgb, var(--white-black), currentcolor var(--alpha_m));
  --palest: color-mix(in srgb, var(--white-black), currentcolor var(--alpha_l));

  /* 薄い基本色: 主に背景色で使用 */
  --palest-red: color-mix(in srgb, var(--white-black), var(--red) var(--alpha_l));
  --palest-yellow: color-mix(in srgb, var(--white-black), var(--yellow) var(--alpha_l));
  --palest-green: color-mix(in srgb, var(--white-black), var(--green) var(--alpha_l));
  --palest-blue: color-mix(in srgb, var(--white-black), var(--blue) var(--alpha_l));
  --palest-gray: color-mix(in srgb, var(--white-black), var(--gray) var(--alpha_l));
}

/* 使用例 */
p.danger {
  background: var(--palest-red);
  border: solid var(--line_m);
  border-radius: var(--radius_m);
  color: var(--red);
  padding: var(--sp_m);
}

汎用的なCSS変数は、作り手の設計思想やスタンスなどが色濃く反映される部分だと思います。Open Props というCSS変数のフレームワークがありますが、自分とは異なった考え方で作られているなと感じます。

関連記事