生成されたコンテンツとCSSグリッドレイアウトを使用した空のセルのスタイリング

公開: 2022-03-10
簡単な要約↬冗長な空の要素を追加せずに空のグリッドセルのスタイリングを実現する方法を考えたことはありますか? そうですね、CSS生成コンテンツはまさにそれを行うのに役立ちます。

一般的なグリッドレイアウトの落とし穴は、レイアウトメソッドの初心者が、コンテンツを含まないグリッドセルのスタイルを設定する方法を考えている場合です。 現在のレベル1仕様では、空のグリッドセルまたはグリッド領域をターゲットにしてスタイルを適用する方法がないため、これは不可能です。 つまり、スタイリングを適用するには、要素を挿入する必要があります。

この記事では、CSS生成コンテンツを使用して、冗長な空の要素を追加せずに空のセルのスタイルを設定する方法を見て、この手法が理にかなっているいくつかのユースケースを示します。

BFCを詳しく見る

CSSを使用してレイアウトを作成したことがある場合は、おそらくBFCが何であるかを知っているでしょう。 なぜそれが機能するのか、そしてそれを作成する方法を理解することは有用であり、CSSでレイアウトがどのように機能するかを理解するのに役立ちます。 関連記事を読む→

空のエリアをすでにスタイリングできないのはなぜですか?

グリッド仕様の冒頭の段落には、次のように書かれています。

「このCSSモジュールは、ユーザーインターフェイス設計用に最適化された2次元グリッドベースのレイアウトシステムを定義します。 グリッドレイアウトモデルでは、グリッドコンテナの子を、事前定義されたフレキシブルまたは固定サイズのレイアウトグリッドの任意のスロットに配置できます。」

ここでのキーワードは「グリッドコンテナの子」です。 この仕様では、子アイテムを配置できる親要素でのグリッドの作成を定義しています。 それはそのグリッドのスタイルを定義せず、Multi-columnLayoutにあるcolumn-ruleプロパティのようなものを実装することさえしません。 グリッド自体ではなく、子アイテムのスタイルを設定します。そのため、そのスタイルを適用するには、何らかの要素が必要になります。

ジャンプした後もっと! 以下を読み続けてください↓

スタイリングフックとしての冗長要素の使用

スタイルに何かを挿入する1つの方法は、スパンやdivなどの冗長要素をドキュメントに挿入することです。 開発者は、フロートを使用してグリッドレイアウトを実現するために、冗長な「行ラッパー」を何年も追加しているにもかかわらず、このアイデアを嫌う傾向があります。 おそらく、明らかに空の要素は、ラッパー要素のやや隠された冗長性よりも不快です!

この例が示すように、完全に空の要素はグリッドアイテムになり、コンテンツを含む要素と同じように背景と境界線を追加できます。

CodePenのRachelAndrew(@rachelandrew)によるPenEmpty要素がグリッドアイテムになるのをご覧ください。

CodePenのRachelAndrew(@rachelandrew)によるPenEmpty要素がグリッドアイテムになるのをご覧ください。

Eric Meyerは、A ListApartの記事FauxGrid Tracksで、 b要素を冗長な要素として使用することを提唱しています。これは、意味的な意味を与えないため、短く、フックとしてのマークアップでもかなり明白です。

追加のいくつかのdivまたはb要素を挿入することは、これまでにコミットした優れたマークアップに対する最大の犯罪になる可能性は低いため、必要に応じてそのアプローチを選択することで眠りを失うことはありません。 Web開発では、より良いソリューションが考案されるまで、仕事を遂行するための最適ではないアプローチを選択することがよくあります。 ただし、可能であれば、スタイルシートで安全にスタイリングを1か所に保持することをお勧めします。 他に何もないとしても、追加の必要なマークアップについて心配する必要がなく、スタイルの再利用が容易になります。 このため、私は生成されたコンテンツに目を向ける傾向があります。これは、CSSを使用して本をフォーマットする作業でよく知っていることであり、ほとんどの時間をこの機能の操作に費やしています。

