フルスクリーンでオーバーレイの検索ボックス

虫眼鏡アイコンをクリックすると、フルスクリーンかつオーバーレイで表示されるタイプの検索ボックス。

増えてきたフルスクリーンでオーバーレイの検索ボックスだが、まだこれといった無難な実装方法はないように見える。今だとvw/vh/vmin/vmax単位を使ってレイアウト、:target擬似クラスを使ってトグルという形にすれば、ほぼCSSで実現できそうだ。

Demo: Fullscreen Overlay Searchbox

デモではShow Searchboxというリンクをクリックすると検索ボックスが表示され、検索ボックスの左上にある✖をクリックすると閉じることができる。実際のウェブサイトではリンクの代わりに虫眼鏡のアイコンでも使ってやれば良いだろう。

マークアップ

<aside id="search" class="searchbox">
  <h1>Search this site</h1>

  <form>
    <input class="query" placeholder="Enter search keyword(s)" type="search">
  </form>

  <footer>
    <a class="close" href="#top">Back to Top</a>
  </footer>
</aside>

検索ボックスのマークアップはaside要素を使って、このような形にした。id属性は後に:target擬似クラスで利用するため、必須になる。

h1要素は冗長な気もするが、通常は隠れたセクションであることを考慮すると、見出しはあった方が良いだろう。label要素やinput type=submit"を使う必要がないフォームであることも考えると、このような一般的な文言で見出しを付けておくのが無難か。

閉じるボタンはa要素で#topに移動させるようにして実現するが、リンク文字列は「閉じる」や「Close」ではない方が良い。CSS側で✖に変えたりすることになるが、リンクそのものの機能としてはページの最上部に移動するという機能でしかないからだ。CSSが無効の時に「閉じる」というリンクで「ページの最上部に移動する」ことになるのがおかしいからというように考えても良いだろう。

フルスクリーン化

.searchbox {
  height: 100vh;
  left: 0;
  position: fixed;
  top: 0;
  width: 100vw;
}

検索ボックスのレイアウトではvwvh単位を使って描画領域全体と同じサイズになるようにして、フルスクリーンになるようにする。サイズさえ正しければposition: fixedで配置するだけで、きれいに全体にかぶさるはずだ。

閉じるボタン

.searchbox .close {
  display: block;
  font-size: 8vmin;
  height: 8vmin;
  left: 1vmin;
  position: absolute;
  top: 1vmin;
  width: 8vmin;
}

.searchbox .close::before {
  content: '✖';
  display: block;
  height: 100%;
  width: 100%;
}

閉じるボタンではvmin単位を使うことで占有する面積を一定以下に維持し、大きすぎる・小さすぎるがあまりないようにしておいた。font-sizeでも使えるので、うまく使ってやるときれいに文字(記号)を配置することができる。また、vwvhではなくvmin単位を使うことで、縦横のどちらが余っているのかわからない検索フォームの領域とかぶさらないようにもできる。そうすると閉じるボタンがクリックできないというような事故や検索フォームをクリアーするアイコンとかぶったというような事故を避けることができるはずだ。

もうひとつスクロールバーの有無という問題があるので、左上に配置すると簡単になる。スクロールバーの有無をCSSで判定するのは難しく、かといってそのためだけにJavaScriptを使うのももったいない。calc()を使うと何とかなるが、直観的ではない。近年のOSのGUIを考えると、閉じるボタンが右上というのももはや暗黙の了解とは言えなくなってきたので、左上でもわかりやすければ大丈夫だろう。

アイコン化は簡単にユニコードのDingbatsブロックのHeavy Multiplication Xを利用した。うかつに絵文字で良さそうなものを探すと予期せぬカラー化などが起こるので、こういったUIでおとなしめに使う場合はこの辺りの記号から選択すると良い。

検索ボックス

.searchbox .query {
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  font-size: 7vmin;
  left: 10vw;
  margin-top: -0.675em;
  position: absolute;
  top: 50%;
  width: 80vw;
}

検索フォームは縦横中央寄せをすることになる。transform: translate()を使って配置しても良いが、運が悪いと枠線や背景画像がぼやけてしまう。この場合はサイズが明確なので、絶対配置と負のマージンで配置する方が安定する。Flexboxも悪くないが、単純な縦方向のセンタリングには少し牛刀感がある。

左位置の指定や幅においてもvw単位を使うことで、前述の閉じるボタンとうまくマッチさせることができる。画面サイズに従ってある程度可変して欲しいフォント・サイズはvminを使って調節するのが簡単だ。メディア・クエリーを使ってビューポートのサイズで切り替えるのも悪くないがそこそこ手間がかかる。

トグルの実装

#searchbox {
  display: none;
}

#searchbox:target {
  display: block;
}

トグルの機能はフラグメント識別子と:target擬似クラスの組み合わせで簡単に実装できる。閉じるボタンのリンク先を#topにしてやると、それをクリック(タッチ)することで#search:targetを無効にできるため、うまいこと検索ボックスを閉じることができるというわけだ。ここでIDセレクターをちゃんと使うことで、フルスクリーンでオーバーレイにするビジュアル・デザインのためのルール群とトグルのためのルールを切り分けることができる。

デモでは検索ボックスを消した後に残るフラグメント識別子をhistroy.replaceState()を使って消しているが、これをやめればCSSのみでできるだろう。


フルスクリーンでオーバーレイの検索ボックスは、独立したコンポーネントとしてデザインしやすいのが大きな利点だ。そうデザインできることで、異なるデバイス間でも似た検索体験を提供でき、また違うプロジェクトでも再利用することも比較的容易になる。ここで作ったデモもほぼどこでも使えるように出来たと思う。

しかし独立したコンポーネントとしてデザインするためには、構造(HTML)として安定した形(独立したセクション)である必要があり、その上で前後の文脈や周辺の要素に依存しないようにCSSを書いていく必要がある。vwvhvminvmaxといった描画領域を基準にした単位は、親要素はもちろんbodyhtml要素のレンダリング状況を迂回してサイズを決定できるので、そういったCSSの書き方に大いに役に立つ。