MENU

【subgrid】カード内の要素の高さを揃える

HTML内の要素の高さを揃える方法は昔からあるが、最適な方法は時代とともに変化している。

  • 昔:JabaScriptで揃える
  • ちょい前:grid + display:contents
  • 今:grid + サブgrid
目次

JavaScriptで揃える

それぞれのカードの要素の高さを取得し、一番高さが大きい要素の高さに全カード合わせる

!デメリット!

jsによる処理が入るのでパフォーマンスに影響が出る

高さをあわせるカスタムメソッド

(function ($) {
    $.fn.tile = function (columns) {
        var tiles, max, c, h, last = this.length - 1,
            s;
        if (!columns) columns = this.length;
        this.each(function () {
            s = this.style;
            if (s.removeProperty) s.removeProperty("height");
            if (s.removeAttribute) s.removeAttribute("height");
        });
        return this.each(function (i) {
            c = i % columns;
            if (c == 0) tiles = [];
            tiles[c] = $(this);
            h = tiles[c].height();
            if (c == 0 || h > max) max = h;
            if (i == last || c == columns - 1)
                $.each(tiles, function () {
                    this.height(max);
                });
        });
    };
})(jQuery);

引数:カードが何列の横並びかの、列数

$.fn.tileについて補足

$.fn.tileは、jQueryを使ったカスタムメソッドの1つで、特定の目的のためにjQueryの関数を拡張するために使用されます。 この場合、というtileメソッドが作成されていることを示していますが、tile自体はjQueryの標準メソッドには存在しないため、カスタムで作成されたものです。 →つまり$(.elem).tile()という指定が可能になる?

通常、$.fnは jQuery の関数のプロトタイプオブジェクトを離れており、このオブジェクトにメソッドを追加することで、すべての jQuery オブジェクトに対して新しいメソッドを使えるようにします。 例えば、要素をグリッド状に並べる処理や高揃える処理を行う場合に、tileという名前でカスタムメソッドを作ることが考えられます。

呼び出し

$(window).on('load resize', function () {
    if ($(window).width() > 767) {
        $('.access-list dl .bg').tile(2);
        $('.corporate-inner03-list .corporate-inner').tile(2);
        $('.corporate-sec03-flex .item .corporate-inner').tile(2);
    } else {

        $('.access-list dl .bg').tile(1);
        $('.corporate-inner03-list .corporate-inner').tile(1);
        $('.corporate-sec03-flex .item .corporate-inner').tile(1);
    }
});

grid + display:contentsで揃える

※jsは使わない

コリス
[CSS]「display: contents;」がすごい便利!ラッパーを使った実装が大きく変わるこれからのテクニック 例えばカードで、見出しが1行・3行、本文の量が多かったり少なかったりする場合、それぞれの高さを揃えるのは非常に難しく、かなりトリッキーな実装が必要でした。もしくは...

参考サイト

!デメリット!

display:contentsの要素は、contentブロックに対するstyle以外が無効になる

contentブロックとは

chrome devツールで言うこの真ん中の青い部分

chrome検証ツールの画像

なので、contentブロックの外にあたるmarginとかは当たらなくなる。 もしかしたらbox-sizingの指定によってあたらなくなるスタイル変わるかも?(未検証)だが すくなくともmarginは当たらなくなる。

対策:display: contentsにする要素にはスタイルを当てない

アクセシビリティに問題が出る場合がある

display: contentsが指定されている要素のroleがアクセシビリティツリー上で無視される。

(tabフォーカスとかもできなくなる?)

→その要素にアクセシビリティ上の役割がある場合、役割が無視されるので問題

対策:display: contentsにする要素には、アクセシビリティ上の役割を与えない

↓↓↓

2024/9月現在は、subgridを使えばよいのでdisplay: contentsを使う機会はないかな

