三点リーダー(text-overflow: ellipsis)の適用を判定する方法と注意点

2 min read読了の目安(約2200字
三点リーダー
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
  • テキストがはみ出すことを防ぐ
  • 文が終わりではないことを示す

ために三点リーダーを適用することがあるかと思います。
しかし、ただ適用しただけでは三点リーダーによって省略された記述の情報が抜け落ちてしまいます。

この問題を解決するために、三点リーダーが適用される場合のみ

  • hover時にTooltipを表示する
  • focus時に全文表示させる(レイアウトシフトに注意)

などを行うことで、ユーザに抜け落ちた情報を届けることができます。
この記事では、この機能を実現するためのoverflowの判定方法と注意点を説明していきます。

overflowの判定方法

判定するには HTMLElement.offsetWidthElement.scrollWidth の値を比較する必要があります。

element.offsetWidth < element.scrollWidth

三点リーダーが適用されていれば、この条件式が true になります。

https://stackoverflow.com/questions/7738117/html-text-overflow-ellipsis-detection/10017343#10017343

overflowの判定での注意点

しかし、実装する上で注意することが2つあります。

左右のborderの幅

条件式の左辺で用いた HTMLElement.offsetWidth が要素に対する何の値であるかを示した図です。

offsetWidthの説明図
MDN Web Docs (offsetWidthの例)

HTMLElement.offsetWidth は border を含むプロパティであることが読み取れます。
そのため、左右のborder幅を適用している場合は、その幅だけ offsetWidth から引いてあげる必要があります。

element.offsetWidth - (BORDER_LEFT_WIDTH + BORDER_RIGHT_WIDTH) < element.scrollWidth

三点リーダーが適用されているのに判定がfalseになる

こちらは多少厄介な問題です。
三点リーダーが表示されない(幅に対してテキストの方が短い)場合、offsetWidthscrollWidth の値は同じになります。

しかし、以下のGIFの3つ目のテキストのように 三点リーダーが適用されているのに判定がfalseになる 場合があります。

厄介なパターンのキャプチャ

なぜこのような現象が起きるかというと、scrollWidth は値を丸めて整数にしているためです。

このときのそれぞれの値はどうなっているかですが width: 100px とすると

  • offsetWidth: 100px
  • scrollWidth: 100px(本当は 100.25px といった値)

のようになっています。
この結果、三点リーダーが適用されているのに判定がfalseになる のです。

今回使用したコードは以下に置いておきます。

きちんとテストしていないので、ブラウザや環境によっては3つ目のテキストでTooltipが表示されていることがあるかもしれません。エディタを開いて width の値を調整したら再現できます。

この記事を書いてて、(たぶんレンダリングエンジンが担ってる)三点リーダーを適用するしないの判定処理についても深ぼりたいなと思いました。

Element.getBoundingClientRect を使用すれば小数点を含む offsetWidth が取得できるのですが、丸める前の scrollWidth は取得できなそうなので取得できる方法があればコメントで教えていただけたらと思います。