目次
新しいフロントエンド プロジェクトを開始するときの最初のタスクは、CSS のいくつかのデフォルト スタイルをリセットすることです。最新の CSS でスタイルをリセットする方法を見てみましょう。この記事では、各ルールを深く掘り下げて、その機能とそれを使用する理由を理解します。
カスタム CSS リセット コードは次のとおりです。
/*
1. 使用更直观的 box-sizing 模型
*/
*, *::before, *::after {
box-sizing: border-box;
}
/*
2. 移除默认 margin
*/
* {
margin: 0;
}
/*
3. 在应用中允许基于百分比的高度
*/
html, body {
height: 100%;
}
/*
排版调整
4. 添加无障碍行高
5. 改进文本渲染
*/
body {
line-height: 1.5;
-webkit-font-smoothing: antialiased;
}
/*
6. 改进媒体默认设置
*/
img, picture, video, canvas, svg {
display: block;
max-width: 100%;
}
/*
7. 删除内置表单排版样式
*/
input, button, textarea, select {
font: inherit;
}
/*
8. 避免文字溢出
*/
p, h1, h2, h3, h4, h5, h6 {
overflow-wrap: break-word;
}
/*
9. 创建根层叠上下文
*/
#root, #__next {
isolation: isolate;
}
ここにはそれほど多くのコードはありませんが、この小さなスタイルシートでは多くのことが行われています。以下、一つずつ紹介していきます!
歴史的に、CSS リセットの主な目的は、ブラウザ間で一貫性を確保し、すべてのデフォルト スタイルを元に戻すことでした。この CSS リセット コードは実際にはこれらのことを何も行いません。
最近のブラウザでは、レイアウトや間隔に大きな違いはありません。一般に、ブラウザは CSS 仕様を正確に実装しており、すべてが期待どおりに動作するため、CSS 仕様は必要なくなりました。
ここでの CSS リセットは、「CSS リセット」の古典的な定義には当てはまらないかもしれませんが、よりクリエイティブです。
1. ボックスサイジングモデル
まずコードの一部を見てみましょう。他の CSS が適用されていないと仮定すると、次のシナリオの .box
要素の幅はどれくらいですか?
<style>
.parent {
width: 200px;
}
.box {
width: 100%;
border: 2px solid hotpink;
padding: 20px;
}
</style>
<div class="parent">
<div class="box"></div>
</div>
ここで、 .box
要素の幅は 100% です。親の幅は 200px なので、100% は 200px に解決されます。しかし、200px の幅はどこに適用されるのでしょうか? デフォルトでは、そのサイズがコンテンツ領域 (以下の画像の白い領域) に適用されます。
width: 100%
この宣言により、 .box
コンテンツ ボックスが 200px に設定されます。代わりに、 padding
さらに 40 ピクセル (両側に 20 ピクセル) が追加されます。境界線はさらに 4 ピクセル (両側に 2 ピクセル) 追加されます。計算すると、ピンク色の長方形の幅は 244 ピクセルになります。
244 ピクセルのボックスを幅 200 ピクセルの親に合わせようとすると、オーバーフローが発生します。
次のルールを設定することで、この奇妙な動作を変更できます。
*, *::before, *::after {
box-sizing: border-box;
}
このルールを適用すると、パーセンテージがボーダーボックスに従って解析されます。上の例では、ピンクのボックスの幅は 200 ピクセルで、内側のコンテンツ ボックスの幅は 156 ピクセル (200 ピクセル - 40 ピクセル - 4 ピクセル) に縮小されます。
これは、CSS の機能を向上させるために必須のルールです。ここでは、ワイルドカード セレクター (*) を使用して、すべての要素と疑似要素に適用します。一般に信じられていることに反して、これはパフォーマンスにとって悪いことではありません。
Web 上の一部の人々は、代わりに次のことを行うことを提案しています。
html {
box-sizing: border-box;
}
*, *:before, *:after {
box-sizing: inherit;
}
これは、ボーダーボックスを使用するために大規模な既存のプロジェクトを移行しようとしている場合に役立つ戦略かもしれません。新しいプロジェクトを最初から開始する場合、これは必要ありません。わかりやすくするために、上記の CSS リセットからは省略されました。
では、これはいつ役立つのでしょうか? 役に立つかもしれない例を見てみましょう。これは、大規模な既存プロジェクトを移行してボーダーボックスを使用する場合に便利な戦略となります。新しいプロジェクトをまったく最初から始める場合は、その必要はありません。わかりやすくするために、CSS リセットからは省略しました。
展開すると、役立つ可能性のある例が表示されます。まず、 legacy
の box-sizing
プロパティを設定します content-box
。これは box-sizing
プロパティのデフォルト値です。
.legacy {
box-sizing: content-box;
}
次に、アプリケーションの一部がボーダーボックスを使用するように移行されていない場合、クラスは次のように配置できます。
<body>
<header class="legacy">
<nav>
<!-- 遗留的内容在这里 -->
</nav>
</header>
<main>
<section>
<!-- 现代的内容在这里 -->
</section>
<aside class="legacy">
<!-- 遗留的内容在这里 -->
</aside>
</main>
</body>
ここではclass<header>
が与えられている legacy
ので、 を使用します box-sizing: content-box
。その子要素 <nav>
には があります box-sizing: inherit
。親が に設定されているため content-box
、nav も同様に に設定されます content-box
。
<main>
ラベルには legacy
クラスがないため、その親から継承します <body>
。<body>
から継承されました <html>
。<html>
に設定されます border-box
。
基本的に、各要素はボックスのサイズ変更動作をその親から見つけるようになります。legacy
設定クラスの祖先が ある場合 、それは になりますcontent-box
。そうしないと、HTML タグを継承することになります (つまり、 を使用することになります) border-box
。
2. デフォルトのマージンを削除します
* {
margin: 0;
}
通常、ブラウザーはマージンに関して常識的な仮定を立てます。たとえば、デフォルトでは、h1 には p よりも多くのマージンが含まれます。これらの仮定は、ドキュメント リテラルの処理というコンテキストでは合理的ですが、最新の Web アプリケーションでは正確ではない可能性があります。
通常、デフォルトでは要素にマージンを持たせないことが望ましいため、デフォルトのマージンをすべて削除します。特定のラベルに余白を追加したい場合は、カスタム スタイルで追加できます。ワイルドカード セレクター (*) は特異性が非常に低いため、このルールを簡単にオーバーライドできます。
3. 身長の割合に基づく
html, body {
height: 100%;
}
CSS でパーセンテージベースの高さを使用しようとして、うまく機能しないことが判明したことはありますか? 例を見てみましょう:
ここでは、メイン要素の高さは 100% ですが、要素はまったく成長しません。これは機能しません。流動的なレイアウト (CSS の主要なレイアウト パターン) では、高さと幅がまったく異なる原理で動作するためです。要素の幅は親要素から計算され、要素の高さは子要素から計算されます。
このルールが適用されるとmain
要素が増加する可能性があります。
React などの JavaScript フレームワークを使用している場合は、このルールに 3 番目のセレクター、つまりフレームワークで使用されるルートレベルの要素を追加することもできます。
たとえば、Next.js プロジェクトでは、ルールを次のように更新します。
html, body, #__next {
height: 100%;
}
では、なぜ vh 単位を使用せずにパーセンテージベースの高さを設定するのでしょうか? 問題は、vh ユニットがモバイルでは適切に動作しないことです。モバイル ブラウザではブラウザ UI の表示と非表示が行われるため、100vh は画面領域の 100% 以上を占有します。将来的には、新しい CSS ユニットによってこの問題が解決される予定です。それまでは、パーセンテージベースの高さを使用できます。
4. 行の高さを調整する
body {
line-height: 1.5;
}
line-height は、段落内のテキストの各行間の垂直方向の間隔を制御します。デフォルトはブラウザによって異なりますが、通常は 1.2 程度です。この単位のない数値は、em 単位と同様に、フォント サイズに基づいています。行の高さが 1.2 の場合、各行の高さは要素のフォント サイズより 20% 大きくなります。
ここに問題があります。失読症の人にとって、行がぎっしり詰まっていて読みにくいのです。WCAG 標準では、行の高さは少なくとも 1.5 でなければならないと規定されています。この図では、見出しやその他の大きなフォント要素にかなり大きな線が生成される傾向があります。
ヘッダーでこの値をオーバーライドすることもできます。私の理解では、WCAG 標準は見出しではなく「本文」テキストに適用されます。
5. スムースフォント
body {
-webkit-font-smoothing: antialiased;
}
MacOS コンピュータでは、ブラウザはデフォルトでサブピクセル アンチエイリアスを使用します。各画素内のR/G/B光を利用して文字を読みやすくする技術です。以前は、これはテキストのコントラストが向上するため、アクセシビリティの向上と見なされていました。
2018 年にリリースされた MacOS Mojave では、Apple はオペレーティング システム全体でサブピクセル アンチエイリアスを無効にしました。ただし、Chrome や Safari などの MacOS ブラウザは依然としてデフォルトでサブピクセル アンチエイリアスを使用します。-webkit-font-smoothing
に設定して オフにする必要があります antialiased
。
以下の図の左側は、閉じた後の効果です。
MacOS はサブピクセル アンチエイリアスを使用する唯一の OS であるため、このルールは Windows、Linux、またはモバイル デバイスには影響しません。MacOS コンピューターを使用している場合は、(CSS リセットなしで) 2 つのリアルタイム レンダリングを比較できます。
p {
-webkit-font-smoothing: subpixel-antialiased;
font-family: sans-serif;
}
.antialiased {
-webkit-font-smoothing: antialiased;
}
効果は次のとおりです。
6. メディアのデフォルト
img, picture, video, canvas, svg {
display: block;
max-width: 100%;
}
HTML では、画像はインライン要素とみなされます。<em>
これは、や の ように段落の途中で使用する必要があることを意味します<strong>
。これは、ほとんどの場合の画像の使用方法と矛盾します。一般に、画像はレイアウト要素である段落や見出しと同じように扱われます。
ただし、レイアウトでインライン要素を使用しようとすると、奇妙なことが起こります。謎の 4 ピクセルのギャップがあったことがある場合、それはpadding
、margin
またはではなくborder
、ブラウザによって行の高さによって追加されたインライン スペースである可能性があります。
この問題は、画像に display: block を設定することで回避されます。それに加えて、 も設定されていますmax-width: 100%
。これは、幅が十分でないコンテナに大きな画像が配置された場合にオーバーフローを防ぐために行われます。ほとんどのブロック レベルの要素は、親に合わせて自動的に拡大/縮小しますが、 <img>
このようなメディア要素は特殊です。これらは置換要素と呼ばれ、これらのルールに従いません。
画像の元のサイズが800x600の場合、横幅500pxの親要素に配置しても横幅は800pxになります。このルールは、イメージがコンテナからはみ出すことを防ぎます。これはおそらく、より賢明なデフォルトの動作です。
7. フォームコントロールのフォントを継承する
input, button, textarea, select {
font: inherit;
}
デフォルトでは、ボタンと入力フィールドは親要素からタイポグラフィ スタイルを継承しません。その代わりに、彼らは独自の奇妙なスタイルを持っています。たとえば、<textarea>
システムのデフォルトの等幅フォントが使用されます。input
入力にはシステムのデフォルトのサンセリフ フォントが使用されます。どちらも非常に小さなフォント サイズ (Chrome では 13.333px) を選択します。モバイル デバイスで 13 ピクセルのテキストを読むのは難しい場合があります。小さなフォントの入力に焦点を当てると、ブラウザーが自動的に拡大してテキストを読みやすくします。
あまり良くない経験を次に示します。
この自動スケーリング動作を回避したい場合は、入力フォント サイズが少なくとも 1rem / 16px である必要があります。この問題を解決する 1 つの方法は次のとおりです。
input, button, textarea, select {
font-size: 1rem;
}
これにより自動スケーリングの問題は解決されますが、それは表面的なものです。この問題の根本原因は、フォーム入力に独自のタイポグラフィ スタイルを持たせないことです。
input, button, textarea, select {
font: inherit;
}
font-size
font は、 、font-weight
、などのフォント関連のプロパティを設定する、ほとんど使用されない省略表現です font-family
。これを に設定すると inherit
、これらの要素が周囲のタイポグラフィと一致することを指定します。これを行うと、本文テキストに非常に小さなフォントを設定しない限り、これらの問題は解決されます。
8. ワードラップ
p, h1, h2, h3, h4, h5, h6 {
overflow-wrap: break-word;
}
CSS では、1 行にすべての文字を入れるのに十分なスペースがない場合、テキストは自動的に折り返されます。デフォルトでは、アルゴリズムは「ソフト改行」の機会を探します。これは、アルゴリズムが分割できる文字です。英語では、ソフトラップできるのはスペースとハイフンだけですが、これは言語によって異なります。
行にソフトラップの可能性がなく、改行に収まらない場合は、テキストがオーバーフローします。
これにより、水平スクロールバーが表示されたり、テキストが他の要素に重なったり、画像やビデオの後ろにスライドしたりする可能性があります。
overflow-wrap
属性は改行アルゴリズムを調整し、ソフトラップの機会が見つからない場合にハードラップの使用を許可できます。
さらに、ハイフン属性を追加してみることもできます。
p {
overflow-wrap: break-word;
hyphens: auto;
}
ハイフン: auto は (ハイフンをサポートする言語で) ハイフンを使用してハード改行を指定するため、ハード改行がより一般的になります。テキスト列が非常に狭い場合、これは価値があるかもしれませんが、少し邪魔になる可能性もあります。そのため、リセットには含めませんでしたが、試してみる価値はあります。
9. ルートカスケードコンテキスト
#root, #__next {
isolation: isolate;
}
この項目はオプションです。通常、React などの JavaScript フレームワークを使用する場合にのみ必要になります。分離プロパティを使用すると、z-index を設定せずに新しいスタッキング コンテキストを作成できます。これにより、特定の優先度の高い要素 (モーダル、ドロップダウン、ツールチップなど) が常にアプリ内の他の要素の上に表示されるようになります。
使用するフレームワークに応じて、アプリケーションでレンダリングされる最上位の要素を選択するセレクターを調整する必要があります。たとえば、create-react-app
は使用される <div id="root">
ため、セレクターを使用する必要があります#root
。
最後に、これらのリセット スタイルの完全なコードを見てみましょう。これはコピーして独自のプロジェクトに貼り付けることができます。
*, *::before, *::after {
box-sizing: border-box;
}
* {
margin: 0;
}
html, body {
height: 100%;
}
body {
line-height: 1.5;
-webkit-font-smoothing: antialiased;
}
img, picture, video, canvas, svg {
display: block;
max-width: 100%;
}
input, button, textarea, select {
font: inherit;
}
p, h1, h2, h3, h4, h5, h6 {
overflow-wrap: break-word;
}
#root, #__next {
isolation: isolate;
}
参考記事: https: //www.joshwcomeau.com/css/custom-css-reset/