この記事はGlobeeアドベントカレンダー22日目の記事です。
AI英語教材 abceed(エービーシード)のWeb版のフロントエンド開発をしている蔵下です。みなさんはContainer Queryを使っていますか? 主要ブラウザでサポートされてから1年近くが経ち、弊社でもいよいよプロダクトに使っていこうという機運が高まっています1。
今回は、Container QueryをVueに導入するときに考えたことを紹介します。
Container Queryとは
今までレスポンシブな画面の実装はMedia Queryを使用していました。Media QueryはWindow幅を基準にCSSを切り替えるため、VueなどのJavaScriptフレームワークで実装するComponentの粒度には合わず、ComponentごとにCSSを切り分けることが難しい状況でした。
そこに登場したのがContainer Query。その名の通りContainer単位で幅や高さを監視し、CSSの切り替えが可能となるため、Component指向な実装にぴったりです。
Container Queryの詳しい解説は、記事「CSS コンテナクエリ(@container)の基礎知識と便利な使い方を解説」をご覧ください。
Container QueryをVueに導入するときに考えたこと
さて、そんなContainer QueryをするっとそのままVueに突っ込んでいいのか、導入前に少し考えてみました。今までも、新しいCSSを使いたいけどJavaScriptフレームワークには合わないな...ということも多々あったためです。
container-type
はどこに書くか?
container-typeを指定することで、Container Queryの監視対象になり、指定した要素のwidthによってCSSを切り替えることができるようになります。下記のような画面で Header
のCSSをContainer Queryで切り替えたいとき、 Page
と MainContents
のどちらに書くべきか悩みました。
<Page class="page">
<!-- SideNavigationは開閉する -->
<SideNavigation />
<MainContents>
<Header />
</MainContents>
</Page>
.page {
display: flex;
}
結論、 MainContents
に書くことにしました。 Page
に書いてしまうと、Media Queryとあまり変わらないですし、 Header
は SideNavigation
の開閉状態を知る必要がなく、 MainContents
のwidthのみ見ていたいからです。
下記のCSSで、 MainContents
のwidthが400px以下で Header
内のflex-directionが切り替わるようになります。
/* MainContents */
.main-contents {
container-type: inline-size;
}
/* Header */
.header {
display: flex;
}
@container (width <= 400px) {
.header {
flex-direction: column;
}
}
もし、画面のレイアウトが変更などで Page
のwidthで切り替えたくなったら、 Header
内のCSSは触らずに、 MainContents
のcontainer-typeを Page
の方に移すだけで対応できます。
container-name
を指定するべきか?
親Componentを飛び越えて先祖Componentで container-type
を指定している場合、子ComponentからはどのComponentを基準にしているかわからない状況になります。これを解消するためにcontainer-nameでnameを設定し、子Component側で直接監視対象を指定することができます。
/* MainContents */
.main-contents {
container-type: inline-size;
/* main-contentsは任意のname */
container-tame: main-contents;
}
/* Header */
.header {
display: flex;
}
@container main-contents (width <= 400px) {
.header {
flex-direction: column;
}
}
この container-name
をContainer Query使用時に必須にするかどうかを考えました。結論、任意でOKということにしました。下記が理由です。
-
container-type
の指定は親Componentに指定することが多く、nameが無くても判断できることが多い - もし親Componentではなく、先祖Componentに
container-type
を指定する場合はcontainer-name
を指定する方が子Component側でどこを監視しているのかわかりやすくなりそう -
container-name
を必須にすると、設定したnameの管理をsass等でしっかりしないと運用がしんどそう
container-name
を必須にした方が監視元を特定できるメリットはありますが、実際に使ってみると、旨味以上に管理のしづらさを感じました。そのため、良い管理方法が見つかるまで container-name
の使用は任意としました。
まとめ
Container Queryは今の時代の実装に即した無くてはならない機能になると考えています。サンプルでしれっと使っていたCSSの比較演算子もサポートされて1年近くになるため、積極的に使っていく予定です。
JavaScriptやフレームワークのネタだけではなく、CSSも定期的に情報を取りに行かないとなと思う今日このごろです。ちゃんちゃん!(子供の最近の口癖)
-
ブラウザのアップデートしづらい環境のユーザーを考慮 ↩