「v-btnコンポーネントのテキストが折り返されない問題」における戦いのいく末を覗く

この記事は、Advent Calendar 2021 / ライブラリ・フレームワーク「Vue Advent Calendar 2021」の22日目の記事です。

はじめに

こんにちは、AI・IoTサービス開発部の岩丸です。 皆さま良きエンジニアライフを満喫されておりますか。4月に新卒入社し気づいたら12月となってしまいました。1年が経つのは早いものですね。

12月といえば、1年で1番技術界隈が盛り上がるイベントでAdvent Calendar (Qiita様主催)があるかと思います。 毎年Advent Calendarには参加しているのですが、今年は本記事で参加できたらと思います。


普段の業務では主にVue.js + TypeScript + Vuetifyと格闘しております。VuetifyMUIなどのCSSライブラリを使用していると、非常に多くの恩恵を受ける反面デフォルトのCSS設定に悩まされることが多々あるかと思います。

今回はVuetifyが提供するButtons(v-btnコンポーネント)でハマったことについてご紹介したいと思います。

目次

解決したい問題

今回v-btn使用時にハマったのは以下のような問題です。内部のテキストが折り返されず、ボタンUIの枠をはみ出てしまうというものでした。

f:id:optim-tech:20211213184803p:plain

本問題が発生した前提条件としては以下の通りです。

  • デザインの関係上、max-widthが設定済みであった
  • レスポンシブ対応のため、サイズを変更してもはみ出してはいけない
  • ユーザー入力文字列を表示するため、最大文字数が存在する(長い文字列が入力されることもある)


10人いたら8人はハマってそうな問題だと思いますが解決方法には辿り着けませんでした。 そこでVuetify公式が提供するライブラリから直接問題の謎を解明すべく、我々はアマゾンの奥地へ向かったのであった。


Vuetify公式のGitHubはこちらです。

github.com

公式提供のコードを覗いてみると...

公式が提供する/components/VBtn/VBtn.sassを覗いてみると、40行目に以下のような記述を確認できました。(以下一部抜粋です) このCSS設定を見る限りだとwhite-spacedisplayの2点を上書きしてやれば良さそうです。

.v-btn
  align-items: center
  border-radius: $btn-border-radius
  display: inline-flex
  flex: 0 0 auto
  font-weight: $btn-font-weight
  letter-spacing: $btn-letter-spacing
  justify-content: center
  outline: 0
  position: relative
  text-decoration: none
  text-indent: $btn-letter-spacing
  text-transform: $btn-text-transform
  transition-duration: $btn-transition-duration
  transition-property: box-shadow, transform, opacity
  transition-timing-function: $btn-transition-fn
  user-select: none
  vertical-align: middle
  white-space: nowrap


white-space: nowrapは以下のようなCSS設定となっています。そのため、max-widthを超えた場合に行の折り返しを実施してくれませんでした。

nowrap

normal と同じくホワイトスペースを詰めますが、行の折り返しは行いません。

解決結果

解決したいボタンコンポーネントのCSS部分に下記の記述の追加を行います。 今回は子コンポーネントに対してもCSSの適用を行いたいので、Deep Selecterである::v-deepを設定しています。

<style lang="scss" scoped>
::v-deep .v-btn {
  display: block !important;
  white-space: normal !important;
  overflow-wrap: anywhere !important; // Safari、IEでNo support
  // word-break: break-word  // IEのみNo support、MDN非推奨
}
</style>

実際に表示してみると無事に折り返されていることが分かります。とても良かったですね。

f:id:optim-tech:20211213184801p:plain


今回のケースではoverflow-wrap: anywhereも追加しております。 これは改行がない長文(「あ」の単語の連続など)の場合にも折り返しをしてもらうためです。

ただ、overflow-wrap: anywhereを使用する際の注意点としては 、MDNドキュメントにも記載があるようにSafariおよびIEでサポートされていない点です。 Safariまでが対象範囲の場合はword-break: break-wordを指定してください(ただし、MDN非推奨であることに注意)。

おわりに

今回はVuetifyの実装時にハマったCSS問題についての紹介を行いました。 CSS問題でハマることにより実際のCSSライブラリがどのように実装されているのかを知ることができ、よりVueに対する理解が深まりました。

OPTiMではフロントエンド技術に知見の深いエンジニアに限らずさまざまなエンジニアをお待ちしております。少しでもご興味のある方はこちらをどうぞご覧ください。

www.optim.co.jp