CSSを使って文章が長い場合に省略して末尾に省略記号(...)を表示させる方法のまとめです。
すべてp要素に対して適用するのを想定したコードで、全3パターンの実装方法と複数行対応させるスニペットを楽に使うmixinを紹介します。

1行の文章を省略

CSSで文章を省略させると聞くとまずこれを思い浮かべる人も多いと思います。
省略したい文章を括っている要素に対して下記のように記述することで、文章が長かったとしても1行に収まる形に省略され、文末に省略記号が表示されます。

p {
  white-space: nowrap;
  text-overflow: ellipsis;
  overflow: hidden;
}

複数行の文章を省略 #1

複数行の文章を省略して同じく文末に省略記号を表示させる方法で、省略したい文章を括っている要素に対して下記のように記述します。
省略させない行数は-webkit-line-clampの部分で指定し、このサンプルコードの場合は3を指定しているので文章が4行以上になってしまうときに3行目の文末で省略されて省略記号が表示されるようになっています。

p {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  overflow: hidden;
}

ただし、この方法はIEやFirefoxが非対応のため、実際の案件などになると使えない場面が多いかと思います。

複数行の文章を省略 #2

こちらは無理矢理感あり且つ詳しくは後述しますが細かく見ると正直実用性が低い方法ではあるものの、複数行の文章を省略される動きを擬似要素を用いて全ブラウザで実装する方法です。

動きとしてはまず文章を表示する高さを決めて、そこにoverflow: hidden;を組み合わせることでそれ以上になった場合は文章が見えないようにします。
そして、2つの擬似要素を用いて1つは省略記号の表示、1つは目隠しの役割をもつ要素として表示させることで複数行の文章が省略されているような見栄えを実装します。

使用する際は2箇所で高さを指定する必要があり、省略したい文章を括っている要素(サンプルコードではp)には「フォントサイズ × 行の高さ × 表示したい行数」を、その擬似要素(サンプルコードではp::before)には「フォントサイズ × 行の高さ × (表示したい行数 - 1)」をそれぞれ指定します。

このサンプルコードの場合は、フォントサイズが16px、行の高さが1.8、3行分表示(4行目以上は省略)させるのを想定したものになります。
また、calc()を使用せずに計算したものを直接記述する形でも実装できます。

p {
  position: relative;
  max-height: calc(16 * 1.8 * 3 * 1px);
  font-size: 16px;
  line-height: 1.8;
  word-break: break-all;
  overflow: hidden;
}
p::before,
p::after {
  position: absolute;
  background: #fff;
}
p::before {
  content: '...';
  top: calc(16 * 1.8 * (3 - 1) * 1px);
  right: 0;
  width: 1em;
}
p::after {
  content: '';
  width: 100%;
  height: 100%;
}

mixinで使いやすく

上記CSSで複数行の場合でも文章省略を実装できますが、見ての通り少し記述が多めですし、至る所で使うとなると毎回これを記述するのは面倒です。
これをSassを利用しているのであれば、下記のようなmixinを使うことで楽に使用できます。

@mixin text-truncate($font-size, $line-height, $line, $bg) {
  position: relative;
  max-height: $font-size * $line-height * $line + px;
  font-size: $font-size + px;
  line-height: $line-height;
  word-break: break-all;
  overflow: hidden;
  &::before,
  &::after {
    position: absolute;
    background: $bg;
  }
  &::before {
    content: '...';
    top: $font-size * $line-height * ($line - 1) + px;
    right: 0;
    width: 1em;
  }
  &::after {
    content: '';
    width: 100%;
    height: 100%;
  }
}

使用する箇所では引数に頭からフォントサイズ、行の高さ、表示したい行数、背景色を指定する形で下記のように記述し、このサンプルコードではフォントサイズが16px、行の高さが1.8、表示したい行数が3行、背景色が白(#fff)の場合になります。

@include text-truncate(16, 1.8, 3, #fff);

使用時の注意点

パッと見ではこれで複数行の場合でも文章省略を実装できるかのように見えますが、使用時には注意しなければいけない点があります。

注意点1:使用できるのは単色背景が指定されている箇所

擬似要素にはそれぞれ背景色を指定する必要があるので、この方法を使いたい箇所は単色の背景が指定されている必要があります。
繋ぎ目がハッキリしないものなのであればできなくもないですが、基本的に背景が透過されていたり背景イメージがある箇所では使えないと考えた方が無難です。

注意点2:フォントによっては中途半端に文字が途切れる

用意したデモもそのような見栄えになってしまっていると思いますが、表示させたい文章の文末と省略記号を表示させる擬似要素の幅がずれてしまうと、中途半端に文字が切れた表示になってしまいます。
使用する箇所の内容が決まっており、フォントサイズやフォントファミリーも完全に固定でどのブラウザでも相違ないという感じであれば位置などを細かく調整することで綺麗に実装することはできますが、そうでない場合で常に綺麗に表示させるための調整はなかなか難しいと思います。


複数行の文章省略について2パターンの方法を紹介したものの、ひとつはブラウザが限定され、ひとつは決して使い勝手が良いとは言えないので、やはりひと通りのブラウザで綺麗に実装となるとJavaScriptを用いるのが無難だとは思います。
どうしてもCSSのみで実装しなくてはいけない場面などあれば試してみてください。