Safariの「影の幽霊」を退治した話

GIFアニメの各 index ページをリニューアルしていた際、ちょっとした問題に直面しました。今回は、その解決までの記録を残しておこうと思います。

これらのページでは、CSS の columns(カラム) という段組み指定を使っています。 コンテンツを縦方向に優先して並べたかったためです。よく使われる flex(フレックス) では要素が左から右へ横並びになるため、今回のレイアウトには向きません。 新聞や雑誌のように「上から下へ流し込み、下まで行ったら自動で次の列へ」という構造にしたかったので、段組みを採用しました。

ところが、PC の Chrome や Edge では問題なく整って表示されるのに、iPhone の Safari で確認すると異変が起きていました。 画面を回転させると段組みが動く仕組みなのですが、本来あるはずのない場所に、ボックスの影だけがポツンと取り残されていたのです。

「影の幽霊」のスクショ:

影の幽霊1

セルの高さが不揃いなことも影響しているのか、前の列の影が移動後の列に“幽霊”のように残ってしまう。これこそが Safari のマルチカラムで発生する、最凶クラスの描画バグでした。

AI(Gemini)が提案した will-changeopacity: 0.99 など、さまざまな回避策を試してみましたが、私の環境ではどれも決定打になりませんでした。 試しに AI に「バグが起きるコード」を作ってもらって検証してみても、やはり同じように影が残ります。

AI が作った再現コードでのスクショ:

影の幽霊2

「もっと根本的で、簡単な見落としがあるんじゃないか?」そう思い、直感で適当にプロパティを組み合わせて試してみたところ、なんと数分で、あれほど頑固だった“影の幽霊”が消え去りました。

そのことを AI に伝えたら、「あ、それ、有名な解決策なんです」という驚きの回答が。……知っていたなら、なぜ最初に言わない?!

詳しく聞いてみると、このテクニックは海外のエンジニアコミュニティや、Safari のカラムバグと戦ってきた先人たちのブログに点在している、鉄板の回避策だったそうです。

【解決策】 Safari のマルチカラムで要素の分断や影の残留を防ぐための正解は、この 2 行でした。

CSS
.item {
  display: inline-block;
  width: 100%;
}

AI 曰く、display: block のままだと Safari は要素をどこで区切るかの計算中に影の描画範囲を忘れてしまうことがあるとのこと。 display: inline-block を指定することで要素を「独立した塊」として扱わせ、 さらに width: 100% を加えることでブロック要素の見た目を維持しつつ、本体と影をセットで正しく移動させられるようになるそうです。なるほど。

CSS のバグは環境や他のコードとの組み合わせにも左右されるため、これで 100% 直るとは言い切れません。 しかし、AI が生成したガタガタの再現コードでさえ、この 2 行を加えた瞬間にピタッと直りました。

もし今、Safari の「影の幽霊」に追いかけ回されている人がいたら、ダメ元でこの 2 行を試してみてください。