背景として使用される CSS グラデーションはどの範囲に描画されるか

Category : CSS

背景として使われる CSS グラデーションが描画される範囲はどのように決定されるのか、仕様を読みながら考えてみたいと思います。
参考にしたのは 2012年4月17日版の CSS Image Values and Replaced Content Module Level 3 です。非公式の日本語訳 もあります。

この記事に書いている範囲は自分で訳したので、上記の翻訳とは用語の表記などが異なっています。ご了承ください。
(調べ終わり頃に日本語訳があるのに気づいたので……)

なお、ここ以降で単に「グラデーション」と書いている場合は「CSS グラデーション」のことを指します。

グラデーションが描画される範囲について

まずはグラデーションが描画される範囲はどのように決定されるのかを調べてみます。
仕様を見ると次のように書かれています。

グラデーションはグラデーションボックス (gradient box) と呼ばれる具体的なオブジェクトサイズ (concrete object size) の寸法内に描画される。しかし、グラデーション自体は本質的な寸法 (intrinsic dimensions) を持っていない。

グラデーションが背景に使用されるとき、初期状態でグラデーションが描画されるグラデーションボックスは要素のパディングボックスになる。もし background-size100px 200px のように明示されているなら、グラデーションボックスは 100px の幅と 200px の高さになるだろう。
同様に、グラデーションが list-style-image に使用されるとき、グラデーションボックスはそのプロパティの初期オブジェクトサイズ (default object size) である 1em の正方形になるだろう。

さらっと書かれていますが、何言ってるか分かりません。
分かるのは背景に使われるときの初期範囲がパディングボックスであるということくらいです。
それだけでも十分といえば十分ですが、調べたいのは「どうやって決まるのか」なので、更に読んでみます。

用語について

本質的な寸法 (intrinsic dimensions)

本質的な寸法とは、本質的な幅、本質的な高さ、そして本質的なアスペクト比 (その比は幅と高さの比である) のことで、指定されたオブジェクトにそれぞれ存在するかもしれないし、しないかもしれない。
これらの本質的な寸法はオブジェクト自体の望ましい、または自然なサイズを表す。すなわち、それらはオブジェクトが使用されるコンテキストの機能ではない。CSS は本質的な寸法が一般的にどのように見つけられるかを定義しない。

ラスター画像は3つの本質的な寸法 (幅、高さ、アスペクト比) を持つオブジェクトの例である。
拡大縮小されるように作られた SVG 画像は、おそらく本質的なアスペクト比だけを持つだろう。また、SVG 画像は本質的な幅または高さのみを持つように作られることもある。
この仕様 (CSS Image Values and Replaced Content Module Level 3) で定義されている CSS グラデーションは、そもそも本質的な寸法を持っていないオブジェクトの一例である。もう一方の例として、HTML での <iframe> 要素のような埋め込みドキュメントがある。
オブジェクトは2つの本質的な寸法のみを持つことはできない。たとえば2つの寸法から自動的に3つ目を定義するといったもの。

つまり……画像が最初から持っている幅と高さ、アスペクト比のことです。
たとえば 800 x 600 の jpg 画像なら、その本質的な寸法は 800px の幅、600px の高さ、4:3 のアスペクト比、となります。
また SVG 画像はそのうち1つしか持っていない場合もあります、と。
そしてグラデーションは、幅も高さもアスペクト比も持っていません。

指定サイズ (specified size)

指定オブジェクトサイズとは、widthheight または background-size プロパティなど、CSS から与えられるものである。
指定サイズは明確な幅と高さ、制約のセット、またはその組み合わせとなる。

オブジェクトが持つ本質的な寸法ではなく、CSS で指定したサイズのこと。

具体的なオブジェクトサイズ (concrete object size)

具体的なオブジェクトサイズとは、オブジェクトを使用するコンテキストにおける初期オブジェクトサイズでのオブジェクトの本質的な寸法と指定サイズを組み合わせた結果であり、明確な幅と高さを持つ矩形を作り出す。

ちょっと言い方がややこしいですが、オブジェクトに CSS を適用した後の、最終的なサイズということです。
初期オブジェクトサイズとは何か、というのは次に説明します。

グラデーションボックスがこの具体的なオブジェクトサイズの寸法であることは最初に出てきました。
つまりこのサイズがグラデーションのサイズとなります。

初期オブジェクトサイズ (default object size)

初期オブジェクトサイズとは、本質的な寸法と指定サイズの両方が存在しないとき、具体的なオブジェクトサイズを決定するのに使用される明確な幅と高さを持つ矩形である。

