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は使わない
参考サイト
!デメリット!
display:contents
の要素は、contentブロックに対するstyle以外が無効になる
contentブロックとは
chrome devツールで言うこの真ん中の青い部分
なので、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を解除して自動行サイズに */
}
}