シンプルで軽量! 新しいCSSリセット「The New CSS Reset」を作成したElad Shechterにインタビュー
Post on:2021年10月28日
CSSの新しい機能:where()
や:not()
、all
プロパティやunset
値やrevert
値などを使用したCSSリセット「The New CSS Reset」の特徴や機能の解説などを作成したElad Shechterに聞いたインタビューを紹介します。
CSSリセットの考え方や現在の扱い方、新しいプロパティや値の使い方・注意点、CSSの記述方法、box-sizing
やlist-sytle
のスタイル、また先日紹介したカスケードレイヤーについてなど、興味深いことばかりです。
An Interview With Elad Shechter on “The New CSS Reset”
by Elad Shechter
下記は各ポイントを意訳したものです。
※当ブログでの翻訳記事は、元サイト様にライセンスを得て翻訳しています。
新しいCSSリセット「The New CSS Reset」
みなさん、こんにちは。
Elad Shechterが、The New CSS Resetという新しいCSSリセットを私に連絡してきました。このプロジェクトはとても興味深いです!
これをみんなと共有する良い方法は、単にプロジェクトを紹介するだけでなく、Eladにいくつか質問することだと思いました。
まずは、The New CSS Resetのコードを紹介します。
【訳者注】当ブログでも紹介しました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
/*** The new CSS Reset - version 1.2.0 (last updated 23.7.2021) ***/ /* ブラウザのUAスタイルシートのすべてのスタイルを削除します、displayは除く */ *:where(:not(iframe, canvas, img, svg, video):not(svg *)) { all: unset; display: revert; } /* box-sizingの優先値 */ *, *::before, *::after { box-sizing: border-box; } /* リストのスタイル(箇条書き・番号)を削除します normalize.cssで使用する場合 */ ol, ul { list-style: none; } /* 画像がコンテナを超えないようにするため */ img { max-width: 100%; } /* テーブルのセル間のスペースを削除します */ table { border-collapse: collapse; } /* Safariのtextarea要素のwhite-spaceプロパティを元に戻します */ textarea { white-space: revert; } |
The New CSS Resetのインタビュー
以下、インタビューです。
こんにちは、Elad!最初に、このプロジェクトの理由を聞きたいと思います。CSSリセットは異なるブラウザ間のデフォルトのスタイル(UAスタイルシート)に存在する差異を一掃し、そこからスタイルを構築することができるため、昔から人気があります。すでに広く使用されているCSSリセットがいくつかありますが、なぜ新しいCSSリセットなのですか?
CSSのリセットについて話すとき、2つのアプローチがあります。
- Nicolas GallagherによるNormalize.cssは、ジェントルなアプローチです。Normalize.cssは、異なるブラウザでの実装の違いを修正しています。
- Eric MeyerによるCSS Resetはハードなアプローチで、
<h1>
から<h6>
などの見出し要素から得られるfont-size
の値や<ul>
や<ol>
などのリスト要素のデフォルトのスタイルなど、ブラウザによる基本スタイルは必要ないとしています。たとえば、リスト要素はセマンティックな意味を持つだけでなく、アクセシビリティやSEOなど他の面でも役立つために使用されています。
参考:
- 2021年、モダンブラウザに適したCSSリセットのまとめ
- 各ブラウザごとのデフォルトのスタイルシート、user agent stylesheetのまとめ -Chrome, Safari, Firefox, Edge
私はNormalize.cssが大好きです。CSS Resetの考え方を好む人でも、どんなプロジェクトにも必要なものだと思います。
なぜ、Normalize.cssが重要なのか。Normalize.cssは、CSS Resetが触れないシャドウDOM要素に触れています。Normalize.cssを見ると、::-moz-focus-inner
や::-webkit-file-upload-button
などの特別な擬似クラスがあります。非常に多くのベースがカバーされており、だからこそNormalize.cssはどんなプロジェクトにも必要なものだと私は信じています。
私はハードなCSS Resetも大好きです。ほとんどの場合、ブラウザの基本スタイルは必要ないと思います。もし特定の場所で必要な場合は、必要に応じて定義すればいいのです。このことから、私はNormalize.cssとCSS Resetの両方を組み合わせて使用しています。つまり、Normalize.cssが最初にロードされ、次にハードなCSS Resetがロードされます。
では、なぜ新しいCSSリセットが必要なのか。
これまでのCSSリセットは、CSSの古い機能をベースに作られていました。しかしここ数年で、CSSでリセットするために特別に作られた新機能を手に入れることができました。これにより、この新しい最先端のCSSの機能を使用して、より有効なCSSリセットを作成できるのではないかと考えました。
重要なのは、最初のルールセットだと思います。最初のプロパティと値all: unset;
から始めましょう。The New CSS ResetでこのCSSが重要な役割を果たしているのですね。これはどのように機能するのでしょうか?
all
プロパティは、CSSに存在するすべてのプロパティを一度にリセットできるため、最も例外的なCSSプロパティです。
all
プロパティではいくつかのキーワードが使用できます。基本的なものはinitial
とinherit
で、よりスマートなものとしてはunset
とrevert
があります。all: unset;
が何をするのかを理解するためには、CSSのプロパティの基本的なビヘイビアを理解する必要があります。
CSSのプロパティには、2つのグループがあります。
- 継承されるプロパティ: これらのプロパティはデフォルトで継承されるプロパティで、主にタイポグラフィのプロパティです。
- 継承されないプロパティ: これらのプロパティはデフォルトでは継承されない他のすべてのプロパティで、例えば、
padding
、border
、margin
を含むBox Modelのプロパティです。
リセットしようとしたときに、タイポグラフィのプロパティのように継承されたビヘイビアを維持したいとします。そこで、inherit
キーワード値を使用することができます。
1 2 3 4 |
/* 親要素の値から値を取得します */ font-size: inherit; line-height: inherit; color: inherit; |
継承されないプロパティのグループの他のプロパティについてはほとんどの場合、それぞれの初期値を取得したいと考えています。初期値キーワードは、プロパティごとに計算方法が異なることに注意してください。
1 2 3 |
max-width: initial; /* = none */ width: initial; /* auto */ position: initial; /* = static */ |
initial
(継承)とinherit
(初期化)のキーワードを理解した上で、すべてのプロパティをまとめてリセットしたい場合は、all
プロパティで直接リセットできないことがわかりました。なぜなら、すべてのプロパティを初期値、つまりall: initial;
でリセットしてしまうと、継承されたプロパティグループの固有のビヘイビアが失われてしまうからです。また、すべてのプロパティをinherit
値でリセットしたとします。この場合、すべてのプロパティが継承されてしまいます。Box Modelプロパティも含まれてしまい、これは避けたいものです。
そのためにunset
値があります。unset
は、そのタイプに応じてプロパティをリセットします。継承されたプロパティに使用すればinherit
と同じになり、継承されていないプロパティに使用すればinitial
と同じになります。
1 2 |
max-width: unset; /* = initial = none */ font-size: unset; /* = inherit = get parent element value */ |
ここで話をThe New CSS Resetの機能に戻します。
all: unset;
が何をしているかは、継承されたプロパティをすべてinherit
値にリセットし、継承されていないプロパティはすべてinitial
値にリセットしています。
これにより、ブラウザが追加しているデフォルトのUAスタイルシートのスタイルがすべて削除されます。このCSSの新しい機能は、すべてのHTML要素に対してたった1つの操作で実行できるのです。
1 2 3 4 5 6 7 8 |
/* すべてをリセットします: - 継承されたプロパティには、inherit値 - 継承されていないプロパティには、initial値 */ * { all: unset; } |
all: unset;
の次にdisplay: revert;
が定義されていますが、all: unset;
はdisplay
プロパティに望ましくない影響を与えるのでしょうか?
簡単に言うと、イエスです。display
プロパティはUAスタイルシートから取得したい基本構造を表します。ほとんどのプロパティで見たようにunset
値は優れた仕事をしてくれるので、1回の操作ですべてのプロパティをリセットします。
ここでrevert
キーワード値がdisplay
プロパティに対して何をしているのかを理解するために、ブラウザから得られる2種類のスタイルについて説明します。
ブラウザから得られるスタイルは、2つのレイヤーから構成されています。
- レイヤー1, CSSの初期値: これまで見てきたように、最初のレイヤーはCSSのすべてのプロパティの初期値で、一部には
inherit
ビヘイビアも含まれます。 - レイヤー2, UAスタイルシート: それぞれのブラウザが特定のHTML要素に対して定義するスタイルです。
参考:
CSSリセットはほとんどの場合、レイヤー2の基本スタイルを削除したいと考えます。all: unset;
でリセットするときは、UAスタイルシートのすべてのスタイルを削除します。
しかし、display
プロパティは例外的です。すでに見たように、CSSのすべてのプロパティは1つの初期値しかありません。つまり、<div>
要素やその他のHTML要素のようにdisplay
プロパティを初期値にリセットすると、常にinline
値が返されます。
このロジックを続けると、<div>
要素をブラウザから得られるデフォルトのdisplay: block;
にします。しかし、このようなビヘイビアが得られるのはレイヤー2、つまりUAスタイルシートが定義しているからです。このことは、<h1>
から<h6>
の見出し要素で他のHTML要素よりもfont-size
が大きくなるのと同じ考え方に基づいています。
1 2 3 4 5 6 7 8 9 10 |
div { display: unset; /* = inline */ } span { display: unset; /* = inline */ } table { display: unset; /* = inline */ } /* または他のHTML要素はinline値を取得します */ |
これはもちろん、望ましくないビヘイビアです。display
プロパティは、ブラウザから得たい唯一の例外です。そのため、ユニークなキーワード値revert
を使用して、UAスタイルシートからデフォルトのdisplay
値に戻しています。
revert
値はユニークです。まず、自身が置かれている特定のHTML要素のUAスタイルシートに、そのプロパティのデフォルトスタイルがあるかどうかをチェックし、見つかればそれを採用します。見つからなかった場合、revert
はunset
値のように機能します。つまり、そのプロパティがデフォルトで継承されたプロパティであればinherit
値を使用し、そうでなければinitial
値を使用します。
CSSリセットで使用しているキーワードのダイアグラム
ここまでの2つのCSSはユニバーサルセレクタ(*)ですべてを対象にしているように見えますが、いくつかを対象から外しています。なぜですか?
The New CSS Resetを考えはじめたとき、私は例外が必要だとは思っていませんでした。最初は、はるかにシンプルなものでした。
🤓 This is how I imagine #CSS Reset in 2022.
What do you think?
More about CSS Resets, you can read my last article on "How Does CSS Work?":https://t.co/r3ZFz4wl6j pic.twitter.com/kce8wbqmOB
— Elad Shechter (@eladsc) February 2, 2021
しかし、エクスペリエンスを作成し始めたとき、古いCSSリセットを新しいCSSリセット(すべての例外を除いたもの)に置き換えていたので、テストした古いプロジェクトを壊すものがいくつか見られました。
壊れた主なものはwidth
とheight
属性でサイズを取得できる要素、つまり、<iframe>
、<canvas>
、<img>
、<svg>
、<video>
要素でした。残念なことに、すべてをリセットしてしまうと、これらの要素のwidth
とheight
はauto
値で定義されます。auto
はより強力で、要素のwidth
とheight
属性の効果を取り除いてしまいます。
これは、HTMLのwidth
とheight
属性でサイズを定義する場合に、正確なサイズをHTML要素から取得する必要があるため、問題になる可能性があります。CSSからサイズを取得すると、ページの読み込み時に不具合が発生する可能性があるため、CSSではなくHTMLから取得することをお勧めします。
私が見つけた解決方法は、それら特定の要素に対してのリセット効果を削除するために:not
セレクタを使用することです。リセット効果を削除しないThe New CSS Resetは役に立たないので、それら特定の要素に対する効果を削除しました。
リセットでは他のスタイルがリセットと競わないように、詳細度を最小限に抑えることが重要です。それが:where()
の目的ですか?
イエスです。:where
を使用した目的は、詳細度を取り除くことです。CSSリセットを上書きするために、より高い詳細度でCSSを記述する必要はなくなります。
一般的には、複数のセレクタを置き換えるためだけではなく、詳細度を取り除くために:where
を使用するケースが増えてくると思います。
<svg>
の子要素に特別な配慮が入っているように見えます。それはどういうことですか?
2番目の:not(svg *)
は問題が異なるため、別の:not()
を使用しています。SVGの内部要素に触れると視覚的なイメージが壊れてしまう可能性があり、ブラウザを中断する合理的な理由がないことの一つです。
画像は画像のままにしておきましょう、と私は思います。
大きなリセットの後には、意見が分かれる部分があります。例えば、box-sizing
の初期値については各ブラウザで一致しないが、とにかく変更するというものです。私自身はこれが好きなのですが、何がリセットされて何がされないのか、その哲学には興味があります。
一般的に、CSSリセットというと意見が分かれると思います。たとえば、Eric MeyerのCSS Resetでは特定のスタイルを削除することを選択しており、他にもdisplay
プロパティなどが途切れないようになっていますが、これはすでに説明したとおり、私も全く同感です。
box-sizing
については、そうですね、意見が分かれますね。私はWebデベロッパーになって15年になります。その間、過去に慣れ親しんだbox-sizing
のデフォルトのビヘイビアを理解するのに苦労している多くのWebデベロッパーを見てきました。何年か前にCSS Resetに追加されるということが分かったとき、この業界に長く携わってきた多くのWebデベロッパーは、一般的に人は変化を恐れるものなので、この変化を恐れていました。
しかし最近では、すべての要素をbox-sizing: border-box;
にリセットしていないプロジェクトはほとんど見かけなくなりました。ブラウザのエンジンは、デフォルトの厄介な挙動であるbox-sizing: content-box;
を修正することはできません。修正してしまうと、古いWebサイトのサポートが機能しなくなるからです。しかし、新しいプロジェクトでは、自分たちで解決するしかないので、このCSSを含めることは必須です。
そして繰り返しますが、これは完全に意見が分かれています。
他の2つのルール、リストスタイルの削除とボーダーの折りたたみはEric MeyerのCSS Resetにも含まれているため、古くから存在しています。まず、リストスタイルについてですが、リストはナビゲーションのようにマーカーを必要としないものにも使用されるので、これをなくしたいという気持ちはわかります。しかし、iOSでlist-style: none;
はリストのセマンティクスを失ってしまうため、最近ではちょっとした論争になっているようです。何か懸念事項はありますか?
簡単に言うと、ノーです。私には何の心配もありません。理由は次の通りです。
list-style
をリセットしない場合、ナビゲーションにリスト要素を使用できないことを意味します。これはまた、他のブラウザのためのセマンティクスを得られないことも意味します。
そして現在、ほとんどのブラウザがこれらのセマンティクスを得るのか、それともブラウザがこれらのセマンティクスを得ないのかを選択する必要があるとしたら、私は前者を選択します。
今後、追加されていきますか?たとえば、プロジェクトでよく使用される画像のmax-width
を定義するなど。繰り返しになりますが、これは今ではブラウザが同意していないことではなく、ほとんどのプロジェクトで定義されていることでもあります。
もしこのリセットに、私が考慮していなかった何かが欠けているのであれば、それを追加して新しいバージョンをリリースします。max-width
のように画像がコンテナからオーバーフローしないようなケースがないようにする必要があります。
この新しいCascade Layersをご覧になりましたか?これがCSSリセットにどのように影響するか、意見をお願いします。
あなたに聞かれるまで、考えたことはありませんでした。Cascade Layersモジュールは、エキサイティングな機能です。まだサポートはされていませんが、ほとんどのブラウザエンジンがこの機能にフラグを立てていますので、1年後にはすべてのエバーグリーンブラウザでこの機能がサポートされている可能性が高いことを意味します。
※エバーグリーンとは、最新版に自動アップデートされるブラウザのことです。
Cascade Layersを知らない人のために説明すると、@layer
がスタイルを上書きする際に、より強い特殊性を持たせることなく、後に読み込む全てのレイヤーが自動的に前のレイヤーよりも強くなるというものです。
この機能が使用できるようになると、リセットされたレイヤーを最初にロードすることになります。例えば、最初にNormalize.css、次にthe-new-css-reset、そしてプロジェクトの@layer
のスタイルの順です。
1 2 3 |
@layer normalize; /* Create 1st layer named “normalize” */ @layer the-new-css-reset; /* Create 2nd layer named “the-new-css-reset” */ @layer project-styles; /* Create 3rd layer named “project-styles” */ |
これにより、下のレイヤーが常に上のレイヤーに勝てるようになります。また、私が行ったように:where()
で詳細度を取り除く必要がなくなることも意味します。
@layer
は、いつも素晴らしい仕事をしているMiriam Suzanneのおかげで、CSSに登場する最もエキサイティングな将来の機能の1つです。
時間を割いていただきありがとうございます、Elad!
sponsors