Tips

【CSSのみ】横並びで高さを揃えるテクニック

  • このエントリーをはてなブックマークに追加

コーディングにおいて横並びのレイアウトは必ずと言っても良いほど登場します。

基本的にはdisplayプロパティを使えば簡単に横並びにすることはできます。

しかしWordPress化などで実際に文章が挿入されたときにレイアウト崩れが起きることがありませんか?

「基本的なレイアウトは作れるけど応用ができない」
「ググってやってもレイアウトが綺麗に揃わない」
「いざアップしてみると思ってた感じと違う。。。」

本日はそんな横並びレイアウトに関する内容です。

さらにJavaScriptを使わずにきれいに作る方法に絞って紹介するので、コーディング初心者でも活用して頂けると思います。

また動画も用意しているので適宜で使ってみてください。

一番カンタンに横並びの高さを揃える方法

今回はホームページにおけるニュース機能を想定して作ってみました。

HTMLについては以下の通りです。

<section class="card-group">
      <article class="card">
        <h2>2022年4月1日</h2>
        <p class="text">
          この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等
        </p>
      </article>
      <article class="card">
        <h2>2022年5月1日</h2>
        <p class="text">
          この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認する
        </p>
      </article>
      <article class="card">
        <h2>2022年6月1日</h2>
        <p class="text">
          この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れ
        </p>
      </article>
</section>

特に難しいことはしていません。

3個のニュース記事を並べている形になっています。

続いてCSSはこちらになります。

* {
  box-sizing: border-box;
}
body {
  background: #fff;
  overflow: hidden;
}
.card-group {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.5rem;
  align-items: flex-start;
}
.card {
  background: #fff;
  padding: 1rem;
  border: 1px solid #333;
  border-radius: 0.25rem;
}
h2,
p {
  margin: 0;
}
h2 {
  margin-bottom: 1rem;
}
.text {
  --max-lines: 3;
  display: -webkit-box;
  -webkit-line-clamp: var(--max-lines);
  overflow: hidden;
  -webkit-box-orient: vertical;
}

注目してもらいたいのは、pタグになる「.text」の部分です。

こちらはコピペでも問題ないです。

簡単に説明すると「3行目まで表示して、それ以降は非表示にする」ということをしているので、結果的に高さが揃う形になっています。

こちらで以下のように簡単に高さを揃えることが出来ました。

ちなみに「.text」の「- -max-lines」についてはCSS変数になります。

「- -」を先頭につけるとCSSのなかで変数として使い回すことが出来ます。

「- -max-lines」に「3」を入れているので3行目で留めることになっていますので、例えば「5」を入力すると5行目までにすることも出来ます。

「CSSで変数なんて使ったことない」という方は多いと思いますが、このようにコードの使い回しは後々の修正や追加作業で自分を楽にすることになるので積極的に使っていきましょう。

行数ではない揃え方

続いて行数ではなく「コンテンツのサイズ」で揃える方法を紹介します。

少し書く量が増えますが、実際の開発現場でも使われるテクニックなので知っておくだけでも全然違ってきます。

HTMLは特に変更ないので、CSSを以下のように書き換えてみます。

* {
  box-sizing: border-box;
}
body {
  overflow: hidden;
  margin: 0;
  padding: 0;
}
.card-group {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.5rem;
  align-items: flex-start;
}
.card {
  padding: 16px;
  border: 1px solid #333;
  border-radius: 0.5rem;
}
.text {
  --max-lines: 5;
  --line-height: 1.7;
  max-height: calc(var(--max-lines) * 1em * var(--line-height));
  overflow: hidden;
  position: relative;
}
.text::before {
  content: "";
  position: absolute;
  height: calc(1em * var(--line-height));
  width: 100%;
  bottom: 0;
  pointer-events: none;
}

こちらもpタグの「.text」に注目します。

疑似要素とセットで高さを計算されたものにしています。

「- – line-height」というものがありますが、先ほど同様にCSS変数になります。

「- -max-lines」「- -line-height」を掛け合わせることで「行数×行間」という計算をしているのです。

これにより行数ではなく「コンテンツのサイズ」を起点にして高さ調整が可能になりました。

表示内容としては先ほどと変わりません。

ボタンを使った表示、非表示を作る

今回の記事としては以上になるのですが、せっかくなのでボタンを使ったコンテンツの表示、非表示の切り替えまで紹介します。

実際には「高さを揃えるだけ」で完成になることはないですよね。

最終的なゴールとしては各コンテンツの表示まで求められます。

ボタンについてはHTMLでinputタグを使って実装してみます。