これは状況によって違うので具体的にどのサイズとは言えませんが、背景画像の初期オブジェクトサイズについては後ほど説明します。

ここまでのまとめ

グラデーションはグラデーションボックスと呼ばれる範囲内に描画される。グラデーションボックスとは、具体的なオブジェクトサイズの寸法である。
しかし、グラデーションそれ自体は寸法を持っていないオブジェクトなので、具体的なオブジェクトサイズが存在しない。
グラデーションに具体的なオブジェクトサイズを与えるには、CSS の指定によって指定サイズを与える必要がある。
その指定サイズも存在しない場合、使用される状況に応じた初期オブジェクトサイズが用いられる。

では次に背景として用いられるグラデーションの描画範囲はどのように決定されるかを見ていきます。

背景として使用されるグラデーションのサイズはどのように決定されるか

これを知るには、まず具体的なオブジェクトサイズ (つまりグラデーションボックス) がどのように決定されるかを知る必要があります。
前セクションの用語解説では「オブジェクトを使用するコンテキストにおける初期オブジェクトサイズでのオブジェクトの本質的な寸法と指定サイズを組み合わせた結果」とだけ書かれていますが、より詳しく見ていきます。

これは CSS Image Values and Replaced Content Module Level 3 の 5.3.1. Default Sizing Algorithm に記載されています。

このアルゴリズムは次のように定義される。

  • 指定サイズが明確な幅と高さである場合、具体的なオブジェクトサイズには幅と高さが付与される。
  • 指定サイズが幅または高さ (両方ではない) のみの場合、具体的なオブジェクトサイズには幅または高さが付与される。他の寸法は次のように決定される。
    1. オブジェクトが本質的なアスペクト比を持つ場合、具体的なオブジェクトサイズの足りない寸法は本質的なアスペクト比と与えられた寸法を使用して計算される。
    2. そうでなければ、足りない寸法がオブジェクトの本質的な寸法により与えられる場合、足りない寸法はオブジェクトの本質的な寸法から取得される。
    3. そうでなければ、具体的なオブジェクトサイズの足りない寸法は初期オブジェクトサイズから取得される。
  • 指定サイズが制約を持たない場合
    1. オブジェクトが本質的な幅または高さを持つ場合、その本質的なサイズが指定サイズとして指定されているかのように解決される。
    2. そうでなければ、初期オブジェクトサイズに対するコンテイン制約 (contain constraint) として解決される。

背景として使われるグラデーションに指定サイズを指定するには、background-size プロパティを使用します。
background-size50% 50% のように、長さまたはパーセンテージの2つの値を指定した場合は1つ目のアルゴリズムが使用されます。
1つ目の値が幅、2つ目の値が高さとなり、ここで指定したサイズがグラデーションボックスとなります。
(パーセンテージがどう扱われるかは後述します)

background-size に1つの長さもしくはパーセンテージのみを指定した場合、その値は幅として扱われ、未指定の高さの値にはプロパティの初期値である auto が指定されます。この auto は2つ目のアルゴリズムにより計算されます。
最初の値に auto を指定し、2つ目の値に長さもしくはパーセンテージを指定した場合も同様です。
グラデーションには本質的な寸法が存在しないので、2つ目のアルゴリズムのうち、3番目の項目が使用されます。一方にのみ指定された auto の値は初期オブジェクトサイズの幅または高さとなります。この値は 100% として扱われると背景の仕様には書かれていますが、なぜそうなるのかは後述します。

background-size が全くの未指定である場合、その値は初期値である auto auto となります。この場合、background-size は3つ目のアルゴリズムにより計算されます。
そして本質的な寸法を持たないグラデーションは3つ目のアルゴリズムのうち、2番目の項目に当たります。つまりコンテイン制約です。
背景の仕様にも、寸法を持たないオブジェクトの background-size: auto auto;contain として扱われると書かれています。

ここでまた新しい用語が出てきました。コンテイン制約とは何か、です。

カバー並びにコンテイン制約サイジング

コンテイン制約とカバー制約の2つの共通指定サイズは、どちらもオブジェクトの本質的なアスペクト比を使用する指定された制約矩形に対して解決される。

  • コンテイン制約とは、オブジェクトの本質的な寸法を持ち、加えて、それぞれ制約矩形の幅と高さよりも大きな幅も高さも持たない最大の矩形に具体的なオブジェクトサイズを設定することにより解決される。
  • カバー制約とは、オブジェクトの本質的な寸法を持ち、加えて、それぞれ制約矩形の幅と高さよりも小さな幅も高さも持たない最小の矩形に具体的なオブジェクトサイズを設定することにより解決される。

