縦書きウェブの道 「おはなしのおはなし」リニューアル
開発::website
序
私のサイトの中で「水樹悠」名義で物語、文筆などの話題を取り扱うはるかのおはなしのおはなしがリニューアルされた。
このサイトはジャンル的な意味でも、名義的な意味でも意義のあるものではあるが、ここでは重要なのは、「おはなしのおはなし」は縦書きのウェブサイトであるということだ。
サイトとしてはv3にあたり、v1ではまず縦書きにトライしたが、状況によってきれいに表示されなかった。
v2ではこれを安全に表示できるようにした上で、縦書きと横書きを切り替えられるようにした。
v3では再び縦書き専用にした上で、v1のときにやりたかったデザインを実現した。
一見なんてこそもないようだが、実はかなりの知見が盛り込まれている。
縦書きボックスの「高さ」
通常のボックスは横幅は制限しやすく、縦は「なり」で伸びるというのが普通だ。
一方、縦書きにした場合はそれが縦が制限されて横が伸びるようになる。
vertical-rl
であれば左へスクロールするのだ。
このとき、ボックスはheightが縦方向、widthが横方向のままでこれは横書きと変わらない状態である。
ところが、縦書きされているボックスの「高さ」の解釈という問題が発生する。 普通の横書きならば高さや幅を制限されていないボックスは、コンテンツを収められるだけのボックスが生成される。 しかし、縦書きの場合、ボックスの高さが内容と合わない。
「おはなしのおはなし」の場合はカラム機能を使っている。 では例えば、
: 3; column-count
の場合どうなるか。
この場合、100vh
相当のボックスが生成され、これを3つに分割したカラムになる。
高さは100vh
存在している。
これを超過するコンテンツを与えると、下方向にoverflowする。
: 20em; column-width
の場合、FirefoxとChromiumで全く異なる結果になる。
Firefoxの場合は、20em
のカラム1段分のボックスが生成される。
2段目からはoverflowする。
Chromiumの場合は、100vh
に近いボックスを生成し、それを20em
のカラムで埋める。
100vh
を超過するコンテンツはoverflowするが、コンテンツが少なくてそれぞれのカラムを埋められない場合、すべてのカラムに均一にコンテンツが入るように分散させる。
これはものすごく違和感のある表示になる。
つまり、column-count: auto
であるときの解釈が違うのだ。
Firefoxの場合は、最低1段で構成されるとし、内容によって増やしていくが、それに合わせてボックスは伸長しない。
Chromiumの場合は、(column-count
が設定された場合と同様に)ビューポートにフィットさせ、ボックスは伸縮しない。
column-width
とcolumn-count
の両方が指定された場合は、Firefoxではcolumn-width
分の高さを持つカラムをcolumn-count
個並べたボックスが生成される。
が、Chromiumはこの場合も100vh
相当のボックスを生成し、column-width
を無視する。
縦書き関連機能はChromiumはちゃんと実装していない感じが強い。text-transform: full-width;
もないし。
こうしたことから縦書きボックスを普通のウェブのように柔軟に配置しようとすると思わぬ事態に遭遇する。 縦書きのボックスの高さはコンテンツ分なくoverflowであるため、縦書きボックスの下に配置されたボックスは、縦書きボックスのコンテンツの途中に見える場所に配置されてしまう。
解決方法としては、まずひとつは「縦書きボックスの下にボックスを配置せず、縦書きボックスの高さに左右されるボックスも配置しない」がある。 正しく高さをコントロールできないなら、そもそも高さをコントロールすることを諦めるという方法だ。
「おはなしのおはなし」はこの方針をとってはいるが、wideビューの場合はグリッドレイアウトになっており、サイトタイトルと縦書きボックスからなる行になっている。
行の高さはグリッドアイテムの高さが高いほうになるが、column-width
のみが指定されているため、Firefoxでは1段分の高さになり、通常はサイトタイトルのほうが長いため、サイトタイトルの高さになる。
ところがChromiumでは縦書きボックスが100vh
になるため、行の高さも100vh
になる。
もともとサイトタイトルは背景色をつけていたのだが、背景色をつけていると「ボックスの高さ」というのが非常に目立つため、wideビューでは背景色をつけないように変更した。
もうひとつの解決策は、「縦書きボックスの高さが外部要因によって確定するようにし、overflow
を設定する」である。
縦書きボックスの高さがauto
である場合、前述したようにどのような高さになるかは、Firefoxではcolumn-width
とcolumn-count
に左右され、Chromiumはビューポートに固定されるためブラウザ間でも違いがある。
しかし、縦書きボックスの高さが固定されている場合、FirefoxもChromiumも縦書きのボックスを指定されたボックスにした上で、カラムがそのボックスの高さに合うように適合させる。
column-count
が指定されている場合はこのボックスの高さに指定された数のカラムを設置しようとし、column-width
が指定されている場合は、指定された高さに最も近くなる段数にしようとする。
そして、問題はoverflow: visible
であるために、実際には意図した高さのブロックになっていないにもかかわらず、見かけ上は高さが「なり」で続いているように見えるということなので、ブロックの高さを意図に合わせたら、次はoverflow
をコントロールすれば良い。
基本的にはoverflow: auto
で良い。
heightが明確になっていればコントロールしやすい挙動になるので、おそらくその状態を想定しているのだと思うが、実際は横書きと同様に「なり」で伸びて欲しいためあまりよくない。 CSSで縦方向にブロックをセンタリングする方法もないし、ページの下端に合わせたデザインにしようとするとJavaScriptが必要になるため、横書きと比べて圧倒的に筋悪なページになってしまうことが避けられない。
もうひとつブラウザによる違いとして、縦書きのブロックをスクロールさせるとFirefoxの場合は左側にスクロールバーが出る。 Firefoxのほうが丁寧に縦書きの状況に対応しているが、Vertical-RLは右にスクロールバーがあったほうが良い気がする。
ボックスレイアウトの苦心
「おはなしのおはなし」は複雑なブロック構成になっており、標準ではGridレイアウトになっている。 ネストはされておらず、構造的には
1 2
3 4
だ。
これが幅が狭くなるとサイトタイトルを右に表示する空間がないため
1 2
3
4
に変わる。
そしてスマートフォンサイズの幅になるとGridだと幅がはみ出してしまうため、Flexレイアウトに変更している。
では各エレメントの順番はどうなっているかというと
ボックス | in HTML | wide | narrow | mobile |
---|---|---|---|---|
メニューボタン | 2 | 2 | 2 | 1 |
サイトタイトル | 1 | 4 | 1 | none |
記事タイトル | 3 | 1 | 3 | 2 |
本文 | 4 | 3 | 4 | 3 |
である。
Gridのときはgrid-column
とgrid-row
を指定し、Flexのときはorder
を指定して入れ替えている。
これをメディアクエリで切り替える仕組みだ。
仕組み自体はそれほど難しくはないが、頭の中で考えてやるとこんがらがらりやすいものではある。
また、wideは2x2のグリッドだが、narrowでは2x3のグリッドであり、こちらもgrid-column: 1 / -1
を用いて横方向をフルに使うようにしている。
HTML上の表現と表示上の表現が異なるのは、Vivaldiのリーダービューやテキストブラウザ、音声ブラウザなどで閲覧する場合はエレメントの順番が影響するので、読みやすい順番になっていたほうが良いからだ。
ここらへんの技術を私がちゃんと使えるようになったのはここ数年の話。 「おはなしのおはなし」は2019年からあり、「あの頃は未熟だったなぁ」の感しきり。