複数行にも対応!はみ出た文字を三点リーダー(…)で省略する方法

公開日 : 最終更新日 :

  • コーディング
複数行にも対応!はみ出た文字を三点リーダー(…)で省略する方法

メディアサイトなどで、長い文字列の文末を「…」にして省略することが結構あります。
これって実は意外とめんどくさかったりします。

1行表示の場合はCSSのみで対応可能なのですが、複数行になると少し難しくなってきます。
この記事では複数行にも対応した、長すぎる文字列を三点リーダー(…)で省略する方法についていくつかご紹介します。

ベースとなるコード

一部異なる箇所もありますが、以下のスタイルをベースとして実装方法についてご紹介してきます。ご自身に合わせて、適宜変更して試してみてください。

共通のHTML

<ul class="card_list">
  <li class="card_item">
    <a href="#">
      <div class="thum_box">
        <img src="logo.svg" alt="">
      </div>
      <div class="text_box">
        <h1 class="title">タイトルが入りますタイトルが入ります</h1>
        <p class="desc js-textTrim">
          親譲りの無鉄砲で小供の時から損ばかりしている。小学校に居る時分学校の二階から飛び降りて一週間ほど腰を抜かした事がある。なぜそんな無闇をしたと聞く人があるかも知れぬ。別段深い理由でもない。新築の二階から首を出していたら、同級生の一人が冗談に、いくら威張っても、そこから飛び降りる事は出来まい。
        </p>
      </div>
    </a>
  </li>
</ul>

共通のCSS

html {
  font-size: 62.5%;
}
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  border: 0;
  list-style: none;
}
a, a:link, a:visited, a:active {
  text-decoration: none;
  color: inherit;
}
.card_item {
  width: 310px;
  border: 1px solid #e3e3e3;
  box-shadow: 0px 6px 6px rgba(0, 0, 0, 0.5);
  margin: 60px;
}
.card_item .thum_box {
  width: 100%;
  height: 200px;
  background: #efefef;
  position: relative;
  overflow: hidden;
}
.card_item .thum_box img {
  width: auto;
  height: auto;
  max-width: 80%;
  max-height: 100%;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
.card_item .text_box {
  width: 100%;
  padding: 28px;
}
.card_item .title {
  font-size: 2.4rem;
  color: #3b4043;
  line-height: 1.6;
  margin-bottom: 12px;
}
.card_item .desc {
  font-size: 1.2rem;
  color: #606060;
}
.card_item .cat {
  display: inline-block;
  font-size: 1.4rem;
  color: #fff;
  background: #606060;
  padding: 4px 30px 2px;
  margin-bottom: 10px;
}

CSSのみで対応(1行のみ)

.card_item .title {
  overflow: hidden;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}
.card_item .desc {
  overflow: hidden;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
}

-webkit-line-clamp では何行表示させるかを指定することができます。
IEではサポートされていませんが、ほとんどのモダンブラウザで使用可能です。

2022年現在のサポート状況は以下の通りです。

JavaScriptを使った方法①

全てのブラウザで実装したい場合は、JavaScriptを利用することで可能です。

function textTrim() {
  // テキストをトリミングする要素
  var selector = document.getElementsByClassName('js-textTrim');
 
  // 制限する文字数
  var wordCount = 57;
 
  // 文末に追加したい文字
  var clamp = '…';
 
  for (var i = 0; i < selector.length; i++) {
    // 文字数を超えたら
    if (selector[i].innerText.length > wordCount) {
      var str = selector[i].innerText; // 文字数を取得
      str = str.substr(0, (wordCount - 1)); // 1文字削る
      selector[i].innerText = str + clamp; // 文末にテキストを足す
    }
  }
}
textTrim();

表示する文字数を指定して、はみ出した場合に「…」をつけています。
ただし、半角文字には対応していなため三点リーダーの位置はずれる場合があります。

JavaScriptを使った方法②

function textTrim() {
  // テキストをトリミングする要素
  var selector = document.getElementsByClassName('js-textTrim');
 
  // 表示したい行数
  var row = 3;
 
  // 文末に追加したい文字
  var clamp = '…';
 
  for (i = 0; i < selector.length; i++) {
    //CSSプロパティを取得
    var style = window.getComputedStyle(selector[i]);
    var fontsize = parseFloat(style.fontSize); //font-sizeを取得
    var width = parseFloat(style.width); //widthを取得
    var letterSpacing = parseFloat(style.letterSpacing); //letter-spacingを取得
 
    // 収まる文字数を計算
    var wordCount = Math.floor(width / fontsize) * row;
 
    // letter-spacingも含めて計算する場合
    // var wordCount = Math.floor(width / (fontsize + letterSpacing)) * row;
 
    // 文字数を超えたら
    if (selector[i].innerText.length > wordCount) {
      var str = selector[i].innerText; //文字数を取得
      str = str.substr(0, (wordCount - 1)); //1文字削る
      selector[i].innerText = str + clamp; //文末にテキストを足す
    }
  }
}
textTrim();

パターン①と似ていますが、違いは文字数を指定するのではなく、テキストの幅とフォントサイズから収まる文字数を計算しているということです。
(要素幅 ÷ フォントサイズ)× 表示したい行数 で何文字入るのかを出しています。
letter-spacing を設定している場合は、フォントサイズにさらに文字間を足すことで文字数を計算することができます。
こちらも半角文字には対応していません。

JavaScriptを使った方法③

<li class="card_item">
  <a href="#">
    <div class="thum_box">
      <img src="logo.svg" alt="">
    </div>
    <div class="text_box">
      <h1 class="title">タイトルが入りますタイトルが入ります</h1>
      <div class="desc_box js-textTrim">
        <p class="desc">
          親譲りの無鉄砲で小供の時から損ばかりしている。小学校に居る時分学校の二階から飛び降りて一週間ほど腰を抜かした事がある。なぜそんな無闇をしたと聞く人があるかも知れぬ。別段深い理由でもない。新築の二階から首を出していたら、同級生の一人が冗談に、いくら威張っても、そこから飛び降りる事は出来まい。
        </p>
      </div>
    </div>
  </a>
</li>
.card_item .desc_box {
  height: 64px;
  overflow: hidden;
  position: relative;
}
.card_item .desc_box.is-hidden::after {
  content: "…";
  font-size: 1.2rem;
  background: #fff;
  position: absolute;
  right: 12px;
  bottom: 0;
}
function textTrim() {
  $('.js-textTrim').each(function () {
    // テキストエリアの高さ取得
    var parentHeight = $(this).height();
 
    // テキスト自体の高さ取得
    var textHeight = $(this).find('p').height();
 
    // もしはみ出ていたら
    if (parentHeight < textHeight) {
      $(this).addClass('is-hidden');
    }
  });
}
textTrim();

擬似要素で「…」がついているように見せる方法です。
親要素の高さを子要素の高さを比較して、はみ出ていた場合にクラスを付けて擬似要素を表示しています。文字数をカウントしているわけではないので、微調整は必要ですが半角文字が含まれていても、同じ位置に三点リーダーを表示することが可能です。
※こちらはjQueryを使用しています。

まとめ

長い文字列の文末を「…」にして省略する方法についていくつかご紹介しました。
WordPressに入れているのであれば、<?php echo wp_trim_words( get_the_title(), 18, '...' ); ?> を使って文字のトリミングをするなど、これに限らず様々なやり方があるかと思います。

是非、状況に応じて試してみて下さい。

合わせて読みたい!