CSS メーソンリーの代替案

Chrome チームは、メーソンリー タイプのレイアウトをウェブで実装したいと考えています。しかし、WebKit の最近の投稿で提案されているように、CSS グリッド仕様の一部として実装するのは間違いだと考えられます。また、WebKit の投稿は、誰も提案しなかったメイソン バージョンに反論しているとも考えられます。

そこでこの投稿では、Chrome が CSS グリッド レイアウト仕様の一部としてメーソンリーを実装することに懸念を抱いている理由を説明し、代替案で何が可能になるかを明確にすることを目的としています。要するに、

  • Chrome チームは、メーソンリーの課題を解消したいと考えています。
  • グリッドの仕様にメーソンリーを追加する際には、メーソンリーがグリッドであるかどうか以外の理由で問題が生じます。
  • グリッドの仕様の外部でメーソンリーを定義しても、メーソンリーの複数のトラックサイズ、およびグリッド レイアウトで使用されるアライメントやギャップなどのプロパティの使用は防止されません。

組積造をグリッドに含めるべきか?

Chrome チームは、メーソンリーは、display: masonry(または別のキーワードを優先して別のキーワード)を使用して定義する個別のレイアウト メソッドであるべきだと考えています。この投稿の後半では、実際のコード例をいくつか紹介します。

メーソンリーがグリッド レイアウト外で定義される可能性が高いと考えられる理由が 2 つあります。1 つはレイアウト パフォーマンスの問題の可能性、もう 1 つはメーソンリーとグリッドの両方に、1 つのレイアウト方法では意味のある機能があり、もう 1 つのレイアウト方法では意味をなさない機能があることです。

パフォーマンス

グリッドとメーソンリーは、ブラウザのサイズ設定と配置の点で逆です。グリッドがレイアウトされると、すべてのアイテムがレイアウトの前に配置され、ブラウザは各トラックの内容を正確に認識します。これにより、グリッドで非常に役立つ複雑な固有のサイズ設定が可能になります。メーソンリーでは、アイテムは並んだ状態で配置されるため、ブラウザは各トラックにあるアイテムの数を認識しません。これは、すべての固有のサイズのトラックまたは固定サイズのすべてのトラックで問題になるのではなく、固定のトラックと固有のトラックを混在させる場合に起こります。この問題を回避するには、ブラウザは測定値を取得するために可能な限りあらゆる方法ですべてのアイテムをレイアウトする事前レイアウト ステップを行う必要があります。大きなグリッドでは、レイアウトのパフォーマンスの問題を引き起こす可能性があります。

そのため、メイソンリー レイアウトにトラックの定義(グリッドで行う一般的な処理)を grid-template-columns: 200px auto 200px にすると、問題に遭遇します。これらの問題は、サブグリッドを追加すると指数関数的に増加します

ほとんどの人はこのような状況に遭遇しないという議論もありますが、グリッドはとても大きいことは周知の事実です。別の方法があるときに、使用方法に制限があるものをリリースすることは望ましくありません。

各レイアウト メソッドで意味をなさないものについては、どのように対処すればよいでしょうか。

Flexbox とグリッドが CSS の一部となったとき、デベロッパーはしばしば、動作が一貫していないと感じていました。このような不整合は、ブロック レイアウトに基づくレイアウトの仕組みに関する長い間前提であったことが原因でした。時間の経過とともに、デベロッパーは書式設定のコンテキストを理解し始めています。グリッドまたは Flex の書式設定コンテキストに切り替えると、一部の動作が異なります。たとえば、Flexbox を使用する場合、Flexbox は 1 次元なので、すべてのアライメント方法を使用できるわけではありません。

メーソンリーをグリッドにバンドルすると、書式設定のコンテキストと、書式設定のコンテキストごとの Box Alignment の仕様で定義される配置プロパティなどの可用性との明確なリンクがなくなります。

組み込みトラックと固定トラックの混合定義をメーソンリーで違法にすることで、前述のパフォーマンスの問題に対処する場合、グリッド レイアウトのごく一般的なパターンはメーソンリーでは機能しないことを覚えておく必要があります。

メーソンリーでは意味のあるパターンもあります。たとえば、grid-template-columns: repeat(auto-fill, max-content) などです。これは、交差制約はないものの、グリッドでは無効なままにする必要があるためです。次のリストは、動作が異なることが想定されるプロパティ、または有効な値が異なるプロパティのリストです。

  • grid-template-areas: メーソンリーでは、最初の行は非メーソンリー方向にのみ指定できます。
  • grid-template: 省略形ではすべての違いを考慮する必要があります。
  • 正当な値の違いにより、grid-template-columnsgrid-template-rows のサイズ値をトラッキングします。
  • grid-auto-flow はメーソンリーには適用されず、masonry-auto-flow はグリッドには適用されません。マージすると、使用しているレイアウト メソッドに合わないという問題が発生します。
  • グリッドには 4 つのプレースメント プロパティ(grid-column-start など)がありますが、メーソンリーには 2 つしかありません。
  • グリッドでは justify-* プロパティと align-* プロパティの 6 つすべてを使用できますが、メーソンリーでは Flexbox などのサブセットのみを使用します。

