overflow: overlay;

Google ChromeのDeveloper Toolsで要素のスタイルをいじっていたら、overflowプロパティにoverlayなる値があることを知った。インターネットをざっと検索した感じだとどうやらWebkit系のみで使えるようだ。

Developer Toolsでoverlay値を表示したキャプチャ

W3Cのoverflowの仕様( CSS2.1 Visual EffectsCSS Overflow Module Level 3CSS basic box model)を見てもoverlay値に関する記述はない。

検索結果を追っていくと、2009年にWebkit Bugzillaに投稿された overlay値に対する提案が見つかる。標準仕様になくWebkitでしか動かないなら削除するか-webkit-overlayのようにプリフィックスをつけてはどうかという主旨だが、やりとりの中で 2006年に-webkit-overlayをアンプリフィックスしたよというコメントがあって驚いた。8年前!えっじゃあ-webkit-overlayが実装されたのいつなんだろう。さらに、overlayはスクロールバーが発生しないので、イベントをトリガーしないという興味深いコメントもある。

Webkit Bugzillaでは2009年の投稿から2013年まで放置されてて、その後 JSFiddleにデモが置かれたのがきっかけかわからないけど、W3Cのスタイルのフォーラムにも overlayの話題が投稿された。

W3Cのフォーラムではなかなか盛り上がっていたようで マイクロソフトの独自実装のことも紹介されている(これも知らなかった!)。イベントのトリガーの件も議論されそうになったものの、overflowプロパティだけじゃなく他の仕様のことも併せて考えたほうがいいのではみたいな流れになって、最後にスクロールバーの計算方法についての提案のリンクが貼られてスレッドは終わっている。それから1年半ほど経つが、結局overlay値が標準化するでもなく、Webkitから削除されるでもリネームされるでもなく、現在も指定可能になっているという状況のようだ。

ブラウザで確認

さっそく一通りのブラウザで表示確認する。前提として、標準設定のMac OSとモバイルブラウザはスクロールバーがデフォルトで非表示であり、コンテンツがスクロール可能な場合はスクロールするとオーバーレイでスクロールバーが表示される。なのでそちらのキャプチャは撮っていない。Macで確認したい場合は 環境設定 -> 一般からスクロールバーを「常に表示」にすると良い。

JSFiddleの最初のデモはあまり見やすくないので、フォークしたもので確認した。左のボックスがoverlay、右はauto値が指定されている。JSFiddleの埋め込みが何も表示されていない場合はResultのタブを押せば出てくるはず。

OS / ブラウザ別の様子。左のボックスがoverflow: overlay、右はoverflow: autoを指定している。
Mac / Safari 7.0.5 Mac / Safari 7.0.5でのキャプチャ
Mac / Google Chrome 35 Mac / Google Chrome 35でのキャプチャ
Mac / Firefox 30 Mac / Firefox 30でのキャプチャ
Win / IE11 Win / IE11でのキャプチャ
Win / Google Chrome 35 Win / Google Chrome 35でのキャプチャ
Win / Firefox 30 Win / Firefox 30でのキャプチャ

Mac Chrome 35のキャプチャが一番わかりやすい。通常、overflowのスクロールバーはその要素幅の内側に表示されて、コンテンツ部分の幅が狭まる。しかしoverlay値を指定するとスクロールバーがコンテンツにかぶさるようになる。SafariやWin Chromeのキャプチャでは一見わかりにくいが、 改行された数字が1つ飛んでいるので、スクロールバーにかぶさった分が隠れていると推測できる。上記に埋め込んだjsfiddleのデモではresizeをつけているので、左右に動かしてみるとコンテンツにスクロールバーがかぶさる様子がわかると思う。

FirefoxとIEでは適応されていないが、その場合の挙動はautoではなくvisibleのようだ。overflowの初期値になるのではなく、無効なプロパティと解釈されてoverflowが宣言されていない状態かつ高さは100pxなのでコンテンツは下にはみ出る状態になる。規定のレンダリング。

ついでに -ms-autohiding-scrollbarも書いてみた。IE11で見たキャプチャは割愛するが、スクロールバーは出ずにvisible値と同じように表示されているように思う。これが正しい描画なのかわからない……。

イベントをトリガーしない?

イベントの件はどうだろうか。そもそも何のイベントについてなのかわからない。おそらくresizeだろうとあたりをつけてコードを書いたけどresizeイベントはwindow(viewport)しか持てないようで検出できなかった。そこでoverflowしているdivの中にもう1つdivを用意してDeveloper Toolsで確認したところ、auto値の方はスクロールバーが出現すると内包しているdivのwidthは小さくなり、overlay値の方はoverlayがない時とwidthが変わらなかった。

となれば、overlayを指定した要素は内包物の変化でwidthとheightが変わらないことになり、ブラウザレンダーのレベルで描画コストが低いと言えるような気がする。

任意の要素でresizeイベントが取れれば検証も簡単なのに。都度サイズを調査する関数を呼んでもいいけどなんか微妙な感じがするので書くのをやめた。

そもそもWebkit系のみ

overflow: overlay;があって嬉しい人はあまりいない気がする。現状ではすでにデフォルト設定のMac、iPhoneやAndroidではすでにスクロールバーは非表示だし、スクロールバーが表示される環境のChromeやSafariでもコンテンツ幅が狭まらないとは言え、要素がその分だけ隠れてしまう。隠れていても 横スクロールも発生しないし、領域をマウスデバイスなどでドラッグしても隠れている部分を見ることはできず、閲覧者に優しくない。いったいどういう理由でこの値は生まれたんだろうか。

overlay値は2006年にすでに使用可能だったわけだが、その頃はMacもまだスクロールバーはオーバーレイ表示ではなかった頃だったと思う。となるとスクロールバーを表示しなければならなくたった時にコンテンツ幅に不都合が生じる状況に対応するために都合主義的に実装されたのかもしれない。


効果と現状から言ってoverlay値がW3Cで標準化されることはなさそう。今回ふとしたきっかけでプロパティの値についての議論を追ってみたが、けっこう面白かったので何かでまたやりたい。