background / position

背景の画像の位置を固定する

─ Guide to page sections ─

背景の画像を固定してパララックスを実装する類の作成をしているが、大いに困惑する状況に陥った。初めに着手したのは「background-attachment: fixed」である。スマートフォンでは不具合が発生する。次に「position: fixed」、「position: sticky」と試していくのだが…。

完成イメージ
ページの起動で画像を表示、スクロールでコンテンツが迫上がり止まる

First

position: プロパティ

position は CSS のプロパティで、文書内で要素がどのように配置されるかを設定する。 top, right, bottom, left の各プロパティが、配置された要素の最終的な位置を決定する。

要素(画像)を固定するプロパティは以下の position プロパティの値の中で、「fixed」と「sticky」が該当する。

「position: fixed;」は、固定したい要素の width を指定したり、メインコンテンツに被らないように margin で空白を用意しなければならないというのが sticky との大きな違いである。 なお、stickyは、指定した要素内のコンテナ内でのみ固定される。

static

既定値。top, right, bottom, left, z-index プロパティの効果はない。

relative

top, right, bottom, left の値に基づいて自分自身からの相対オフセットで配置される。オフセットは他の要素の配置には影響を与えない。ページレイアウト内で要素に与えられる空間は、位置が static であった時と同じ。

absolute

要素は文書の通常のフローから除外され、ページレイアウト内に要素のための空間が作成されない。直近の配置されている祖先があれば、それに対して相対配置される。そうでなければ、初期の包含ブロックに対して相対配置され、最終的な位置は top, right, bottom, left の値によって決定される

fixed

ビューポートによって定められた初期の包含ブロックに対して相対配置されるが、一部の例外を除き、祖先が包含ブロックとしてふるまう。

sticky

要素は文書の通常のフローに従って配置され、直近のスクロールする祖先および包含ブロック (直近のブロックレベル祖先、表関連要素を含む) に対して top, right, bottom, left の値に基づいて相対配置される。「スクロールの仕組み」を持つ直近の祖先 (overflow が hidden, scroll, auto, overlay として作成されたもの) に「粘着」する。これによって「粘着」のふるまいを効果的に抑止する。


Second

vw とパーセント

例えば画像の高さを指定するときに、その単位に「vw」を使いたい。

ときに、100vw ≠ 100% である。

100vwが示す領域は、縦スクロールバーを含めたものを表示領域とする。だから、PC でスクロールバーをブラウザが表示したときに、100%を超えた表示となる。

スクロールバーの幅 = calc(100vw - 100%)

「calc(100vw - 100%)」でスクロールバーの幅を求めて、ビューポート幅(100vw)からスクロールバーの幅を引くと、100% のサイズと同等になる。

.full-area {
  width: calc(100vw - calc(100vw - 100%));
}
    

100vw ≠ 100% を確認する

検証用イメージ

実際に表示したものを見てみよう。幅が 100vw、幅が 100%、vw と calc()を使った 100% と同等のサイズを色別に表示した。

高さを「150vh」に設定したためブラウザは縦スクロールバーを表示、次に幅を「100vw」に設定したため、100%を超えた表示になるのでブラウザは画面下部にスクロールバーを表示した。そのスクロールバーを右端までドラッグして「100%」と「width: calc(100vw - calc(100vw - 100%));」が同等であることが確認できる。

ビューポートのサイズで画像を定義する

検証用イメージ

例えば、横×縦のサイズの画像が 2 : 1 だとしよう。その画像を横幅いっぱいに表示するとき、厳密にビューポートのサイズで定義をすると「style="width: calc(100vw - calc(100vw - 100%)); height: 50vw;"」になる。

上図のビューポートのサイズで定義したページを見る。


Third

background-size

background-size プロパティは以下のいずれか 1 つの方法で指定する。

キーワード

contain または cover のキーワード値を使用。

幅の値

幅の値のみを使用、この場合の高さは既定の auto になる。

幅と高さの値

幅と高さの値の両方を使用、この場合は 1 番目の値で幅を、2 番目の値で高さを設定する。どちらの値も <length>、 <percentage> または auto のいずれかになる。

