こんにちは。今回は、最近見かけたdiplay: gridを使って要素を重ねる方法について考えていこうと思います。
デモ
ブログなどの記事一覧でよく見るカードの形です。左上のタグが画像に重なっています。
デモサイトはこちら。
結論
結論から言えば、gridレイアウトを作り同じセルに複数の要素を置くとそれらが重なります。
シンプルな例を出します。正方形を5個重ねます。
<div class="Container">
<div class="Child" style="background-color: red"></div>
<div class="Child" style="background-color: green"></div>
<div class="Child" style="background-color: blue"></div>
<div class="Child" style="background-color: yellow"></div>
<div class="Child" style="background-color: pink"></div>
</div>
.Container {
width: 500px;
height: 500px;
display: grid;
}
.Child {
grid-area: 1/1;
width: 100%;
height: 100%;
}
こうすると、ピンクの正方形が1つ表示されます。
では、どれでも良いのでz-indexを指定します。ここでは青にしてみます。
<div class="Container">
<div class="Child" style="background-color: red"></div>
<div class="Child" style="background-color: green"></div>
<div class="Child" style="background-color: blue: z-index: 10"></div>
<div class="Child" style="background-color: yellow"></div>
<div class="Child" style="background-color: pink"></div>
</div>
すると青い正方形が表示されます。
このような形で、gridレイアウトで同じセルの場所に複数要素を置くことで重なりが表現できました。
デモの解説
デモのような実践的な場面でどう使うかを見ていきましょう。display: grid;を使う都合上いくつか気を付けるポイントがあります。
まずはタグ以外のカード部分です。
<article class="Card">
<img src="./resources/images/logo-css.png" alt="" class="Card-Thumbnail" />
<div class="Card__Bottom">
<h2 class="Card-Title">gridで要素を重ねる</h2>
<p class="Card-Content">
ダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストダミーテキスト
</p>
</div>
</article>
.Card {
box-shadow: 0 0 12px 4px rgba(0, 0, 0, 0.4);
width: 100%;
max-width: 500px;
display: grid;
grid-template-columns: 1fr;
gap: 20px;
}
.Card-Thumbnail {
width: 100%;
}
.Card__Bottom {
width: 100%;
padding-left: 16px;
padding-right: 16px;
padding-bottom: 16px;
display: grid;
grid-template-columns: 1fr;
gap: 8px;
}
.Card-Title {
font-size: 20px;
font-weight: bold;
}
.Card-Content {
font-size: 14px;
line-height: 1.5;
}
.Card__Bottom以下は今回のレイアウトには関係ないので流してOKです。.Cardにgridを適用していることがポイントです。
続いてタグの部分を作りましょう。タグの要素は.Cardの直下、画像と並列になっていればどこでも良いです。
<article class="Card">
<div class="Card-Tag">HTML/CSS</div>
<img src="./resources/images/logo-css.png" alt="" class="Card-Thumbnail" />
<div class="Card__Bottom">
<!-- 省略 -->
</div>
</article>
.Card-Tag {
padding: 4px;
background-color: #0095d9;
color: #fff;
}
この時点ではこんな感じ。
では重ねていきます。grid-areaというプロパティで、画像とタグを同じ位置に配置します。
.Card-Tag {
grid-area: 1 / 1; /* 追加 */
padding: 4px;
background-color: #0095d9;
color: #fff;
}
.Card-Thumbnail {
grid-area: 1 / 1: /* 追加 */
width: 100%:
}
grid-areaはgridレイアウトの位置を数字などで明示的に指定するプロパティです。1 / 1とすると左上のセル1つ分の領域を確保します。今回は縦は1列のみなので、一番上に配置されます。
詳しくは以下より。
またgridレイアウトの数値についてはちらをご覧ください。ざっくりいうと縦横のグリッド線に左上からそれぞれ1、2、3・・・と番号が割り振られています。
こうするとタグと画像が重なります。
さて、タグ部分が裏へいってしまったのでz-indexを指定しましょう。
.Card-Tag {
grid-area: 1/1;
z-index: 10; /* 追加 */
padding: 4px;
background-color: #0095d9;
color: #fff;
}
するとこうなります。
おっと、タグが大きすぎますね。これがgridレイアウトを使ったことによる注意点で、同じセルに配置した要素は基本的にセルのwidth / height のサイズになります。
これでは要素を重ねられたとしても使えません。何らかの数値で指定する方法もありますが、動的コンテンツの場合はそれだとうまく表示するのは難しいですね。
そこでサイズ指定にfit-contentというキーワードを使います。
.Card-Tag {
grid-area: 1/1;
z-index: 10;
width: fit-content; /* 追加 */
height: fit-content; /* 追加 */
padding: 4px;
background-color: #0095d9;
color: #fff;
}
こうすると、コンテンツ分だけ領域を確保してくれます。従来のdisplay: inline-block;に近い挙動です。
このfit-contentは、「コンテンツ分の領域だけを確保+親要素をはみ出してしまう場合は折り返しを行う」という大変都合のいい指定方法です。今回の主題とは若干違いますが、ぜひ覚えてみてください。
ブラウザ対応もほぼ問題ないでしょう。
というわけで、gridを使って要素の重ねを表現することができました。
ただし・・・
と、ここまで解説しましたが個人的にはposition: absolute;を使う方法でも別にいい、あるいは場合によってその方法の方が良いこともありそうです。
理由はdisplay: gridの影響範囲の大きさです。今回の場合重ねたいのはタグと画像だけでした。しかし、そのためだけにコンテンツ部分のレイアウトにもgridが影響してしまいます。カードのようなレイアウトの場合はたまたま問題がありませんでしたが、場合によっては面倒ごとが起きることもあるでしょう。
タグと画像部分を要素で囲ってそこをgridにする手もあるでしょうが、単純に余計な要素が増えますし意味的にもそれらがグループかというと今回はちょっと違いますよね。
そういうわけで、あくまで選択肢の1つとして捉えるくらいが良いかなと考えています。もちろんposition: absolute;の扱いづらさは依然としてありますから、使いやすい方、安全な方を選択していきましょう。
ちなみに、gridレイアウトにおいては要素の重なりは想定されているようです。gridの特徴として明確に「コンテンツの重ね合わせや、z-indexによるレイヤーコントロール機能」が挙げられています。
the ability to overlap content and control layering with z-index
https://www.w3.org/TR/css-grid-2/#overview
まとめ
display: grid;による要素の重ね合わせについてでした。これまで要素を重ねる=position: absplute;でしたが、使える場面では使っていきたい方法ですね。
コメント