<section class="card-group">
      <article class="card">
        <h2>2022年4月1日</h2>
        <p class="text">
          この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等
        </p>
        <input type="checkbox" class="btn" />
      </article>
      <article class="card">
        <h2>2022年5月1日</h2>
        <p class="text">
          この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認する
        </p>
        <input type="checkbox" class="btn" />
      </article>
      <article class="card">
        <h2>2022年6月1日</h2>
        <p class="text">
          この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れ
        </p>
        <input type="checkbox" class="btn" />
      </article>
</section>

inputタグのtype属性を「checkbox」にしておくのを忘れないでください。

今回はチェックボッスを使ったボタンになります。

「なぜチェックボックスなのか?」は後々に説明します。

現状はチェックボックスが表示されているので、こちらのチェックボックスにCSSを当てていきます。

* {
  box-sizing: border-box;
}
body {
  background: #fff;
  overflow: hidden;
}
.card-group {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.5rem;
  align-items: flex-start;
}
.card {
  background: #fff;
  padding: 1rem;
  border: 1px solid #333;
  border-radius: 0.25rem;
}
h2,
p {
  margin: 0;
}
h2 {
  margin-bottom: 1rem;
}
.text {
  --max-lines: 5;
  --line-height: 1.4;
  max-height: calc(var(--max-lines) * 1em * var(--line-height));
  line-height: var(--line-height);
  overflow: hidden;
  position: relative;
}
.text:has(+ .btn:not(:checked))::before {
  content: "";
  position: absolute;
  height: calc(1em * var(--line-height));
  width: 100%;
  bottom: 0;
  pointer-events: none;
  background: linear-gradient(to bottom, transparent, #fff);
}

.btn {
  appearance: none;
  border: 1px solid #333;
  padding: 0.5em;
  border-radius: 0.25em;
  cursor: pointer;
  margin-top: 1rem;
}

.btn::hover {
  background: #ccc;
}
.btn::before {
  content: "もっと見る";
}
.btn:checked::before {
  content: "閉じる";
}
.text:has(+ .btn:checked) {
  max-height: none;
}

inputタグが「.btn」になるので、こちらにスタイルを書きました。

ボタンの文字は疑似要素のcontentプロパティに「もっと見る」「閉じる」を指定しています。

表示内容はこのようになっています。

ボタンが表示されていて、「もっと見る」という文字になっています。

さらに文章の部分にも注目してみてください。

5行目がうっすら非表示になっていますね、これが先ほどからお話している「コンテンツの高さ」で揃えている効果です。

行数ではなくコンテンツの高さで揃えることで、今回のようにボタンを後から追加しても全体のサイズは変わりません。

コーディングをしているとデザイナーさんから「これも追加で!」と追加の表示内容をもらうことがあります。

追加の依頼が来てもサイズが変わらないような組み方をすることを意識できるようになるとレベルアップしたと言っても良いでしょう。

少し脱線しましたがボタンについて、クリックすると以下のように動作します。

ボタンの文字が「閉じる」に切り替わって、文章が全体まで表示されています。

これらを実現しているのは主に以下の部分です。

.text:has(+ .btn:not(:checked))::before {
  content: "";
  position: absolute;
  height: calc(1em * var(--line-height));
  width: 100%;
  bottom: 0;
  pointer-events: none;
}
.text:has(+ .btn:checked) {
  max-height: none;
}

「has」という文法を使うことで「.textの直後にある.btn」という意味になります。

HTMLを見返してみましょう。

<article class="card">
        <h2>2022年4月1日</h2>
        <p class="text">
          この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等
        </p>
        <input type="checkbox" class="btn" />
</article>

「.text」のすぐ次に「.btn」が存在していますね。

さらにinputタグをチェックボックスにしていることで、「チェック(クリック)」を利用できるようになっています。

「チェック(クリック)されていなければ高さを揃えておく」が以下の部分です。

.text:has(+ .btn:not(:checked))::before {
  content: "";
  position: absolute;
  height: calc(1em * var(--line-height));
  width: 100%;
  bottom: 0;
  pointer-events: none;
}

「チェック(クリック)されたら高さを揃えずに全て表示」が以下の部分です。

.text:has(+ .btn:checked) {
  max-height: none;
}

これがinputタグでチェックボックスをあえて使っていた理由になります。

チェックボックスは今回のように違う用途にも利用できるので、日々のコーディングでチェックボックスが使えそうな部分が無いか探してみるのも良いかもしれませんね。

  • このエントリーをはてなブックマークに追加

コメントを残す

*