background-size は CSS のプロパティで、要素の背景画像の大きさを変更し、画像の幅や高さから見た完全な大きさの画像をタイル表示するという既定の動作を変更することができる。こうすることで、画像を必要に応じて拡大したり縮小したりすることができる。

このページではキーワードではなく、「幅と高さの値」を使って表示してみよう。注視しなければならないのは、「background-attachment: fixed ;」を設定する要素の高さに何の単位を使うかである。

通常、画像を表示するだけならコンテナに対して幅の <percentage> を例えば「width: 100%;」などとして使用する。

背景の background-attachment の値が fixed の場合、配置領域はビューポート全体となる。

ということで、以下はビューポートを基準としたサイズの単位である。ビューポートとは表示領域のことで、ブラウザのウィンドウの画面のサイズだ。

vw

1% of viewport’s width。横幅のビューポートの1%分が1単位となる。

vh

1% viewport’s height。高さのビューポートの1%分が1単位となる。

vmin

1% of viewport’s smaller dimension。横幅と高さのビューポートの内、より小さい方の幅の1%分が、1単位となる。

vmax

1% of viewport’s larger dimension。横幅と高さのビューポートの内、より大きい方の幅の1%分が、1単位となる。

検証用の画像を作って確認する

検証用イメージ
イメージのサイズ width: 1000px; height: 500px; 升目を 横方向へ20 個

イメージの比率は「2 : 1」(width: 1000px; height: 500px; )で作成した。

「background-attachment: fixed ;」を設定すると、画像を表示させるためには高さが必要だ。レスポンシブを考えると、単位は「vw」が相応しい。高さは「35vw」になる。

PC に於いて、このページのイメージを配置する CSS には以下のように設定。

.fixed-area {
	background: url("images/jean.png") no-repeat;
	background-attachment: fixed ;
	background-size: 70vw;
	background-position: center;
	height: 35vw ;
	background-color: #ccc;
  }

Fourth

background-attachment

background-attachment とは画面のスクロールバーに合わせて、背景画像を固定表示するかスクロールさせるかを指定するプロパティであり、値は以下がある。

fixed

背景はビューポートに対する相対位置で固定される。要素がスクロール機構を持っていたとしても、背景画像は要素とともには動かない。 (これは background-clip: text とは両立できない)

local

背景はコンテンツに固定され、コンテンツと共にスクロールする。

scroll

背景は要素自身に固定され、コンテンツがスクロールしても背景はスクロールしない。)

background-attachment: fixed; のみでは、位置を固定できない。background-position、size、repeat なども設定する必要がある。

但し、スマートフォン(iPhone)向けには background-attachment: fixed; が不具合になる。「background-attachment: fixedとbackground-size: coverを同時に使うとiOSで問題が起きる」と Can I use.com に書かれている。

そこで、「background-attachment: fixed; スマートフォン解決策」で検索にかけると、多くが「 疑似要素を固定表示させる position: fixed」を使ったもの、少数だが「 position: sticky」を使ったものがある。


Fifth

position: sticky と position: fixed プロパティを使う

背景の画像を固定してパララックスを実装する作業を進めて感じたことは、「background-attachment: fixed;」に始まりその殆どが「background-attachment: fixed;」の不具合を解決する「position: fixed を使った(親要素へ疑似要素を指定し、その疑似要素を固定表示させる)解決策」で終わっているようだ。

他に 「position: sticky」も少数だがあった。実はこれが一番使い勝手が良い。

結局のところ、「background-attachment: fixed;」は出番がなく、存在意義自体が疑われることになった。そこで、「position: fixed;」、もしくは「position: stick;」を試すことになった。両者とも普通にプロパティを使えば簡単に実装できるようである。

「position: fixed;」の場合は、スクロール時の挙動をコントロールするために、テキストの収まるコンテナの高さを「100vh」に修正すると、スクロールがトップでピタッと止まる。

「position: sticky;」は、普通にこのプロパティを収めるだけで上手くいく。