どちらの場合でも、オブジェクトが本質的なアスペクト比を持たない場合、具体的なオブジェクトサイズは指定された制約矩形である。

background-size が指定されていない、背景として使用されるグラデーションはコンテイン制約であり、本質的なアスペクト比も持たないので、その具体的なオブジェクトサイズは背景として指定される箇所の初期オブジェクトサイズと等しくなる、ということです。

ここでようやく前セクションのまとめで書いた「その指定サイズも存在しない場合、使用される状況に応じた初期オブジェクトサイズが用いられる」がどのように決定されているかが分かりました。

よって、背景として使用される、指定サイズを持たないグラデーションボックスは、グラデーションを指定する background-image の初期オブジェクトサイズと同じサイズになります。

次に background-image のオブジェクトサイズについてを見てみます。

background-image のオブジェクトサイズ

background-image の初期オブジェクトサイズについては、仕様に載っている例で次のように書かれています。

background-image の初期オブジェクトサイズは、CSS 2.1 と CSS Backgrounds and Borders Module Level 3 により定義される。
CSS 2.1 においては、指定サイズなしでデフォルトサイジングアルゴリズムを使用し、初期オブジェクトサイズとして背景配置領域を使用する。
CSS 3 においては、background-size プロパティはデフォルトサイジングアルゴリズムまたはカバーもしくはコンテイン制約のどちらか一方のいずれかを呼び出すことでサイジング制約を付与できる。background-repeat の値が round である場合は、具体的なオブジェクトサイズは更に後の段階で調整される。

ここで background-image の初期オブジェクトサイズは背景配置領域であることが分かりました。
前述したように「背景として使用される、指定サイズを持たないグラデーションボックスは、グラデーションを指定する background-image の初期オブジェクトサイズと同じサイズ」であるので、background-size による指定のない、背景として使用されるグラデーションの具体的なオブジェクトサイズは背景配置領域と等しい、ということになります。

背景配置領域は background-origin プロパティによって指定が可能です。
そしてそのプロパティの初期値は padding-box であるので、background-origin による背景配置領域の指定のない箇所へ適用される、background-size による制約のないグラデーションの具体的なオブジェクトサイズは padding-box となります。

これでやっと最初の方に出てきた「グラデーションが背景に使用されるとき、初期状態でグラデーションが描画されるグラデーションボックスは要素のパディングボックスになる」の意味が分かりました。

background-size の2つの値のうち一方のみに指定された auto100% として扱われる理由についてですが、デフォルトサイジングアルゴリズムにより、この値は初期オブジェクトサイズの幅または高さであります。
background-size による指定のないグラデーションの具体的なオブジェクトサイズは background-image の初期オブジェクトサイズであり、それは背景配置領域のサイズでもあります。
そして background-size のパーセンテージ値は背景配置領域に対するパーセンテージです (背景の仕様参照)。
よって、デフォルトサイジングアルゴリズムの2つ目3番目が使用される、一方の値が autobackground-size が指定されたグラデーションの auto の寸法は背景配置領域の幅または高さと等しく、100% と等しくなります。

まとめ

背景として使用されるグラデーションはどの範囲に描画されるか。

  • background-size による指定がない限りは、背景配置領域に対して最大の大きさとなる。これは background-size: auto auto; と同じであり、それは contain として扱われる。
  • background-size へのパーセンテージは背景配置領域に対するパーセンテージである。
  • background-size の値の一方にのみ auto が指定されたグラデーションは、長さもしくはパーセンテージの幅または高さは指定したサイズ、auto が指定された幅または高さは背景配置領域に対して最大のサイズとなる。
  • background-size の2つの値に長さまたはパーセンテージを指定した場合は、その指定したサイズとなる。
  • 背景配置領域は background-origin プロパティで領域を指定可能である。

以上で終わりですが、読み違えている可能性もありますので、気になる方は自分でも調べてみることをお勧めします。
背景以外の初期オブジェクトサイズは仕様に書かれていますので、興味のある方はご確認ください。

おまけ

たまに「グラデーションが background-repeat: repeat; で繰り返し表示できない」と書いている方を見かけますが、それは background-size で明確なサイズを指定していないからです。
それと単純なグラデーションの繰り返しなら repeating-[linear/radial]-gradient() があるので、それを使うのもいいと思います。

あと、背景に使うグラデーションを指定するのは background-image プロパティです。background-color ではありません。

まだ実装はありませんが、グラデーションは list-style-imagecontent プロパティなどにも指定できることになっています。
一応、もうすぐ Webkit で使えるようになります-webkit- 接頭辞も外れます。

Leave a Reply