<div class="cards cards-grid">
	<article class="card display-contents">
		<div class="card__img"></div>
		<h3 class="card__title">短いタイトル</h3>
		<p class="card__text1">長いテキスト1です。長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1</p>
		<p class="card__text2">短いテキスト2</p>
	</article>
	<article class="card display-contents">
		<div class="card__img"></div>
		<h3 class="card__title">長いタイトル長いタイトル長いタイトル長いタイトル長いタイトル</h3>
		<p class="card__text1">長いテキスト1です。長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1</p>
		<p class="card__text2">長いテキスト2長いテキスト2長いテキスト2長いテキスト2長いテキスト2長いテキスト2長いテキスト2長いテキスト2長いテキスト2長いテキスト2長いテキスト2長いテキスト2長いテキスト2長いテキスト2長いテキスト2長いテキスト2長いテキスト2長いテキスト2長いテキスト2長いテキスト2</p>
	</article>
	<article class="card display-contents">
		<div class="card__img"></div>
		<h3 class="card__title">短いタイトル</h3>
		<p class="card__text1">短いテキスト1</p>
		<p class="card__text2">短いテキスト2</p>
	</article>
</div>

css(card内要素のstyleは省略)

.cards-grid{
	display: grid;
	grid-auto-flow: column; /* gridアイテムを縦に設置 */
	grid-template-rows: auto auto auto 1fr; /* 4行 */
	grid-template-columns: repeat(3, 1fr);
	column-gap: 30px;
}
.cards-grid .display-contents{
	display: contents;
}

@media screen and (max-width: 767px){
	.cards-grid{
		grid-auto-flow: row;
		grid-template-columns: 1fr;
		row-gap: 30px;
	}
	.cards-grid .display-contents{
		display: block;
	}
}

grid + サブgridで揃える

参考サイト

https://zenn.dev/tonkotsuboy_com/articles/css-subgrid-all-browsers

  • 子要素もdisplay: gridにする
  • grid-template-rows: subgrid;で、入れ子であることを宣言する
		<div class="cards cards-grid-with-sub">
			<article class="card card-sub-grid">
				<div class="card__img"></div>
				<h3 class="card__title">短いタイトル</h3>
				<p class="card__text1">長いテキスト1です。長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1</p>
				<p class="card__text2">短いテキスト2</p>
			</article>
			<article class="card card-sub-grid">
				<div class="card__img"></div>
				<h3 class="card__title">長いタイトル長いタイトル長いタイトル長いタイトル長いタイトル</h3>
				<p class="card__text1">長いテキスト1です。長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1長いテキスト1</p>
				<p class="card__text2">長いテキスト2長いテキスト2長いテキスト2長いテキスト2長いテキスト2長いテキスト2長いテキスト2長いテキスト2長いテキスト2長いテキスト2長いテキスト2長いテキスト2長いテキスト2長いテキスト2長いテキスト2長いテキスト2長いテキスト2長いテキスト2長いテキスト2長いテキスト2</p>
			</article>
			<article class="card card-sub-grid">
				<div class="card__img"></div>
				<h3 class="card__title">短いタイトル</h3>
				<p class="card__text1">短いテキスト1</p>
				<p class="card__text2">短いテキスト2</p>
			</article>
		</div>
.cards-grid-with-sub{
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
	gap: 30px;
}

.card-sub-grid{
	display: grid;
	grid-template-rows: subgrid;
	grid-row: span 4; /*親要素の4行分を使う */
	gap: 0; /* 孫要素間のgapを指定できる (省略した場合は親gridのgapを引き継ぐ?)*/
}

補足:SP時などでsubgrid解除したいときは以下で上書く

@media (max-width: 768px) {
  .card-sub-grid{
    grid-template-rows: auto; /* subgridを解除 */
    grid-row: auto; /* spanを解除して自動行サイズに */
  }
}
よかったらシェアしてね!
  • URLをコピーしました!

この記事を書いた人

kotooriのアバター kotoori Webコーダー

Webコーダーの「ことおり」です。
LPサイトや静的サイトの実装、修正、Wordpress化を承っております。

企業や個人のお客様の顔となるWebサイト制作を通じて、お客様の成果に貢献いたします。

目次