CSSでカードの高さを揃える3つの方法|中身の量が違う場合
-
この記事でわかること
- 中身の量が違うカードを横に並べても、見た目を揃えて整った一覧を作れる
- カードのレイアウトがずれたときに、原因を見つけて直せる
カード一覧を作ると、タグや説明文の量によって区切り線や文章の位置がずれることがあります。揃え方を知っておけば、CSSだけで整った一覧を作れます。この記事では、簡単な方法から順に3つの対処法を紹介します。
JavaScriptを使わなくても、CSSだけで揃えられるよ!
カードを揃える方法の全体像
カードを揃える方法は、手軽さと揃う精度の違いで3つあります。多くの場合は方法1と方法2で十分なので、初めての人は目次の順に読み、デザインに合う方法を選んでください。
やりたいことが決まっている場合は、次の表から探してください。方法2のコードは、方法2の完成形のコードにまとめています。
| やりたいこと | 使うプロパティ | 解説 |
|---|---|---|
| カードの下側を揃える | margin-top: auto |
方法1 |
| 区切り線の位置を揃える | min-height |
方法2 |
| 長い説明文を省略する | -webkit-line-clamp |
方法2 |
| 中身を行ごとに揃える | subgrid |
方法3 |
方法1:margin-top: autoで下側を揃える
いちばん手軽な方法です。区切り線から下をカードの下端に寄せて、カードの下側を揃えます。HTMLは変更せず、CSSだけで対応できます。
下準備:カードの中身を下端まで伸ばす
横に並べたカードは、外枠の高さは揃っても、中身は上に詰まったままです。下に寄せるには、中身をカードの下端まで伸ばす必要があります。
そこで、カード・リンク・本文エリアを縦並びのflexにして、余った高さを順に受け渡します。この記事では、次のようなカードを例に解説します。
HTML
<li class="card">
<a href="#">
<figure class="card__thumb"><img src="sample.jpg" alt=""></figure>
<div class="card__body">
<p class="card__date">2026.09.28</p>
<p class="card__title">会社名</p>
<ul class="card__tags"><li>タグ</li></ul>
<div class="card__divider"></div>
<p class="card__desc">説明文</p>
</div>
</a>
</li>
CSS
.card {
display: flex; /* ① */
flex-direction: column;
}
.card > a {
flex: 1; /* ② */
display: flex;
flex-direction: column;
}
.card__body {
flex: 1; /* ③ */
display: flex;
flex-direction: column;
}
| コード解説 | |
|---|---|
| ① | カードの中身を縦に並べる |
| ② | リンクをカードの下端まで伸ばし、その中身も縦に並べる |
| ③ | 本文エリアを、画像を除いた残りの高さいっぱいまで伸ばす |
margin-top: autoで区切り線から下を下端に寄せる
中身が伸びたら、区切り線にmargin-top: autoを指定します。autoのマージンは、余っている空間をすべて吸収します。その結果、区切り線とその下の説明文が、カードの下端まで押し下げられます。
HTML
<div class="card__divider"></div>
CSS
.card__divider {
margin-top: auto; /* 余った高さを上側で吸収して下に寄せる */
}
これで、カードの高さが揃い、日付・会社名・タグは上揃え、区切り線と説明文は下揃えになります。
ただし、説明文の行数がカードごとに違うと、区切り線の位置はずれます。例えば、説明文が3行のカードと2行のカードを並べると、区切り線が1行分ずれます。この程度のずれが気にならなければ、方法1で完成です。
区切り線が少しずれても気にならないデザインなら、方法1だけで十分だよ!
方法2:方法1+説明文の高さ固定で区切り線も揃える
方法1に指定を足して、残った区切り線のずれを直す方法です。説明文の高さを全カードで同じにすれば、下揃えになった説明文の上にある区切り線の位置も揃います。この方法も、HTMLの変更は不要です。
min-heightで説明文の高さを確保する
説明文にmin-heightを指定して、最低限の高さを確保します。値は「行の高さ × 行数」で決めます。例えば、line-heightが1.1で3行分確保したいなら、1.1 × 3で3.3emです。
HTML
<p class="card__desc">説明文</p>
CSS
.card__desc {
line-height: 1.1;
min-height: 3.3em; /* 1.1 × 3行分の高さ */
}
これで、説明文が1〜3行のどのカードでも、区切り線が同じ位置に揃います。
行数制限で長い説明文を省略する
min-heightだけだと、想定より長い説明文が入ったカードだけ、区切り線がずれてしまいます。そこで、行数を超えた部分を「…」で省略する指定を組み合わせます。
HTML
<p class="card__desc">説明文</p>
CSS
.card__desc {
display: -webkit-box; /* ① */
-webkit-box-orient: vertical; /* ② */
-webkit-line-clamp: 3; /* ③ */
overflow: hidden; /* ④ */
}
| コード解説 | |
|---|---|
| ① | 行数制限を使うための表示形式にする |
| ② | 中身を縦方向に並べる(①とセットで必要) |
| ③ | 表示する行数を3行にし、超えた部分を「…」で省略する |
| ④ | 3行を超えた部分を隠す |
-webkit-line-clampは、①と②の指定があるときだけ効きます。①と②は非推奨扱いのプロパティですが、この3つを組み合わせた動作は仕様で定められていて、今後も使えるとされています。
なお、接頭辞のないline-clampというプロパティもありますが、一部の主要ブラウザでまだ動きません。現時点では-webkit-付きの書き方を使いましょう。詳しくはMDN(line-clamp)で確認できます。
文章が途中で切れるため、全文を読ませたい内容には向きません。短いキャッチコピーのような説明文に使うのがおすすめです。
min-heightの数値は、行数制限の行数とそろえておくと管理しやすいよ!
方法3:subgridで中身を行ごとに揃える
全文を読ませたい説明文で、区切り線の位置も揃えたい場合はsubgridを使います。方法1・2とは別のやり方で、中身の量や画面幅に関係なく、パーツごとの位置が揃います。その代わり、HTMLの変更が必要です。
subgridの書き方
subgridは、入れ子にした要素が、親のグリッドの行をそのまま使う仕組みです。カード一覧の行を「画像・日付・会社名・タグ・説明文」の5行として共有させることで、隣のカード同士で各行の高さが揃います。
方法1・2と違い、カードを並べている一覧がdisplay: gridであることが条件です。一覧をflexで並べている場合は、一覧側もGridに変更します。
HTMLでは、区切り線と説明文を1つの要素で囲みます。1行に入る要素を1つにするためです。
HTML
<ul class="card-list">
<li class="card">
<a href="#">
<figure class="card__thumb"><img src="sample.jpg" alt=""></figure>
<div class="card__body">
<p class="card__date">2026.09.28</p>
<p class="card__title">会社名</p>
<ul class="card__tags"><li>タグ</li></ul>
<div class="card__desc-wrap">
<div class="card__divider"></div>
<p class="card__desc">説明文</p>
</div>
</div>
</a>
</li>
</ul>
CSS
.card-list {
display: grid; /* ① */
grid-template-columns: repeat(3, 1fr);
}
.card {
display: grid;
grid-row: span 5; /* ② */
grid-template-rows: subgrid; /* ③ */
row-gap: 0; /* ④ */
}
.card > a {
display: grid;
grid-row: span 5;
grid-template-rows: subgrid;
row-gap: 0;
}
.card__body {
display: grid;
grid-row: span 4; /* ⑤ */
grid-template-rows: subgrid;
row-gap: 0;
}
| コード解説 | |
|---|---|
| ① | カードを並べる一覧をGridにする(subgridの行の共有元になる) |
| ② | カード1枚で、一覧の5行分(画像・日付・会社名・タグ・説明文)を使う |
| ③ | 自分で行を作らず、親のグリッドの行をそのまま使う |
| ④ | 親から引き継いだ行の間のすき間をなくす |
| ⑤ | 本文エリアは、画像を除いた4行分を使う |
カード・リンク・本文エリアの3段すべてに、同じ指定が必要です。どこか1段でも抜けると、そこで行の共有が途切れて揃わなくなります。
subgridはBaseline※1の機能で、2023年9月以降、主要なブラウザすべてで使えます。詳しい仕様はMDN(サブグリッド)で確認できます。
※1:Baseline…主要なブラウザすべてで使えるようになった機能であることを示す目印。
タグが縦に伸びるときの対処法
タグを横に並べて折り返す指定をしていると、subgridにしたときにタグが縦長に伸びることがあります。タグの行の高さが、タグが一番多いカードに揃うためです。
タグを並べている要素にalign-content: flex-startを指定すると、タグが上に寄り、元の形に戻ります。
HTML
<ul class="card__tags">
<li>タグ</li>
<li>タグ</li>
</ul>
CSS
.card__tags {
display: flex;
flex-wrap: wrap; /* ① */
align-content: flex-start; /* ② */
}
| コード解説 | |
|---|---|
| ① | タグを横に並べ、入りきらない分を折り返す(タグが縦に伸びる原因になる書き方) |
| ② | 伸びた行の中で、タグを上に寄せる |
区切り線と説明文が重なるときの対処法
subgridにしたとき、区切り線が説明文の1行目に重なって表示されることがあります。原因は、区切り線と説明文を囲む要素が、実際のHTMLに出力されていないことです。
subgridでは、要素が行数より多くても、新しい行は作られません。はみ出した要素は最後の行に詰め込まれるので、区切り線と説明文が同じ場所に重なります。
ブラウザの開発者ツールで、囲みの要素が出力されているか確認しましょう。次のような原因が多いです。
- 編集したファイルがサーバーにアップロードされていない
- キャッシュが残っていて、古いHTMLが表示されている
- WordPressの子テーマに同じ名前のファイルがあり、そちらが使われている
表示がおかしいときは、CSSより先に「HTMLが思った通りに出ているか」を見てみてね!
どの方法を選ぶか
3つの方法は、揃えたい精度と、文章を省略してよいかで選びます。迷ったら方法1から試して、足りなければ方法2、方法3の順に検討するのがおすすめです。
| 方法 | 揃う範囲 | 向いている場面 |
|---|---|---|
| 方法1:margin-top: auto | カードの高さと下端 | 区切り線が少しずれても気にならないとき |
| 方法2:方法1+高さ固定 | 区切り線の位置まで | 説明文が短いキャッチコピーで、途中で切れてもよいとき |
| 方法3:subgrid | 各パーツの位置まで厳密に | 全文を読ませたい文章で、区切り線も揃えたいとき |
方法1と方法2はカードの中身のCSSだけで済み、一覧の並べ方やHTMLを変えずに使えるのが強みです。方法3は、料金表や比較表のように、行ごとに揃っていないと読みにくいレイアウトにも向いています。
一覧カードなら、方法2で困ることは少ないよ!
方法2の完成形のコード
方法1と方法2の指定をまとめた、カードの中身の完成形です。カードの高さと区切り線の位置が揃い、長い説明文は3行で省略されます。
HTML
<li class="card">
<a href="#">
<figure class="card__thumb"><img src="sample.jpg" alt=""></figure>
<div class="card__body">
<p class="card__date">2026.09.28</p>
<p class="card__title">会社名</p>
<ul class="card__tags"><li>タグ</li></ul>
<div class="card__divider"></div>
<p class="card__desc">説明文</p>
</div>
</a>
</li>
CSS
.card {
display: flex; /* ① */
flex-direction: column;
}
.card > a {
flex: 1;
display: flex;
flex-direction: column;
}
.card__body {
flex: 1;
display: flex;
flex-direction: column;
}
.card__divider {
margin-top: auto; /* ② */
}
.card__desc {
line-height: 1.1;
min-height: 3.3em; /* ③ */
display: -webkit-box; /* ④ */
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
overflow: hidden;
}
| コード解説 | |
|---|---|
| ① | カード・リンク・本文エリアを縦に並べ、下端まで伸ばす(方法1) |
| ② | 区切り線から下をカードの下端に寄せる(方法1) |
| ③ | 説明文に3行分の高さを確保して、区切り線の位置を揃える(方法2) |
| ④ | 3行を超えた説明文を「…」で省略する(方法2) |
さいごに
まとめ
中身の量が違うカードは、デザインに合わせて3つの方法から選べば、CSSだけで揃えられます。まずは方法2の完成形のコードを試してみてください。
- 区切り線に
margin-top: autoを付けて、下側を揃える(方法1) - 説明文の高さを
min-heightと行数制限で固定して、区切り線も揃える(方法2) - 全文を見せつつ厳密に揃えたいときは、一覧をGridにしてsubgridを使う(方法3)
よくある質問
カードを横に並べたのに、区切り線や説明文の位置がずれるのはなぜ?
一覧をGridとflexのどちらで並べていても、初期設定では同じ行のカードが一番高いカードに合わせて伸びます。そのため、カードの外枠の高さは揃います。
ただし、伸びるのは外枠だけで、中のリンクや本文エリアは伸びません。中身が上に詰まったままになるため、区切り線や説明文の位置がずれて見えます。「下準備:カードの中身を下端まで伸ばす」で解説しています。
いちばん下の要素にmargin-bottom: autoを付けたら揃いました。これで大丈夫?
おすすめしません。上下2つのautoマージンが余った高さを半分ずつ分け合うため、タグと説明文の増えた高さが近いときだけ、たまたま揃って見えます。
タグの行数だけが違うカードや、画面幅が変わったときにはずれます。確実に揃えるなら、説明文の高さを固定する方法を使いましょう。「min-heightで説明文の高さを確保する」で解説しています。
説明文が2段落あるカードだけ、区切り線がずれます
min-heightは段落ごとに高さを確保するため、段落が2つあるカードはその分だけ高くなります。説明文を1つの段落にまとめるか、段落の数に関係なく揃うsubgridを使いましょう。「subgridの書き方」で解説しています。
JavaScriptで高さを揃える方法は使わないの?
jQueryのmatchHeightなど、JavaScriptで高さを揃える方法は、flexやGridが普及する前によく使われていました。現在はCSSだけで揃えられるため、使う必要はありません。
subgridにしたら、区切り線が説明文に重なりました
区切り線と説明文を囲む要素が、実際のHTMLに出力されていない可能性が高いです。開発者ツールで、囲みの要素があるか確認しましょう。「区切り線と説明文が重なるときの対処法」で解説しています。

