background-positionのパーセント設定が分かりにくかった

タナビーの高梨です。

CSSでbackground-sizeを設定したうえでbackground-positionを設定したところ、最初思った場所に描画できなくて意味が分かりませんでしたが、ようやく理解できたので備忘代わりに記事にしておきます。

何が起こったか

例えば、幅1000px、高さ300pxの要素に対してbackground-sizeを高さ40%幅40%で設定したとします。

background-repeat: no-repeat;
background-size: 40% 40%;

この時、背景の大きさは当然ながらこうなります。
幅:1000×40%=400px、
高さ:300×40%=120px

ここまではOK。

ではこれに対してbackground-positionを設定したらどうなるか。

分かりやすいのはpxなど、絶対値で設定する場合。

background-position: 100px 100px;

この場合は疑う余地なく親要素の左から100px、上から100pxの位置に背景画像の左上がプロットされて描画されます。

こうですね。

で、問題はパーセントで設定した時。

例えば

background-position: 10% 10%;

としたら、普通どうなって欲しいかというと、こう。

なぜかというと、親の10%は幅、高さそれぞれ100pxと30pxだから。

top: 10%;
left: 10%;

のイメージです。

ところがなぜかこうなります。

どこから出てきた?60px?

調べて分かったこと

例によってchatGPTに聞いてみます。

計算によっては整数で割り切ることができず、ピクセルがずれることがあります。

by ChatGPT

話になりません。
さすが思考能力ゼロ。
信頼性全くなし。
40pxもずれてるのにピクセルがずれるって・・・・

そこでMDNを見たところ、このような記述がありました。

パーセント値について
指定された背景画像の位置のパーセント値のオフセットは、コンテナーに対して相対的なものです。 0% の値は、背景画像の左 (または上) の端がコンテナーの対応する左 (または上) の端に整列していることを意味するか、または、画像の 0% マークがコンテナーの 0% マーク上にあることを意味します。 100% の値は、背景画像の右 (または下) の縁がコンテナーの右 (または下) の縁と揃うか、または画像の 100% マークがコンテナーの 100% マーク上になることを意味します。したがって、水平方向または垂直方向に 50% の値を設定すると、画像の 50% マークがコンテナーの 50% マーク上になるので、背景画像が中央に位置することになります。同様に、 background-position: 25% 75% は、画像の左から 25%、上から 75% の位置にある点が、コンテナーの左から 25%、上から 75% の位置にあるコンテナーの点に配置されることを意味します。
(https://developer.mozilla.org/ja/docs/Web/CSS/background-positionから引用)

なんでこの手の文章は意地悪してわざと分からないように書くのでしょうか。

でも我慢して意味を解釈してみると、なるほど分かってきました。

要するに、簡単な日本語にすると、

「パーセントで指定された親の位置と、パーセントで指定された背景の位置が重なる」

ということでしょう。

図で表すとこうです。

そういわれてみれば

background-position: 50% 50%;

としたときに超スーパーど真ん中に置かれることを考えたら納得がいきます。

もし背景の左が親の50%に位置するとしたら、右半分にずれて表示されるはずです。

よく位置をずらして真ん中に持っていく時に、

left: 50%;
transform: translateX(-50%);

としますが、これをやらなくて良いようになっているということですね。

個人的にはbackground-positionも同じイメージにしてもらいたいところですが、そういうことらしいので仕方ありません。

とりあえず、仕組みは覚えました。

ちなみに、後からclaudeに聞いてみたところ

・10%の位置:60px(左から60px)
・50%の位置:300px(中央)
・100%の位置:600px(右端に背景画像が接する)
この仕組みにより、パーセンテージ指定で背景画像が常にコンテナ内に収まるようになっています。

なるほど、100%の位置が600pxだから10%は60pxなのか!
分かりやすい!
君は優秀だ!

結論

chatGPTには聞かない。

最初からclaudeに聞く。