生成されたコンテンツをスタイリングフックとして使用する

CSSで生成されたコンテンツは、 ::beforeおよび::after CSS疑似クラスをcontentプロパティとともに使用して、ある種のコンテンツをドキュメントに挿入します。 コンテンツを挿入するという考えは、これがテキストを挿入するためのものであると思わせるかもしれません。これは可能ですが、私たちの目的では、グリッドコンテナの直接の子として空の要素を挿入することに関心があります。 要素を挿入すると、スタイルを設定できます。

次の例では、グリッドコンテナになる包含要素があり、その中に別の要素がネストされています。 この単一の直接の子はグリッドアイテムになります。 コンテナに3列3行のグリッドを定義し、グリッド線を使用して単一のアイテムを配置したので、中央のグリッドセルに配置されます。

 <div class="grid"> <div class="item"></div> </div>
 .grid { display: grid; grid-template-columns: 100px 100px 100px; grid-template-rows: 100px 100px 100px; grid-gap: 10px; } .grid > * { border: 2px solid rgb(137,153,175); } .item { grid-column: 2; grid-row: 2; }

この例を見ると、Firefoxグリッドインスペクターを使用してグリッド線をオーバーレイすると、グリッドの他の空のセルがどのように存在するかを確認できますが、それらに背景または境界線を追加するには、子を追加する必要があります要素。 これはまさに生成コンテンツが可能にするものです。

グリッドの中央のセルにある単一のアイテム
Firefoxグリッドインスペクターでトラックが強調表示された単一のグリッドアイテム

CSSで、グリッドコンテナの::before::afterに空の文字列を追加します。 これらはすぐにグリッドアイテムになり、コンテナを埋めるためにストレッチします。 次に、ボックスに必要なスタイルを追加します。この場合は背景色を追加し、通常のグリッドアイテムと同じように配置します。

 .grid::before { content: ""; background-color: rgb(214,232,182); grid-column: 3; grid-row: 1; } .grid::after { content: ""; background-color: rgb(214,232,182); grid-column: 1; grid-row: 3; } 
グリッドの中央のセルに1つのアイテムがあり、隅に2つの緑色のアイテムがあります
1つのグリッドアイテムと、生成されたコンテンツである2つのアイテム

このドキュメントにはまだ子要素が1つしかなく、冗長なスタイリング要素はCSS内に含まれています。これは、スタイリングの目的でのみ存在するため、完全に合理的と思われます。

生成コンテンツアプローチの制限

このアプローチの明らかな問題は、右上と左下のグリッドセルもスタイル設定する場合に明らかになります。 生成されたコンテンツの1つだけをコンテナーの上部と下部に適用できます。複数の::beforeおよび::after疑似要素は許可されていません。 CSSグリッドチェッカーボードを自分で作成する場合、このメソッドは機能しません。 多くの空のセルのスタイリングを行う必要があることがわかった場合は、当面の間、上記で説明した「フィラーB」のアプローチが最善の策となる可能性があります。

生成されたコンテンツメソッドは、プロジェクトに取り組んでいる将来の開発者を混乱させる可能性もあります。 コンテナを対象としているため、そのクラスを他の場所で再利用すると、生成されたコンテンツが一緒に表示されます。これは、必要な場合に役立ちます。 次の例では、見出しの両側に装飾的な線を追加しましたh1のすべてのインスタンスにそれらの線があるのは合理的です。 ただし、これが発生することに気付いていなかった場合は、非常に混乱します。 コンテナルールの上のコメント行がここで役立ちます。 私は最近、パターンライブラリで作業する傾向があります。これは、これらのコンポーネントを1つの場所で適切に処理し、クラスが要素に適用されたときに何が起こるかをより明確にします。

派手な見出し

私のお気に入りの生成コンテンツのトリックの1つは、見出しのスタイルを設定することです。 以前は、達成するために追加のラッパーと絶対測位トラックを必要とする見出しスタイルを押し戻す必要がありました。 コンテンツがCMSからのものである場合、それらの冗長ラッパーを追加することはしばしば不可能です。

