Unformed Building

背景として使用される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×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 autocontainとして扱われると書かれています。

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

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

コンテイン制約とカバー制約の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-接頭辞も外れます。