🖼️

[CSS]background-imageにカスタムプロパティを使用するとiOSで背景画像が表示されない不具合

2022/03/25に公開
2

2023/09/05 更新

気づいたら本件、不具合修正されていましたBugzilla も解決済みステータスに変更されています。
上記 Bugzilla のコメントで言及されている Web Platform Tests の見方がよくわからないぞ、どう見るんだ、 iOS バージョンいくつから直ったんだ。
とりあえず無事に修正されたようで良かったです。しかし、ここ1年以内で修正されたばかりであることには間違いないので、まだ気をつけた方が良いのは変わりないですね。

表示されない背景画像

カスタムプロパティを利用したCSS設計を使用しており、背景画像にもカスタムプロパティを使用していました。
下記は非常に簡素な例です。

.section-first { --image: url("../img/bg-1.jpg"); }
.section-second { --image: url("../img/bg-2.jpg"); }
.section { background-image: var(--image); }
<div class="section section-first"></div>
<div class="section section-second"></div>

するとなんということでしょう、iOSだけ背景画像が表示されないではありませんか。
iOSよ、またおまえか。

確認に使用したiOSのバージョンは 15.3.1 です。

iOSのバグ

おそらくカスタムプロパティを使ったことが原因なのだろうと推測はしていましたが、カスタムプロパティを使用したすべての背景画像が表示されないというわけではありませんでした
カスタムプロパティを使用していても正常に表示されている背景画像もありました

なので、単純に background-image とカスタムプロパティの組み合わせが良くないというわけではなく、他の要因も合わさった結果なのだと予想できます。
予想はできても、初めて出くわす現象に、検証や調査も含めてほぼ丸一日潰しました。

やっと見つけたのが下記です。
https://stackoverflow.com/questions/66752308/css-background-image-relative-path-var-on-safari-not-loading-image
そもそもこの不具合について言及している記事やフォーラムがほとんどなく、同様の現象を探すのに苦労しました。

さらに探すと、Bugzillaでも言及されていました。
https://bugs.webkit.org/show_bug.cgi?id=200092
これです、ドンピシャです。ちなみに記事を書いている2022年3月25日現在もまだ修正されていません。

不具合が起きる条件

さらなる検証を重ねました。単純に background-image とカスタムプロパティの相性だけの問題ではなさそうなので、他の要因も特定しないといけません。
先程のBugzillaによると、相対パスの解決に不具合があるとかなんとかっぽいので、まあよくわかりませんがそこら辺を調べたいと思います。

下記のようなディレクトリ構造のプロジェクトを作り、3つのCSSファイルと3つの画像を異なる階層に置きました。

root
├ index.html
├ style.css // CSS その1
├ image.png // 画像 その1
└ src
  ├ style.css // CSS その2
  ├ image.png // 画像 その2
  ├ css
  │ └ style.css // CSS その3
  └ img
    └ image.png // 画像 その3

それぞれのCSSファイルからそれぞれの画像を、カスタムプロパティを使用して背景画像として表示します。
CSSが3つと画像が3枚なので全部で9パターンです。

これをChromeで見た結果が下記の画像です。これが正常な表示になります。

同じものをiOSで見た結果が下記の画像です。9パターンのうち4パターンが正しい表示ではありません。

背景画像が表示されないどころか、なんと異なる階層にある画像まで読み込んでる始末でした。予想以上にひどい。

上記の結果から、iOSでは下記のような挙動をしていると予測をたてました。

  1. カスタムプロパティは表示しているHTMLの内部で定義していると認識される
    • 外部のCSSファイルで定義したとしても、HTML内部の <style> 要素内でカスタムプロパティを定義したことと同義になる
    • このとき url() で相対パスを記述していたとしても、相対パスは適切に解決されずそのままの値である
    • 相対パスの解決が狂っている原因その1
  2. カスタムプロパティで定義している相対パスの../が無視される
    • 例えば url('../../path/to/image.png')url('path/to/image.png') もしくは url('./path/to/image.png') だと認識される
    • 相対パスの解決が狂っている原因その2
  3. 上記の過程を経て得られた相対パスの画像を読みに行く

あくまで私の予想なのでご了承ください。しかし上記の過程を経たと考えると、先程の検証で画像が表示されなかったり異なる画像が表示された現象と合致します。

不具合を避ける方法

下記の4項目のうち、いずれか1項目の対処で不具合は起きなくなります。

background-image にカスタムプロパティを使用しない

そもそもカスタムプロパティを使用して発生している不具合なのだから、カスタムプロパティを使わなければ不具合は起きません。

before
background-image: var(--image);
after
background-image: url("../path/to/image.jpg");

画像のパスを絶対パスに変える

相対パスの解決に不具合があるので、絶対パスを使えば不具合は起きなくなります。

before
--image: url("../path/to/image.jpg");
after 1
--image: url("/path/to/image.jpg");
after 2
--image: url("https://example.com/path/to/image.jpg");

CSSをHTMLファイル内に記述する

CSSが外部ファイルであることも要因らしいので、HTMLファイルの中の <style> 要素にCSSを移植すれば不具合は発生しなくなります。

before
<head>
  <link rel="stylesheet" href="./css/style.css" />
</head>
after
<head>
  <style></style>
</head>

background ショートハンドを使用する

これは偶然発見した解決方法で、何がどうなって不具合が起きなくなるのかよくわかりません。
background-image プロパティではなく background ショートハンドプロパティに置換すると、不具合は発生しなくなりました。
これが一番良い解決策ではないかと思います。

before
background-image: var(--image);
after
background: var(--image);

おわり

iOSの不具合に対応するのはもういやだ。

Discussion

HieroglypHHieroglypH

同様の現象に遭遇しており、助かりました。ありがとうございます。
私の場合は、画像パスはカスタムプロパティにはしていませんでしたが、カラーコードをカスタムプロパティにして利用しており、それの組み合わせで発生していました。

background: url(../images/bg01.png) center 50% / 100% auto no-repeat, var(--color-main);

これだと画像が表示されません。ただ、--colo-mainで指定している背景色は表示されていました。

以下のようにすれば、問題なく表示されました。

/* カスタムプロパティの背景色指定を外す */
background: url(../images/bg01.png) center 50% / 100% auto no-repeat;

/* 画像パスをルート相対にする */
background: url(/assets/images/bg01.png) center 50% / 100% auto no-repeat, var(--color-main);

たしかに予測しておられるように、
htmlからの相対パスとして画像を読み込みしようとして失敗しているようでした。

なお、この現象を確認できたのは、iOS 14.3でした。
ただ、iOS 14.7では問題は確認できなかったという報告もありました。
本記事の現象を確認されたのが、iOS 15.3.1 とのことだったので、
画像パス自体をカスタムプロパティに使った場合のバグよりはもう少し早い段階で解消されたのかもしれません。

udyestudyest

コメントありがとうございます。
少しでもお役に立てたようでしたら何よりです。

私のケースでは background ショートハンドを使用したら解消されましたが、HieroglypH 様のケースは background ショートハンドを使用していても同様の現象が起きている上に背景色の方が原因とは、私のケースよりもさらに業が深そうな事象ですね……。
本当に困ったものです。