こんにちはお久しぶりです。Web標準黒帯(ヤフー内のスキル任命制度)の岡部和昌(@kzms2)と申します。
今回の記事はありがちな「たくさんの良さげなCSSのプロパティなどを羅列してひたすらまとめる」だけではなく以下の考えのもと、まとめた記事です。
- 岡部が「使うケースがある・覚えておくべき」と感じたオススメできる、または有用と判断したCSS
- 可能な限り2020年からブラウザに実装された、またはこれから実装されるCSS
- 比較的新しいまたはあまり使われている印象がないCSS
- 実際のコードや挙動、対応ブラウザを掲載
- 自分目線でみたコメントや使えそうな場面をできる限り丁寧に説明
つまり2020年に実装されたものを中心に、有益でオススメできるCSSを簡単かつできる限り丁寧に書いています。
1つ1つの仕様詳細を詳しく説明すると、量が多すぎて複雑になってしまうので簡単な説明とオススメの使い方のみを載せていきます。詳しい仕様などは記事の最後に仕様書やMDNなどにリンクを貼るので、そちらで確認してください。
またこの記事はとても長く、説明する内容は以下の通りなので、この目次を見て知らないプロパティなどだけでも見ていっていただけたらと思います。
- ユーザーの要求に合わせたメディアクエリ:
prefers-color-scheme
prefers-reduced-motion
- CSSの変数、カスタムプロパティ:
--var
@property
- CSS指定を見やすく、まとめる疑似クラス:
:is()
:where()
:not()
:has()
- 値を省略・機能的にするCSS数学関数:
min()
max()
clamp()
- レイアウトの新しい考え方CSS論理的プロパティ:
block-size
margin-block
inset-inline
etc. - 背景に画像処理を簡単に施す:
backdrop-filter
- リスト記号の装飾を簡単に施す疑似要素:
::marker
- アスペクト比を簡単に保つ:
aspect-ratio
- パフォーマンス最適化:
content-visibility
contain
それでは上記で述べたそれぞれのCSSについて、説明していきます。
1.ユーザーの要求に合わせたメディアクエリ:「prefers-color-scheme」「prefers-reduced-motion」
メディアクエリといえばレスポンシブ デザインにて横幅や画面の状態を見て、CSSを出し分けるという印象が強い方が多いと思いますが、ユーザーの要求に合わせて出し分けるものが新たに追加され始めています。
多数追加され始めているのですが、今回はprefers-color-scheme
とprefers-reduced-motion
の2つが個人的には有用だと感じたのでそれらに関して説明します。
「@media (prefers-color-scheme: dark)」
OSの設定で見た目の好みを「ダークモード」に指定している場合に、有効になる出し分けを指定できます。
macOSでいう以下の設定画面の値によって、例えばユーザーがOSの設定をダークモードにしているときは背景色を黒色にして、文字色を白色を指定できます。
@media (prefers-color-scheme: dark) {
body {
background-color: #000;
color: #fff;
}
}
ただしこの設定を行うとOSの設定に沿った見た目の表示だけになってしまうので、見た目をユーザーに選択させたい場合は別途選択できる機能をJavaScriptなどで提供することも視野に入れたほうがよいでしょう。
対応ブラウザ
「@media (prefers-reduced-motion)」
OSの設定で挙動の好みを「視差効果を減らす」(Reduce motion)をチェックしている場合に、有効になる出し分けを指定できます。
macOSでいう以下の設定画面の値によって、例えば「視差効果を減らす」の設定が有効なときはアニメーションがシンプルになります。
@media (prefers-reduced-motion) {
.animation {
animation-name: simpleAnimation;
}
}
アニメーションをシンプルにした動きを別途用意して、それを適用するとユーザーに優しい設計だと考えられます。
アニメーション前後の差が重要でない場合はanimation-duration: 0ms;
やanimation: none;
を指定するとよいでしょう。
@media (prefers-reduced-motion) {
.animation {
animation: none;
}
}
このように例えばアニメーションを好まないユーザーがいる前提でCSSを組んでいくことで、ユーザー個別の好みに合わせたページを作り上げていくことができます。
対応ブラウザ
2.CSSの変数、カスタムプロパティ:「--var」「@property」
CSSの変数を宣言して簡単に値を使いまわしたり、指定できる仕様で、--var
、@property
などを用いて使用できます。JavaScriptでも宣言ができますがCSS内で簡単に宣言して扱えます。そして値としてvar()
を用いることで指定した変数を使用できます。
変数宣言について
変数の宣言の仕方は以下の3種類があります。
--main-color
のように、ハイフン2つから始まるカスタムプロパティ名と、任意のプロパティ値を指定@property
を用いた指定- JavaScriptで
CSS.registerProperty
を用いた指定
今回は1と2の宣言の仕方について話をします。JavaScriptを用いたCSS.registerProperty
の宣言方法について詳しく知りたい方はCSS.registerProperty() - Web API | MDN(外部サイト)をご覧ください。
ハイフン2つを用いた指定
普通に使う分にはこちらの指定の仕方が簡単でオススメです。基本的な使い方は以下の通りです。以下説明の都合上この宣言の仕方を簡易宣言と呼びます。
:root {
--main-color: violet;
}
section {
background-color: var(--main-color);
}
span {
background-color: #ffffff;
color: var(--main-color);
}
var()
の第2引数に値をセットしておくと、仮に宣言がされていない場合の値を指定できます。例えば下のように指定すると、section
の背景色は何も指定が効かず、a要素に対しては第2引数に指定してあるviolet
が適用されます。
section {
background-color: var(--main-color);
}
span {
background-color: var(--main-color, violet);
}
また前述したメディアクエリと合わせて使うことによって、下記のように使用するのはオススメです。
:root {
--main-color: #fff;
--sub-color: #000;
}
@media (prefers-color-scheme: dark) {
:root {
--main-color: #000;
--sub-color: #fff;
}
}
section {
color: var(--sub-color);
background-color: var(--main-color);
}
このように指定する事によって条件や場合によって値を簡単に一括で変更することが可能です。
対応ブラウザ
「@property」を用いた宣言
@property
を用いると、値に対して型などを付与できるようになり、複雑な値の使用にも耐えられるようになります。
具体的な例を上げると以下のようなグラデーションの色変化を、アニメーションさせたい場合には@property
を用いないと思ったとおりに動作しません。
例えば以下のサンプルの場合、簡易宣言だと動作しません。
:root {
--main-color: #12c2e9;
}
.propertySample {
background-image: linear-gradient(to right, #c471ed, var(--main-color));
transition: --main-color 500ms ease-in-out;
}
.propertySample:hover,
.propertySample:focus {
--main-color: #f64f59;
}
上記のコードだとtransition
を用いたグラデーションの途中の色が計算されません。これは宣言した値がCSSの色プロパティの値として認識できないためです。この問題を解決するためには@property
を用います。
@property --main-color {
syntax: '<color>';
initial-value: #12c2e9;
inherits: false;
}
/* ここから下は全く同じコード */
.propertySample {
background-image: linear-gradient(to right, #c471ed, var(--main-color));
transition: --main-color 500ms ease-in-out;
}
.propertySample:hover,
.propertySample:focus {
--main-color: #f64f59;
}
「結局どちらの宣言方式を使うのがよいの?」 と感じるかもしれませんが基本的には簡易宣言を用いて、その宣言で問題が出る箇所には@property
を用いれば良いと覚えればよいでしょう。厳密には値に意味をしっかり持たせたいのであれば@property
を用いるべきではあります。
対応ブラウザ
3.CSS指定を見やすく、まとめる疑似クラス:「:is()」「:where()」「:not()」「:has()」
こちらはものすごく単純にいうと無駄に長いセレクタ指定をスッキリ見やすくするセレクタだと考えてください。ちなみにこれらは疑似クラスと呼ばれます。
この指定を用いなくても実現できないことはほぼありませんが、これらを用いることでスッキリとした見やすいCSSを書くことができるようになります。
「:is()」
条件が:is()
のカッコの中身と一致する要素をセレクタとして指定できます。これは理解するよりもソースを見たほうがわかりやすいと思うので例をいくつか記載します。
header h1,
main h1,
footer h1
aside > div h1{
color: red;
}
/* ↑と↓は同じ意味合い */
:is(header, main, footer, aside > div) h1 {
color: red;
}
CSSを書いたことがある人なら、ほぼ似た指定なのにたくさんセレクタを書いた記憶はあるのではないでしょうか? この疑似クラスを用いればそれらを省いてコードをスッキリさせられます。
対応ブラウザ
※Edge、Chrome、Android Chrome、Android Browserは:is()
ではなく:-webkit-any()
を用いることで実装可能
「:where()」
:where()
は:is()
とほぼ同じ挙動ですが、:where()
は詳細度を0にして指定できます。
詳細度とはセレクタを用いてプロパティや値を指定したときの強さを表します。CSSの詳細度に関しては基本的な内容かつ説明すると長くなってしまうので詳細が気になる方は「CSS 詳細度」でヤフって見てください。
詳細度がよくわからない方も、以下の例を見ればなんとなくは伝わるかなと思います。
aside > div h1 {
color: blue; /* :where() の指定よりも、この指定が優先される */
}
:where(header,main,footer,aside > div) h1 {
color: red;
}
一見すると後に書いた color: red;
の指定で上書きされそうです。が、:where()
は詳細度が0なので、:where()
よりも前に記載していても color: blue;
指定で上書きできます。
ちなみに上記コードの:where()
を:is()
に変更すると後に書いた color: red;
が適用されます。
対応ブラウザ
※オススメではありますが、実装されているブラウザは少なめです
「:not()」
こちらは:is()
とは逆の挙動でカッコの中身と一致しない要素をセレクタとして指定できます。:not()
を用いた1つの要素に対しての指定は昔から実装されているのですが、複数の要素に対しての指定が新たな仕様となります。こちらもコードを書いて例をお見せします。
section :not(h2,h4){
color: red;
}
指定の通り section h2
とsection h4
以外に対して指定 することが可能です。
またこれは小ネタなのですが以下のような指定をすることでalt
を指定し忘れた場合に警告するといったこともできます。こういった指定を用いて開発・社内向けのツールで気楽に使えるというメリットがあります。
img:not([alt]){
outline: 3px dashed fuchsia;
}
対応ブラウザ
※section:not(h2)
のような1つの要素に対しての指定であれば、現在の主要ブラウザ全てで使用可能
「:has()」
現時点で満足に実装されているブラウザはありませんが、:has()
はおそらくこの中で一番便利な疑似クラスです。子要素に任意の要素を含んでいる場合を指定できます。
a:has(> img) {
background-color: red;
}
上記の指定はa
要素の直下にimg
が存在するa
要素だけに対して有効です。
対応ブラウザ
※オススメではありますが、実装されているブラウザはありません
4.値を省略・機能的にするCSS数学関数:「min()」「max()」「clamp()」
これらの仲間で近年よく使われているのは calc()
だと思います。今回紹介するmin()
max()
clamp()
の使用感や便利さはcalc()
にとても近いです。calc()
に関しては実装からかなりたっているのでここでは説明しませんが、詳細が気になる方は「CSS calc()」でヤフって見てください。
「min()」
任意のプロパティに対する値に最大値を指定して、そのプロパティの値は必ず最大値以下になります。例えばsection
のwidth
をcalc(60% - 40px)
にして、最大値を600px
にしたい場合は以下のように書きます。
section {
width: min(60% - 40px, 600px);
}
/* ↑と↓は同じ意味合い */
section {
width: calc(60% - 40px);
max-width: 600px;
}
つまり、上の例の場合section
は必ず600px
以下になります。またcalc(60% - 40px)
を算出した値が600px
未満のときwidth
の値はcalc(60% - 40px)
を参照します。
説明文を読むよりもコードと動作している画像を見るほうが理解が深まるかと思います。
対応ブラウザ
「max()」
こちらはmin()
と逆で、任意のプロパティに対する値に最小値を指定して、そのプロパティの値は必ず最小値以上になります。例えばsection
のwidth
をcalc(60% - 40px)
にして、最小値を500px
にしたい場合は以下のように書きます。
section {
width: max(60% - 40px, 500px);
}
/* ↑と↓は同じ意味合い */
section {
width: calc(60% - 40px);
min-width: 500px;
}
つまり、上の例の場合section
は必ず500px
以上になります。またcalc(60% - 40px)
を算出した値が500px
より上のときwidth
の値はcalc(60% - 40px)
を参照します。
対応ブラウザ
「clamp()」
そしてこのclamp()
は最も理解するのが難しいと個人的に感じます。ですがとても有用なのでぜひ試して使って覚えることをオススメします。
任意のプロパティに対する値に最小値と最大値を指定して、そのプロパティの値は必ず最小値以上、最大値以下になります。
何を言っているかわからなくなっているかもしれませんが、例えばsection
のwidth
をcalc(60% - 40px)
にして最小値を500px
、最大値を600px
にしたい場合は以下のように書きます。
section {
width: clamp(500px, 60% - 40px, 600px);
}
/* ↑と↓は同じ意味合い */
section {
width: calc(60% - 40px);
min-width: 500px;
max-width: 600px;
}
つまり、上の例の場合section
は必ず500px
以上・600px
以下になります。またcalc(60% - 40px)
を算出した値が500px
より上かつ600px
未満のときwidth
の値はcalc(60% - 40px)
を参照します。
「こんなややこしいことをしないでもmin-width
やmax-width
を使えば良いのでは?」と考える方がいると思いますが、これらの強みは最小値や最大値が指定できないプロパティに対しても使える点です。
例えばwidth
に対してではなく、font-size
などに対しても同じく指定ができます。font-size
に対して最小値、最大値を設定できるのです。
そしてこのclamp()
を用いることによって、フォントサイズを画面幅に合わせてシームレスに大きさを可変させる、といったことが簡単にできるようになります。以下がそのサンプルコードと動作画像です。
p {
font-size: clamp(34px, 5vw, 44px);
}
この指定を簡単に説明するとフォントサイズは5vw
を計算した値になり、その計算した結果が34px
より小さい場合は34px
に、44px
より大きい場合は44px
になります。
対応ブラウザ
5.レイアウトの新しい考え方CSS論理的プロパティ:「block-size」「margin-block」「inset-inline」etc.
CSSを触ったことがある方なら誰でも知っていると言っても過言ではないmargin
padding
border
width
height
top
right
bottom
left
などに対して新しい考え方が導入されています。
これらのCSS論理的プロパティはwriting-mode
direction
text-orientation
それぞれの定義された値にしたがった箇所の値の指定となります。
文字だけでの説明だととても理解が難しい内容だと思うので、旧来のボックスモデルと比較した図と併せて説明します。
名前が置き換わっただけにみえるかもしれませんが、上記の図は例えば英語のように横書きで左上始まりの文章の場合です。
日本語の縦書きのような縦書きで右上始まりの文章の場合では異なった振る舞いになります。
上記を見て気づいた方もいるかとは思いますが、文字の開始位置と文字の流れていく方向に依存するプロパティです。つまり英語の場合、文章の流れていく方向は左から右なのでmargin-inline-start
はmargin-left
。日本語縦書きの場合、文章の流れていく方向は上から下なのでmargin-inline-start
はmargin-top
と同じ扱いになります。
一見ややこしく見受けられるかもしれませんが、文章の規則にのっとってレイアウトも変化するという国際化対応を考えた概念なのです。
これらmargin-inline-start
などの新しいプロパティを用いることにより、言語ごとの書き方に沿ってCSSを同等に割り当てることが可能になります。設計次第ではありますが、文章の冒頭の余白をどの言語でも等しく文章の開始方向に指定することが可能になります。
その他にもtext-align
float
などといったプロパティに対しても策定中なので、詳しくはCSS Logical Properties and Values Level 1(外部サイト)の情報を追うようにしてください。
以下はそのうちの一部をそれぞれの横書きで左上始まりの文章の場合に置き換えた表です。
旧来の考え方 | 新規の考え方 |
---|---|
text-align: left; |
text-align: start; |
text-align: right; |
text-align: end; |
float: left; |
float: inline-start; |
float: right; |
float: inline-end; |
「結局margin-inline-start
とmargin-left
どちらを使うべき?」と考える方がいると思いますが、多言語化対応を行わない場合は現在よく使われているmargin-left
などを用いて記述して問題ないでしょう。
このようなCSS論理的プロパティという指定方法があって、またどういう理由で用意されているのかは理解しておきましょう。
対応ブラウザ
※この仕様はブラウザごとに一部実装されており、規格がまだドラフトで仕様の変動が激しいです。最新の情報を仕様書から追うようにしてください。→CSS Logical Properties and Values Level 1(外部サイト)
6.背景に画像処理を簡単に施す:「backdrop-filter」
backdrop-filter
は簡単に背景に対して、ボカシやグレースケールなどの画像処理を入れることができる有用なプロパティです。似たような効果を発揮するプロパティとしてfilter
がありますが、こちらは子要素までフィルターの処理を施してしまうので使い勝手が難しいシーンがありました。
以下にbackdrop-filter
とfilter
を並べたサンプルを用意したので、その挙動の差を確認できるかと思います。
.sample-left .box {
backdrop-filter: blur(10px);
}
.sample-right .box {
filter: blur(10px);
}
.sample-left .box {
backdrop-filter: grayscale(1);
}
.sample-right .box {
filter: grayscale(1);
}
たった1行書くだけで画像や要素の背景だけに対してフィルタをかけられて、表現の幅を気軽に広げられるので試しに使ってみてはいかがでしょうか。
対応ブラウザ
※Safari、iOS Safariは-webkit-backdrop-filter
を用いることで実装可能
7.リスト記号の装飾を簡単に施す疑似要素:「::marker」
おそらくこの項は今回解説する中で一番地味だとは思いますが、意外と役立つシーンがある新仕様であると考えているので簡単ではありますが説明していきます。
li
やsummary
の行頭に表示される記号に対して、スタイルを割り当てるのはひと手間必要でした。今回説明する::marker
を用いると簡単に装飾を変更できます。
ul li::marker {
color: red;
font-size: 20px;
}
またcounter()
と併せて使用することでナンバリングの仕方を自身で指定できます。
ol li::marker {
content: "【" counter(list-item, lower-roman) "】";
}
対応ブラウザ
※Safariでは一部機能が未実装
8.アスペクト比を簡単に保つ:「aspect-ratio」
現時点で満足に実装されているブラウザはありませんが、近いうちに実装されるであろうとても便利なaspect-ratio
について説明します。
これは要素に対してアスペクト比を簡単に指定してレスポンシブな状態を簡単に実現できる素晴らしいプロパティです。
例えばimg
やiframe
の比率を16:9に保ったまま、画面幅に合わせて可変させることが容易にできます。下記のようにcalc()
を用いた複雑な式を用いつつ比率を簡単に保てます。
img {
width: calc(100% - 20px);
aspect-ratio: 16 / 9;
}
16 / 9
は半角スペースをなくしても動作しますが、半角スペースを入れた方がよいでしょう。
もちろん画像に対してだけでなく、どの要素に対しても指定できるので例えば1:1の比率を保ったまま、レスポンシブな領域を作ることも可能です。
対応ブラウザ
※オススメではありますが、実装されているブラウザはありません。(2021年はじめにChromeに実装される見込み)
9.パフォーマンス最適化:「content-visibility」「contain」
ここの項の内容に関しては9月に書いた表示速度を飛躍的に向上させるHTML/CSS最新仕様「content-visibility」「Lazy loading」「contain」をコード付き簡単解説の記事で詳細を書いているのでご覧いただければと思います。
2021年は現状よりも一層パフォーマンス最適化:が必要になってくると考えられます。速度はGoogle検索の検索順位にも影響する指標となることが発表されています。 詳しくは本年度のアドベントカレンダーにもあるユーザー体験を向上!Yahoo!ニュースにおけるCore Web Vitals対応事例でもその重要性が説明されているので一読してみてはいかがでしょうか。
まとめ
いかがでしたか。ここで紹介したCSSも一部でまだまだたくさんの仕様がどんどん追加されています。主要なブラウザ全てに実装されてからが本番なので、その時までにどういったものなのかを理解しておくとスムーズに導入できるのではないでしょうか。
今回紹介した仕様はIE11では基本的には使えませんが、似通った実装をするPolyfillも用意されていたりするので、気になった仕様に関してIE11でも使いたい場合は別途調べてみてください。
どのブラウザに実装されているのか、されていくのかはCan I use… Support tables for HTML5, CSS3, etc(外部サイト)を見る癖をつけるとよいでしょう。
またこれは岡部個人が受けている印象なのですが、近年新しく追加されていくCSSは以下の傾向があると感じています。
- 高速化・パフォーマンス向上
- 開発者のコード記述における手間や負荷を軽減
- 文字やレイアウトのグローバル対応
- ユーザーの好みに合わせた出し分け
- アクセシビリティを高める指定
CSSは一昔前よりも内容が充実してきて、UXを向上させる仕様が増えてきているので今後のWebは、より表現力が強まりアクセシブルなものになっていくと考えられます。
今回の記事で紹介したものはまだ勧告されていないものも多数あるので、仕様に変更が入る可能性は大いにあります。
今回説明したかったプロパティはまだまだあるのですが、それはまたの機会に説明できたらと思います。
こういった最新のCSSや標準系の情報をTwitterでキャッチアップ、RTなどしているので新しいCSSや標準などにf興味がある方は@kzms2のフォローをよろしくお願いいたします。
参考リンク(外部サイト)
- ユーザーの要求に合わせたメディアクエリ:
prefers-color-scheme
prefers-reduced-motion
- CSSの変数、カスタムプロパティ:
--var
@property
- CSS指定を見やすく、まとめる疑似クラス:
:is()
:where()
:not()
:has()
- 値を省略・機能的にするCSS数学関数:
min()
max()
clamp()
- レイアウトの新しい考え方CSS論理的プロパティ:
block-size
margin-block
inset-inline
etc. - 背景に画像処理を簡単に施す:
backdrop-filter
- リスト記号の装飾を簡単に施す疑似要素:
::marker
- アスペクト比を簡単に保つ:
aspect-ratio
- パフォーマンス最適化:
content-visibility
contain
こちらの記事のご感想を聞かせください。
- 学びがある
- わかりやすい
- 新しい視点
ご感想ありがとうございました