280blockerはiOS Safariにユーザースタイルを追加する

CSS

ハンドルネームつながりで越智建設のウェブサイトを見ていたら、手元の iPhone でページが真っ白で何も見えない状態だった。

ochikensetsu.co.jpにアクセスした画面。読み込みは完了しているが画面は白いままになっている。サーバーエラーでもなさそうだ。

macOS Safari で USB 接続デバッグをすると、fontplus.js でエラーが出てるとか<meta content="viewport">の値がカンマ区切りであるべきところがセミコロン区切りになってるとかあったが、だからと言って何もレンダリングされないのはおかしいだろうと思って首を傾げた。

そこで要素に当たってるスタイルをちゃんと洗っていたら、class="ad-preview-smart"ユーザースタイルが適用されているのに気づいた。

[class^="ad-"]:not(body) {
  display: none !important;
}

泣く子も黙るdisplay: none !importantである。しかも前方一致の属性セレクタである。

iOS Safariでochikensetsu.co.jpを閲覧してmacOS SafariからWebインスペクタを使ってスタイルを確認した。するとdisplay:none!importantが適用されているdivがあるのがわかった。

注目すべきはこのスタイルのオリジンがユーザースタイルであること。UA スタイルでもなくウェブサイトが読み込んだスタイルでもない。iOS Safari にはデフォルトでユーザースタイルを設定できる機能はない。ここでようやく外部アプリの介入に思い至った。そういえばそんなアプリを入れた記憶がある。

広告非表示アプリ 280blocker

280blocker とは Safari を利用中に出る広告をある程度ブロックしてくれるアプリ。インストールすると全てではないが確かに広告の表示は減る。

このアプリが原因かどうかを探るのは簡単だった。アプリを起動するともう設定画面なので、「広告ブロック」をトグルするだけ。もしくはホワイトリストにドメインを登録してもいい。

iOS版280blockerを起動した画面。広告だけでなくSNSなどのアイコンも非表示にする機能がある。

広告ブロック機能をオフにしてから件のウェブサイトにアクセスすると、きちんと表示された。

ナビゲーションやコンテンツが表示されている。これが越智建設のあるべき姿である。さしずめOchi Prideと言ったところか。

Web インスペクタで確認すると、class="ad-preview-smart"に当たっていたdisplay: none !importantがなくなっている。やはりこのアプリが原因とみて良さそうだ。

280blockerで広告ブロックをオフにしてから越智建設にアクセスし、Webインスペクタでスタイルを確認すると、当該要素にユーザースタイルが適用されていないことがわかった。

一応検証用に[class^="ad-"]がたくさんある検証ページを作った。280blocker で広告ブロックを有効にしていると TKG 写真が一枚も表示されない。

https://output.jsbin.com/biyonupupu

上記リンクの HTML ソースを抜粋するとこうなっている。

<body>
  <h1>280blockerで広告ブロックを有効にしている時に写真が表示されないかテスト</h1>
  <p>280blockerが有効だと <code>ad-</code> で始まるクラス名の要素が非表示になる。</p>
  <img src="https://picsum.photos/200/301" class="ad-tkg">
  <img src="https://picsum.photos/200/302" class="ad-da">
  <img src="https://picsum.photos/200/303" class="ad---">
  <img src="https://picsum.photos/200/304" class="ad-01">
  <img src="https://picsum.photos/200/305" class="ad-">
</body>

[class^="ad-"]:not(body) {display: none !important} が適用されていれば TKG 写真は一枚も表示されないだろう。

このアプリがどういう仕組みで広告をブロックしてるのか知らなかったけど、それっぽいセレクタをdisplay: none !importantしているとは思わなかった。確かにこれなら要素内のリソースは通信しない。

と言うことで、広告ではない要素にad-なクラス名をつけると 280blocker のようなツールが要素を非表示にしてしまう可能性があるという事例だった。このことは覚えておいた方が良さそうだ。