最近よく聞くdisplay:contentsを使ったレイアウトを学習しました。
作成していて、学んだことを備忘録としてまとめていきます。
完成サンプル
CodeSandBoxを使って、サンプルを作成しました↓
画面幅が小さい時、タイトル > 画像 > テキストの縦並びに、
画面幅が大きい時、画像とタイトル + テキストの横並びにするレイアウトを作成しました。
こういったレイアウトをする場合、普通にdisplay:flex;を指定するだけでは難しいと思います。
display:grid;を使ったり、positionを使ったりしてもいける気がしますが、
今回は、display:contents;を使った実装を書いていきます。
HTML作成
HTMLのコードはこちら↓
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>display:contentsを使ってレイアウト</title>
<link rel="stylesheet" href="assets/css/style.css" />
</head>
<body>
<div class="l-container">
<h1 class="p-pageTitle">display:contentsを使ったレイアウト</h1>
<div class="l-spacer" data-space="xxs:mediumTop lg:largeTop">
<section class="c-media p-media">
<div class="p-media__inner">
<div class="p-media__header">
<h2 class="p-media__title">タイトル</h2>
</div>
<div class="p-media__body">
<p class="p-media__text">
テキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキスト
</p>
</div>
</div>
<figure class="p-media__thumbnail">
<img
class="c-media__image p-media__image"
src="assets/img/apple.jpg"
alt="新鮮なりんごが輪っか状に5個並べられていて食欲そそる"
/>
</figure>
</section>
</div>
</div>
</body>
</html>
HTML上では特に変わったことはしておらず、一般的なメディア型パーツのコードを記述しました。
CSS作成
CSSのコードはこちら↓
/* リセットCSS */
* {
margin: 0;
padding: 0;
}
/* フルードイメージ */
img {
max-width: 100%;
height: auto;
vertical-align: bottom;
}
/* ========================================
Layout
==========================================*/
.l-container {
max-width: 960px;
width: 90%;
margin: 120px auto;
}
.l-spacer[data-space~="xxs:mediumTop"] {
padding-top: 3rem;
}
@media (min-width: 768px) {
.l-spacer[data-space~="lg:largeTop"] {
padding-top: 5rem;
}
}
/* ========================================
Component
==========================================*/
.c-media {
display: flex;
}
/* ========================================
Project
==========================================*/
.p-pageTitle {
font-size: 1.5rem;
}
@media (min-width: 767px) {
.p-pageTitle {
font-size: 3rem;
text-align: center;
}
}
.p-media {
flex-direction: column;
}
@media (min-width: 767px) {
.p-media {
flex-direction: row;
align-items: center;
}
}
.p-media__inner {
display: contents;
}
@media (min-width: 767px) {
.p-media__inner {
display: block;
margin-left: 2rem;
flex: 1;
order: 2;
}
}
.p-media__header {
padding-top: 0.5em;
order: -1;
}
.p-media__body {
order: 3;
}
.p-media__title {
font-size: 1.5rem;
}
.p-media__text {
font-size: 1.25rem;
}
@media (min-width: 767px) {
.p-media__text {
padding: initial;
}
}
.p-media__thumbnail {
border: 1px solid #333;
order: 2;
}
@media (min-width: 767px) {
.p-media__thumbnail {
flex: 2;
order: 1;
}
}
「.p-meida__inner」にdisplay:contents;を指定しました。
そして、orderプロパティを使って要素の並び替えをして、今回のレイアウトを実装しました。
display:contents;は、IE以外の主要なブラウザに対応しているのでスマホの時だけ指定すれば、IEの対策を考えなくても大丈夫です。
まとめ
今回学んだことは、display:contentsを指定された要素が存在しない扱いになることです。
とても便利なので今後も使用する機会があれば、使っていきたいです。
ただ、MDNによると
ブラウザーのバグにより、現在のところ、この値を使用するとアクセシビリティツリーから要素を削除します。 — 読み上げソフトは中に何があるかを見ません。詳しくは後述のアクセシビリティの考慮の節をご覧ください。
引用元:display – CSS: カスケーディングスタイルシート | MDN
とあるので注意が必要です。
2023/07/13追記:Chorme115から上記のバグを修正したらしいです↓
参考サイト
参考にさせていただいたサイト一覧↓
・地味に便利なdisplay: contents;
・display – CSS: カスケーディングスタイルシート | MDN
・“display:contents;” | Can I use… Support tables for HTML5, CSS3, etc