背景として使用されるCSSグラデーションはどの範囲に描画されるか
公開:
背景として使われるCSSグラデーションが描画される範囲はどのように決定されるのか、仕様を読みながら考えてみたいと思います。
参考にしたのは2012年4月17日版の「CSS Image Values and Replaced Content Module Level 3」です。非公式の日本語訳もあります。
この記事に書いている範囲は自分で訳したので、上記の翻訳とは用語の表記などが異なっています。ご了承ください。
(調べ終わり頃に日本語訳があるのに気づいたので……)
なお、ここ以降で単に「グラデーション」と書いている場合は「CSSグラデーション」のことを指します。 まずはグラデーションが描画される範囲はどのように決定されるのかを調べてみます。 グラデーションはグラデーションボックス(gradient box)と呼ばれる具体的なオブジェクトサイズ(concrete object size)の寸法内に描画される。しかし、グラデーション自体は本質的な寸法(intrinsic dimensions)を持っていない。 グラデーションが背景に使用されるとき、初期状態でグラデーションが描画されるグラデーションボックスは要素のパディングボックスになる。もし さらっと書かれていますが、何言ってるか分かりません。 本質的な寸法とは、本質的な幅、本質的な高さ、そして本質的なアスペクト比(その比は幅と高さの比である)のことで、指定されたオブジェクトにそれぞれ存在するかもしれないし、しないかもしれない。 ラスター画像は3つの本質的な寸法(幅、高さ、アスペクト比)を持つオブジェクトの例である。 つまり……画像が最初から持っている幅と高さ、アスペクト比のことです。 指定オブジェクトサイズとは、 オブジェクトが持つ本質的な寸法ではなく、CSSで指定したサイズのこと。 具体的なオブジェクトサイズとは、オブジェクトを使用するコンテキストにおける初期オブジェクトサイズでのオブジェクトの本質的な寸法と指定サイズを組み合わせた結果であり、明確な幅と高さを持つ矩形を作り出す。 ちょっと言い方がややこしいですが、オブジェクトにCSSを適用した後の、最終的なサイズということです。 グラデーションボックスがこの具体的なオブジェクトサイズの寸法であることは最初に出てきました。 初期オブジェクトサイズとは、本質的な寸法と指定サイズの両方が存在しないとき、具体的なオブジェクトサイズを決定するのに使用される明確な幅と高さを持つ矩形である。 これは状況によって違うので具体的にどのサイズとは言えませんが、背景画像の初期オブジェクトサイズについては後ほど説明します。 グラデーションはグラデーションボックスと呼ばれる範囲内に描画される。グラデーションボックスとは、具体的なオブジェクトサイズの寸法である。 では次に背景として用いられるグラデーションの描画範囲はどのように決定されるかを見ていきます。 これを知るには、まず具体的なオブジェクトサイズ(つまりグラデーションボックス)がどのように決定されるかを知る必要があります。 これは「CSS Image Values and Replaced Content Module Level 3 - 5.3.1. Default Sizing Algorithm」に記載されています。 このアルゴリズムは次のように定義される。 背景として使われるグラデーションに指定サイズを指定するには、 ここでまた新しい用語が出てきました。コンテイン制約とは何か、です。 コンテイン制約とカバー制約の2つの共通指定サイズは、どちらもオブジェクトの本質的なアスペクト比を使用する指定された制約矩形に対して解決される。 どちらの場合でも、オブジェクトが本質的なアスペクト比を持たない場合、具体的なオブジェクトサイズは指定された制約矩形である。 ここでようやく前セクションのまとめで書いた「その指定サイズも存在しない場合、使用される状況に応じた初期オブジェクトサイズが用いられる」がどのように決定されているかが分かりました。 よって、背景として使用される、指定サイズを持たないグラデーションボックスは、グラデーションを指定する 次に ここで 背景配置領域は これでやっと最初の方に出てきた「グラデーションが背景に使用されるとき、初期状態でグラデーションが描画されるグラデーションボックスは要素のパディングボックスになる」の意味が分かりました。 背景として使用されるグラデーションはどの範囲に描画されるか。 以上で終わりですが、読み違えている可能性もありますので、気になる方は自分でも調べてみることをお勧めします。 たまに「グラデーションが あと、背景に使うグラデーションを指定するのは まだ実装はありませんが、グラデーションはグラデーションが描画される範囲について
仕様を見ると次のように書かれています。background-size
が100px 200px
のように明示されているなら、グラデーションボックスは100pxの幅と200pxの高さになるだろう。
同様に、グラデーションがlist-style-image
に使用されるとき、グラデーションボックスはそのプロパティの初期オブジェクトサイズ(default object size)である1emの正方形になるだろう。
分かるのは背景に使われるときの初期範囲がパディングボックスであるということくらいです。
それだけでも十分といえば十分ですが、調べたいのは「どうやって決まるのか」なので、更に読んでみます。用語について
本質的な寸法(intrinsic dimensions)
これらの本質的な寸法はオブジェクト自体の望ましい、または自然なサイズを表す。すなわち、それらはオブジェクトが使用されるコンテキストの機能ではない。CSSは本質的な寸法が一般的にどのように見つけられるかを定義しない。
拡大縮小されるように作られたSVG画像は、おそらく本質的なアスペクト比だけを持つだろう。また、SVG画像は本質的な幅または高さのみを持つように作られることもある。
この仕様(CSS Image Values and Replaced Content Module Level 3)で定義されているCSSグラデーションは、そもそも本質的な寸法を持っていないオブジェクトの一例である。もう一方の例として、HTMLでの<iframe>要素のような埋め込みドキュメントがある。
オブジェクトは2つの本質的な寸法のみを持つことはできない。たとえば2つの寸法から自動的に3つ目を定義するといったもの。
たとえば800×600のjpg画像なら、その本質的な寸法は800pxの幅、600pxの高さ、4:3のアスペクト比、となります。
またSVG画像はそのうち1つしか持っていない場合もあります、と。
そしてグラデーションは、幅も高さもアスペクト比も持っていません。指定サイズ(specified size)
width
やheight
またはbackground-size
プロパティなど、CSSから与えられるものである。
指定サイズは明確な幅と高さ、制約のセット、またはその組み合わせとなる。具体的なオブジェクトサイズ(concrete object size)
初期オブジェクトサイズとは何か、というのは次に説明します。
つまりこのサイズがグラデーションのサイズとなります。初期オブジェクトサイズ(default object size)
ここまでのまとめ
しかし、グラデーションそれ自体は寸法を持っていないオブジェクトなので、具体的なオブジェクトサイズが存在しない。
グラデーションに具体的なオブジェクトサイズを与えるには、CSSの指定によって指定サイズを与える必要がある。
その指定サイズも存在しない場合、使用される状況に応じた初期オブジェクトサイズが用いられる。背景として使用されるグラデーションのサイズはどのように決定されるか
前セクションの用語解説ではオブジェクトを使用するコンテキストにおける初期オブジェクトサイズでのオブジェクトの本質的な寸法と指定サイズを組み合わせた結果
とだけ書かれていますが、より詳しく見ていきます。background-size
プロパティを使用します。background-size
に50% 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
として扱われると書かれています。カバー並びにコンテイン制約サイジング
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つの値のうち一方のみに指定されたauto
が100%
として扱われる理由についてですが、デフォルトサイジングアルゴリズムにより、この値は初期オブジェクトサイズの幅または高さであります。background-size
による指定のないグラデーションの具体的なオブジェクトサイズはbackground-image
の初期オブジェクトサイズであり、それは背景配置領域のサイズでもあります。
そしてbackground-size
のパーセンテージ値は背景配置領域に対するパーセンテージです(背景の仕様参照)。
よって、デフォルトサイジングアルゴリズムの2つ目3番目が使用される、一方の値がauto
のbackground-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-image
やcontent
プロパティなどにも指定できることになっています。
一応、もうすぐWebkitで使えるようになります。-webkit-
接頭辞も外れます。