3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

GlobeeAdvent Calendar 2023

Day 22

Container QueryをVueに導入するときに考えたこと

Last updated at Posted at 2023-12-21

この記事は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で切り替えたいとき、 PageMainContents のどちらに書くべきか悩みました。

<Page class="page">
  <!-- SideNavigationは開閉する -->
  <SideNavigation />
  <MainContents>
    <Header />
  </MainContents>
</Page>
.page {
  display: flex;
}

結論、 MainContents に書くことにしました。 Page に書いてしまうと、Media Queryとあまり変わらないですし、 HeaderSideNavigation の開閉状態を知る必要がなく、 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も定期的に情報を取りに行かないとなと思う今日このごろです。ちゃんちゃん!(子供の最近の口癖)

  1. ブラウザのアップデートしづらい環境のユーザーを考慮

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?