グリッドと生成されたコンテンツを使用すると、マークアップを追加せずに、見出しの両側に行を追加できます。 グリッドがブラウザで使用できない場合、線は使用可能なスペースに応じて拡大および縮小し、プレーンな中央のヘッダーにエレガントにフォールバックします。

両側に行があり、その後にテキストが続く見出し
実現したい見出しスタイル

マークアップは単純なh1です。

 <h1>My heading</h1>

h1のルールでは、3列のグリッドを作成します。 grid-template-columnsの値は、 1frのトラックを示し、次にautoのトラックと1frの最終トラックを示します。 2つの1frトラックは、見出しがautoサイズのトラック内に配置する必要のあるスペースを取得した後に残った利用可能なスペースを共有します。

グリッドのないブラウザで見出しを入力するために、 centerの値でtext-alignプロパティを追加しました。

 h1 { text-align: center; display: grid; grid-template-columns: 1fr auto 1fr; grid-gap: 20px; }

次に、生成されたコンテンツを追加して、見出しテキストの前後に行を追加します。 これらのルールを機能クエリでラップしているので、グリッドレイアウトのないブラウザーで奇妙な生成コンテンツを取得することはありません。

線自体は、生成されたアイテムの境界線です。

 @supports (display: grid) { h1:before, h1:after { content: ""; align-self: center; border-top: 1px solid #999; } }

それがあなたがする必要があるすべてです! 同じ手法を使用して、要素の上または下の要素の両側にスタイルを追加したり、アイコンを追加したりすることもできます。 アイテムを別のトラックに配置することで、アイテムが見出しのテキストと重なる可能性がないことがわかります。これは、絶対的な位置でこの種のことを行おうとすると問題になる傾向がありました。 また、アイテムをグリッド内で互いに整列させることができる正確な方法の利点もあります。

CodePenのRachelAndrew(@rachelandrew)によるペン生成コンテンツの見出しの例を参照してください。

CodePenのRachelAndrew(@rachelandrew)によるペン生成コンテンツの見出しの例を参照してください。

これは、グリッドレイアウトを使用して可能な拡張機能の良い例であり、グリッドを使用した大規模な再設計に進む準備ができていない場合でも利用できます。 それは非常にわかりやすい見出しにフォールバックし、ブラウザをサポートしている人は余分なタッチを取得し、誰もがコンテンツを取得します。 同様のアプローチがEricMeyerによって採用され、生成されたコンテンツを使用して、簡単にスタイル設定および配置可能な引用符をブロック引用符要素に追加しました。

これらの小さな機能では、グリッドレイアウトを使用することを考え始めないことがよくあります。 自分のデザインをどのように実装するかを理解し始めると、それが選択するレイアウト方法であることがわかります。 このため、グリッドをコンポーネント上のページレイアウトとして考えないように勧めます。そうすると、役立つ機会をたくさん逃してしまう可能性があります。

デザインの領域に背景と境界線を追加する

生成されたコンテンツを使用してアイテムを積み上げることもできます。 実際には、複数のアイテムが特定のグリッドセルを占有する可能性があります。 これには、生成されたコンテンツとともに挿入されたアイテムを含めることができます。

次の例では、2つのコンテンツセクションと全幅のアイテムを含むデザインがあります。 コンテンツの背後には、全幅のアイテムの下にもある背景があります。

全幅画像を使用した単一列レイアウト
私たちが目指しているレイアウト

マークアップには、直接の子としてセクションと全幅要素を含むコンテナーがあり、ラインベースの配置を使用してアイテムをグリッドに配置しています。

 <article class="grid"> <section class="section1"> <p>…</p> </section> <div class="full-width"> <img src=“placeholder.jpg” alt=“Placeholder”> </div> <section class="section2"> <p>…</p> </section> </article>
 .grid { display: grid; grid-template-columns: 1fr 20px 4fr 20px 1fr; grid-template-rows: auto 300px auto; grid-row-gap: 1em; } .section1 { grid-column: 3; grid-row: 1; } .section2 { grid-column: 3; grid-row: 3; } .full-width { grid-column: 1 / -1; grid-row: 2; background-color: rgba(214,232,182,.5); padding: 20px 0; }

これにより、全幅の画像と2つのコンテンツセクションが配置されたレイアウトが得られます。 ただし、セクションに背景を追加すると、 sectionと全幅の画像の間のrow-gapの上で停止します。

 .section { background-color: rgba(214,232,182,.3); border: 5px solid rgb(214,232,182); } 
全幅の画像、コンテンツ領域の背後の背景色を含む単一列のレイアウト
背景はコンテンツ領域の背後にあります

grid-row-gapを削除し、パディングを使用してスペースを作成した場合でも、全幅パネルの下にある背景の効果は有効になりません。

ここで、生成されたコンテンツを使用できます。 生成されたコンテンツを::beforeに追加し、背景色を付けます。 他に何もしなければ、コンテンツはグリッドの最初のセルに配置されます。

 .grid::before { content: ""; background-color: rgba(214,232,182,.3); border: 5px solid rgb(214,232,182); } 
レイアウトの左上隅にある色の正方形
生成されたコンテンツは、グリッドの最初の空のセルに入ります

次に、線ベースの配置を使用してコンテンツを配置し、背景色を表示する領域に拡大します。

 .grid::before { content: ""; background-color: rgba(214,232,182,.3); border: 5px solid rgb(214,232,182); grid-column: 2 / 5; grid-row: 1 / 4; }

このCodePenで完全な例を見ることができます。

CodePenのRachelAndrew(@rachelandrew)によるペン生成コンテンツの背景の例を参照してください。

CodePenのRachelAndrew(@rachelandrew)によるペン生成コンテンツの背景の例を参照してください。

z-indexスタックを制御する

上記の例では、生成されたコンテンツは::beforeで挿入されます。 これは、他の要素がその後に来ることを意味します。それはスタックの一番下にあるので、残りのコンテンツの後ろに表示されます。 z-indexを使用してスタックを制御することもできます。 ::beforeセレクターを::afterに変更してみてください。 生成されたコンテンツの背景は、境界線が画像の上を走る方法からわかるように、すべての上に配置されます。 これは、グリッドコンテナの最後のものになり、最後にペイントされて「上」に表示されるためです。

これを変更するには、この要素に他のすべてよりも低いz-indexプロパティを指定する必要があります。 他にz-index値がない場合、最も簡単な方法は、生成されたコンテンツに-1z-indexを与えることです。 これにより、 z-indexが最も低いアイテムとして、スタックの最初のものになります。

 .grid::after { z-index: -1; content: ""; background-color: rgba(214,232,182,.3); border: 5px solid rgb(214,232,182); grid-column: 2 / 5; grid-row: 1 / 4; }

この方法で背景を追加することは、コンテンツの背後に背景を完全にドロップすることに限定する必要はありません。 デザインの一部の背後にある色のブロックをポップできると、いくつかの興味深い効果が生まれる可能性があります。

これは、仕様が将来解決する可能性があるものですか?

背景と境界線を追加することは、CSSグリッド仕様の欠落している機能のように感じられ、ワーキンググループがコミュニティの多くのメンバーと話し合っています(ディスカッションスレッドはGitHubにあります)。

生成されたコンテンツでは簡単に解決できないユースケースがある場合は、そのスレッドに考えを追加してください。 コメントとユースケースは、この機能に開発者の関心があることを示し、提案があなたが行う必要のある種類のことをカバーしていることを確認するのに役立ちます。

その他の例をお願いします!

この記事で生成コンテンツを試すように勧められている場合、またはすでに例がある場合は、コメントに追加してください。 誰もが本番環境でグリッドを使用するのは初めてなので、「私はそれについて考えたことはありませんでした。 グリッドを他のレイアウト方法と組み合わせるため、必要な瞬間があります。