また、grid-with-masonry または grid-without-masonry で無効な値を使用しているデベロッパーによって引き起こされるすべての新しいエラーケースで何が発生するかを指定する必要もあります。たとえば、grid-template-columns: masonry または grid-template-rows: masonry は使用できますが、両方を同時に使用することはできません。両方を同時に使用するとどうなりますか? すべてのブラウザで同じ処理が行われるように、これらの詳細情報を指定する必要があります。

これは、現在も将来も、仕様の観点から見ると複雑になります。すべての作業について、組積造が機能するかどうかを考慮する必要があります。デベロッパーの観点から見ると 混乱を招くとも言えますdisplay: grid を使用しているにもかかわらず、メーソンリーを使用している場合に動作しないものがあるということを頭に入れておく必要があるのはなぜですか?

別の提案

すでに説明したように、Chrome チームはグリッド仕様の範囲外でメーソンリーを定義したいと考えています。これは、同じ列サイズを持つ非常にシンプルなレイアウト メソッドに限定されるという意味ではありません。WebKit 投稿のデモはすべて、引き続き行うことができます。

クラシックな組積造のレイアウト

多くの人がメーソンリーといえば、同じサイズの複数の列を持つレイアウトを思い浮かべます。これは次の CSS を使用して定義します。そのためには、同等のグリッド バンドル バージョンよりも行数の少ないコードが必要です。

.masonry {
  display: masonry;
  masonry-template-tracks: repeat(auto-fill, minmax(14rem, 1fr));
  gap: 1rem;
}

トラックのサイズが同じ。

さまざまな列幅に対してグリッドタイプのトラックサイズを使用する

前述の固有のトラック サイズと固定トラック サイズが混在する問題以外にも、グリッドから好みのトラック サイズをすべて使用できます。WebKit のブログ投稿の例のように、幅の狭い列と広い列を繰り返すパターンです。

.masonry {
  display: masonry;
  masonry-template-tracks: repeat(auto-fill, minmax(8rem, 1fr) minmax(16rem, 2fr)) minmax(8rem, 1fr);
  gap: 1rem;
}

幅が広く、幅の狭いトラックのパターン。

メーソンリー用の追加のトラックサイズ

グリッドは 2 次元のレイアウト方法であるため、グリッドでは許可されない追加のトラックサイズ変更オプションがあります。これらはメーソンリーでは便利ですが、グリッドでは機能しない場合は混乱します。

max-content サイズのトラックを自動入力しています。

.masonry {
  display: masonry;
  masonry-template-tracks: repeat(auto-fill, max-content);
  gap: 1rem;
}

auto サイズのトラックを自動入力します。同じサイズのトラックを作成し、最も大きいトラックに合わせてサイズが自動的に調整されます。

.masonry {
  display: masonry;
  masonry-template-tracks: repeat(auto-fill, auto);
  gap: 1rem;
}

オートサイズの線路を使用した組積造。

コンテンツが複数の列にまたがるようにし、アイテムをメーソンリー レイアウトに配置できるようにする

別のメーソンリー仕様で列にまたがるコンテンツを用意しない理由はありません。この場合、メーソンリー レイアウトでは 1 つのディメンションしかスパンできないため、masonry-track-startmasonry-track-end の省略形である masonry-track プロパティを使用できます。

.masonry {
  display: masonry;
  masonry-template-tracks: repeat(auto-fill, auto);
}

.span-2 {
  masonry-track: span 2; /* spans two columns */
}

.placed {
  masonry-track: 2 / 5; /* covers tracks 2, 3, and 4 */
}

配置されたアイテムとスパンアイテムが積み重なった組積造。

組積造の線路を採用した部分組積造または副送電網

これは別のメーソンリー仕様でサポートできますが、組み込みのトラックと固定サイズのトラックを混在させることは禁止されています。正確にどのようなものかを定義する必要があります。これがうまくいかない理由はありません

おわりに

相互運用可能な形で提供できる仕様に到達したいと考えています。ただし、Google は、現在と将来にわたって問題なく機能し、デベロッパーが信頼できる方法でそれを実現したいと考えています。ここで説明したパフォーマンスの問題に対処する唯一の方法は、2 つ目の問題(グリッドの一部が組積造で違法となる)を悪化させることです。特に、異なるものを明確に分離しつつ、必要なすべてのグリッド機能を使用できる場合は、これは良いソリューションとは言えません。

フィードバックがある場合は、問題 9041 のディスカッションにご参加ください。

この投稿のレビューとそれに寄与したディスカッションについて、Bramus、Tab Atkins-Bittner、Una Kravets、Ian Kilpatrick、Chris Harrelson に感謝します。