calc()とvw単位を使った飛び出すpre要素

pre要素の背景をビューポートの幅まで拡大する

飛び出すpre要素っていうのは昔書いた描画領域一杯にpre要素の幅を拡大するテクニックと目指す見た目は同じもの。以前考えたものはちょっとの間使ったもののバグが多くすぐやめた。このテクニックは大きい要素を左右に付け、はみ出した部分を隠すというものだった。それをvw単位を使ってビューポートの幅を取り、それとcalc()を組み合わせることでどうにかしようという試み。

View Demo: Expand pre Element #2

pre要素の左右が#f0fの矩形で埋められている。Chrome 35、Firefox 30、そしてInternet Explorer 11で確認できる。Mobile Safari 7ではうまく動かない(多分vw単位の問題のような気がする)。わかりやすいように左右に追加する擬似要素の背景の色を変えておいたけど、同じ色にすればあたかもpre要素が飛び出すように見えるはず。

.test {
  margin-right: auto;
  margin-left: auto;
  position: relative;
  width: 480px;
}

.test:before,
.test:after {
  display: block;
  position: absolute;
  top: 0;
  width: calc((100vw - 100%) / 2);
  height: 100%;
  content: "";
  background-color: #f0f;
}

.test:before {
  right: 100%;
}

.test:after {
  left: 100%;
}

vw単位は1vwでビューポートの幅の1/100なので、100vwがビューポートの幅になる。calc()では%も使え、widthプロパティーでcalc(100%)とするとその要素の幅になる。つまりcalc(100vw - 100%)ビューポート幅からその要素の幅を引いた余りを計算できることになる。デモではpre要素は真ん中寄せなので単純にこれを半分にし、左右に追加する擬似要素の幅にすれば良い。高さは100%で自動的に揃うので計算不要。

左右に追加する擬似要素の位置調整はpositionプロパティーを使った相対配置内での絶対配置で行う。


だいたい問題なくてどんな状況でも使える解だと思ったんだけど、vw単位にスクロールバーの幅が含まれてしまうことによって起こる問題が解決できなそう。WindowsのChrome 35やInternet Explorer 11(デスクトップ版)などスクロールバーが浮いていないブラウザーでは、その幅分ずれてしまい水平スクロールバーが出るようになる。このvw単位などにおけるスクロールバーの解釈については、仕様に以下のように注意書きがある。

Note that the initial containing block's size is affected by the presence of scrollbars on the viewport.

5.1.2. Viewport-percentage lengths: the ‘vw’, ‘vh’, ‘vmin’, ‘vmax’ units

スクロールバーの有無に影響を受けるとなっているので、実装バグのような気がする。この辺りの扱いが直るまではスクロールバーの幅を決め打ちである程度確保してcalc()内で更に引く必要がありそう。

ただしInternet Explorer 11以降では-ms-overflow-style独自プロパティーでオーバーレイのスクロールバーに変更できるのでなんとか解決できる。

html {
  -ms-overflow-style: -ms-autohiding-scrollbar;
}

overflow-styleプロパティー自体は一時期いくつかの標準仕様に存在したんだけど、今はoverflowプロパティーへ統合された。元々overflowした時の内容物の扱われ方を定義するプロパティーだったようなので、スクロールバーの表示形式の変更に使うのは間違ってたりとかすることもあるので、独自プロパティーであることに目をつぶったとしても使わない方が良さそう。