【css】行数指定でテキストを省略できるline-clampを使ってみた【IE11別途対応】

こんにちは、katori@xxbicottです。
サイト制作をしていると、文章の行数を制御したいところがちょこちょこ出てきますよね。
例えば、ブログの記事一覧のリード文。
私はこれまでテンプレート側で出力文字数を制限して対応していたんですが、微調整効かないのでレスポンシブがめんどくさいなぁと思っていました_(┐「ε:)_

そんな時にline-clampというcssプロパティを「意外と知られていない、CSSで文末を3点リーダーで省略表示するline-clampプロパティの効果的な実装方法」というcoliss様の記事で発見。
使ってみるとこれまで格闘してたのはなんだったのか、というくらい便利だったので、使い方や気づいたことなどをまとめてみました!

line-campの使い方

CSS プロパティの-webkit-line-clamp は、特定の条件を満たしたコンテンツを指定した行数に制限することができます。
つまり、出力する文字数を調整する必要がない!

実際にサンプルを作ってみました。

See the Pen
clamptest
by BICOxxx (@BICOxxx)
on CodePen.

行数指定に関するcssだけ抜き出したのがこちら。

/* 行数指定部分 */
.post_content .ttl {
	display: -webkit-box;
	-webkit-line-clamp: 3;
	-webkit-box-orient: vertical;
	overflow: hidden;
}
@media screen and (max-width: 700px){
	.post_content .ttl {
		-webkit-line-clamp: 4;
	}
}

上記では「テストテストテストテスト(省略)」の部分に対して、700px以下のデバイスの場合は4行に制限、それ以外の場合は3行に制限されて表示するよう指定しています。
ちなみに文章が指定した行数より長い場合は文末に自動で「…」が付与されるようになっている優秀さ。

-webkit-line-clampのポイントは、以下の組み合わせのときのみ使用できることです。

  • display プロパティに -webkit-box もしくは -webkit-inline-box が設定されている
  • -webkit-box-orient プロパティに vertical が設定されている

併せて、指定行数以降の文字を表示させないためのoverflow: hidden;も必要。
なので、以下はセットで使いましょう。

	display: -webkit-box;
	-webkit-line-clamp: 数値;
	-webkit-box-orient: vertical;
	overflow: hidden;

ほとんどのブラウザでは、これだけで行数指定が行えます。

IE11対応する場合

line-clampプロパティは、残念ながらIE11に対応してません。(2019/11時点)

これらのブラウザでは、前述のブログにて紹介されていたClamp.jsというjsが便利そうだと思い試してみました。
公式に載っていたサンプルコードはこんな感じ。jQueryがなくても動作します。

<script src="../clamp.js"></script>
<script>
var header = document.getElementsByTagName('body')[0].getElementsByTagName('h1')[0];
$clamp(header, {clamp: 1, useNativeClamp: false});
</script>

useNativeClampオプション

実用性を考えるならline-clamp非対応ブラウザだけこのjsを発火させたいなぁ…と使い方を見ていたらuseNativeClampというプロパティを発見。

useNativeClamp
(Boolean). Enables or disables using the native -webkit-line-clamp in a supported browser (ie. Webkit). It defaults to true if you’re using Webkit, but it can behave wonky sometimes so you can set it to false to use the JavaScript- based solution.

日本語訳)
useNativeClamp(ブール)。 サポートされているブラウザー(Webkitなど)でネイティブの-webkit-line-clampの使用を有効または無効にします。 Webkitを使用している場合はデフォルトでtrueに設定されていますが、不安定な動作をすることがあるため、falseに設定してJavaScriptベースのソリューションを使用できます。

「ネイティブの-webkit-line-clampが使えるブラウザではjsは使わずプロパティを有効にして使うよ!」ということならぴったりじゃないか!と一瞬思ったんですが、後半の文章から、うまく動かない時があるから-webkit-line-clampが使えるブラウザでもそのcssプロパティすべて無効にして全てのブラウザでこのjsを使用しようねという話だった模様。
公式で推奨されてない以上このオプションの利用は断念しました。

UAでIE11だけ切り分けで実行する

ということで、UAでIE11だけ切り分けて適用する方法を使いました。
先ほどのHTMLに以下を追記します。
* 下記は複数の要素の行数に適用するケースを想定。一つの要素だけに適用するならeach関数は不要

<script
src="https://code.jquery.com/jquery-3.4.1.js"
integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU="
crossorigin="anonymous"></script>
<script src="clamp.min.js"></script>
<script>
jQuery(function($) {
	var userAgent = window.navigator.userAgent.toLowerCase();
	if(userAgent.indexOf('msie') != -1 || userAgent.indexOf('trident') != -1 ) {
		if($(".post_content .ttl").length > 0){
			$(".post_content .ttl").each(function(i, elem) {
				$clamp(elem, {clamp: 3})
			});
		}
	}
});
</script>

サンプル

phpでUAを切り分けるならこちら。

<?php // IEのみ
$browser = strtolower($_SERVER['HTTP_USER_AGENT']);
if (mb_strstr($browser , 'trident') || mb_strstr($browser , 'msie')): ?>
<script
src="https://code.jquery.com/jquery-3.4.1.js"
integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU="
crossorigin="anonymous"></script>
<script src="clamp.min.js"></script>
<script>

jQuery(function($) {
	if($(".post_content .ttl").length > 0){
		$(".post_content .ttl").each(function(i, elem) {
			$clamp(elem, {clamp: 2})
		});
	}
});
</script>
<?php endif; ?>

一点気になったのが、このjs自体は便利なことにレスポンシブ対応しているようで、読み込み後ウィンドウ幅を変えても指定した行数で制限できます。(つまり-webkit-line-clampと同じ挙動)
しかし、IE11では最初の読み込み時の指定行数に対応する文字分で固定されてしまう事象を確認。

同様の事例を調べても見当たらなかったんですが、困る場合はウィンドウサイズ変えたら際読み込みなどの処理は検討すると良さそうです。

さいごに

IE11以外はおおよそ使えるようになったことで、本当に有用なプロパティだなぁと思います。
まだW3Cでは草案段階のプロパティなので仕様が変更される可能性があることを留意しつつ使っていきましょう。