0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

アプリ内ブラウザで縦書きの高さがガタつく — vh をやめて px に固定する

0
Last updated at Posted at 2026-08-13

こんにちは。小学生向けのニュースサイト、こどもニュースをつくっています。

このサイトには記事を縦書きで読む機能があります。縦書きは高さを決めないと行が折り返せないので、本文のブロックに高さを指定しています。

最初は 70vh と書いていました。SNS のアプリ内ブラウザで開いたときに、本文がガタガタと組み直され続けました。

何が起きていたか

アプリ内ブラウザ(WebView)では、スクロールに応じて上下のツールバーが出たり隠れたりします。そのぶん、表示領域の高さが変わります。

vh は表示領域の高さに対する割合なので、ツールバーが動くたびに値が変わります。

横書きなら、高さが少し変わっても見た目は変わりません。中身の高さは文章の量で決まるからです。

縦書きは違います。高さが変わると 1 列に入る文字数が変わり、全部の列が組み直されます。読んでいる最中に文字の位置が動くので、非常に読みにくいです。

しかもツールバーの出入りはスクロールに連動するので、スクロールするたびに組み直しが起きます。

高さを px で固定する

対処は、表示領域に追従させないことです。初回に高さを測って、px の固定値として持ちます。

height: var(--kn-vbody-h, 70vh);

CSS 変数にしておいて、値は JavaScript が入れます。

70vh 直書きだとアプリ内ブラウザ(WebView)のツールバー出入りで高さが揺れて
縦書きが組み直され続けるため、boot script が innerHeight から固定 px を
--kn-vbody-h に入れる(幅変化時のみ再計測)。JS 無効時のみ 70vh フォールバック。

innerHeight から計算した値を入れるので、初回の見た目は 70vh と同じです。違うのは、その後に表示領域が変わっても値が変わらないことです。

フォールバックとして 70vh を残しているのは、JavaScript が無効な環境のためです。CSS 変数の第 2 引数は、変数が未定義のときに使われます。この形なら、スクリプトが動かなくても縦書きは成立します。

再計測の条件

固定してしまうと、画面を回転させたときに高さが合わなくなります。

そこで、幅が変わったときだけ再計測することにしました。ツールバーの出入りでは幅が変わらないので、再計測は走りません。回転や、ウィンドウのサイズ変更では幅が変わるので、そこで測り直します。

resize イベントは、高さだけの変化でも発火します。イベントの発火をそのまま再計測の条件にすると、元の問題に戻ります。「何が変わったときに再計算するか」を自分で決める必要がありました。

初回のペイント前に入れる

この値は、最初の描画の前に入れます。このサイトには、読者の設定(文字サイズ・書体・縦書きか横書きか)を最初のペイント前に反映するブートスクリプトがあるので、そこに相乗りさせました。

後から入れると、70vh で一度組んでから固定値で組み直すことになります。ちらつきの原因が 1 つ増えるだけです。

似た問題は他にもある

この手の「表示領域の高さが動く」問題は、モバイルでは広く知られています。100vh にすると画面からはみ出す、というのが典型です。

いまは dvh / svh / lvh という単位があり、これらを使う手もあります。ただ、dvh は「動的な表示領域」なので、今回のケースでは同じように揺れます。svh(最小の表示領域)なら揺れませんが、ツールバーが隠れているときに余白が出ます。

このサイトでは、初回の値で固定するほうが目的に合っていました。読んでいる最中に組み直されないことが最優先で、多少余白が出るのは許容できます。

単位の選択より先に、「何を固定したいのか」を決めるほうが早い、というのが結論でした。

気づき方

この問題は、手元の PC ブラウザでは再現しません。開発者ツールのモバイル表示でも起きません。ツールバーの出入りが無いからです。

実機のアプリ内ブラウザで開いて、初めて気づきました。

モバイルの表示領域まわりは、実機でしか出ない挙動が多い領域です。とくにアプリ内ブラウザは、通常のブラウザとも挙動が違います。リンクを SNS で共有するサイトなら、一度は実機のアプリ内ブラウザで開いておく価値があります。

まとめ

  • アプリ内ブラウザではツールバーの出入りで表示領域の高さが変わる
  • 縦書きは高さが変わると全部の列が組み直されるので、vh を使うと読めなくなる
  • 初回に測った値を px として CSS 変数に入れ、以降は追従させない
  • CSS 変数のフォールバックを使えば、JavaScript が無効でも成立する
  • 再計測の条件は自分で決める(幅の変化だけ)。resize イベントをそのまま使うと元に戻る
  • 値は最初のペイント前に入れる。後からだと組み直しが見える
  • この種の問題は実機のアプリ内ブラウザでしか再現しない
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?