できるだけCSSで縦書き段組みレスポンシブブログを作る

この「がとらぼ」ではないのだが、中の人が運営する某縦書きブログでは縦書き段組みを実現するために h2vR.js を利用させて貰っていた。Wordpressへの組み込みやレスポンシブ対応も簡単にできて、表示も細かなところまでほぼ期待通りなので非常に助かりました。
ただ、コンテンツが大きくなるとページ表示が凄く遅くなるのよね。
そこで、原点に立ち戻り、ほぼCSS(一部Javascript)で自力で縦書き段組みを実現することに。細かいところは触らないことにして、仕組みのメモ。

横書き
一般的な横書きのコンテンツ。文字の流れは左から右。スクロールは上から下方向。世の中の大部分、特に日本だと99%以上のウェブサイトはこの横書きかと。

縦書き
縦書きのコンテンツ。文字の流れは上から下。下から上っていう言語ってあるのかしら?改行して右から左方向にスクロールする。これは窓の広いPCのブラウザなどで見るにはコンテンツの高さが伸びすぎて見るのがツラい。そして横にスクロールというのが馴染みが無い閲覧者にとってはどう見て良いのかわからないという問題も。

縦書き段組み
これが、縦書きの段組みコンテンツ。1段あたりの高さが低いと新聞などに近いように見えるかも。文字の流れは上から下方向で、改行して右から左方向に視線を移すが、コンテンツエリアの左端まで進むと一段下の右端に移動する。段は上から下方向への流れとなる。縦書きでありながらブラウザの操作は一般的な縦スクロールなので初めて見る人でもわかりやすいかと。

CSSの縦書き段組みの問題点

  • ブラウザによって表示が大きく違う。
  • 段組みを行うと表示領域の大きさが正しく認識されなくなる。(レイアウト崩壊に)
  • 段組みを行うとコンテンツの量が少ない場合でも勝手に4段組みになりコンテンツ幅が狭くなる。
  • 幅・高さ・縦位置・横位置の指定が正しく処理されない。

縦書き段組み領域認識
上段の縦書き段組みのコンテンツの領域をブラウザは白背景の部分だと判断しているが、そのコンテンツはオーバーフローして下に溢れ出ている。下段のピンク背景部分のブロックは白背景ブロックに続いて表示されている。これはスタイルシートの指定に従えば正しい表示なのだが、上段のコンテンツが溢れて下段のコンテンツに覆いかぶさってしまっている。
これサイアク。

考え方

縦書き段組みコンテンツスクロール
段組みを行うと表示されるブロック領域の高さが実際より低く(狭く)なるのが一番の問題なのでブロック領域の高さで表示してその中でスクロールさせるという方法がある。( overflow-y )
ただし、この方法はブラウザの縦スクロールとは別にコンテンツ内に縦スクロールが存在するのでUIとしてどうなの?という問題がある。

スタイルにはどうやらブロック領域からオーバーフローしたコンテンツの高さを求めるプロパティは存在しないらしい。
しかし、Javascriptではこの実際のコンテンツの高さの属性を読み取ることができるらしい。( Element.scrollHeight )
そこで、ページ表示完了時にJavascriptでElement.scrollHeightを取得し、スタイルでボックスの高さを再指定することとする。

やること

  • 基本はスタイルシートだけで縦書き段組み。
  • スタイルシートは細かく指定すると環境依存でグッダグタになるので極力シンプルに。
  • どうしても使わざるを得ない部分だけJavascript。
  • WordPressに組み込むのでそのテンプレートを縦書き用に触る。
  • CSSはWordpressのテンプレートのstyle.cssに書く。
  • 縦書き段組みの表示用のJavascriptはWordpressのテンプレートのfooter.phpあたりに書く。

/使用中のWordpressテンプレDIR/template-parts/post/content.php
/使用中のWordpressテンプレDIR/template-parts/page/content-page.php
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>   ←最初(2行目あたり)
    <div class="vr-cont">                              ←挿入
        <div class="vr-box">                           ←挿入

    中略  コンテンツヘッダとコンテンツ本文部分

        </div><!-- .vr-box -->                         ←挿入
    </div><!-- .vr-cont -->                            ←挿入
</article><!-- #post-## -->                            ← 最終行

<article>内にvr-contとvr-boxというクラス名のブロックを2重で追加した。内側の(記事が入る)vr-boxの方は殆ど存在価値が無いが、段組みの境でルビを振ってたりするとそのルビが縦に切れて泣き別れになることがあるのでrightでズラして切れなくするような使い方を想定している。

/使用中のWordpressテンプレDIR/style.css (最後に追加)
.vr-cont {
	-webkit-writing-mode: vertical-rl;
	-moz-writing-mode: vertical-rl;
	-ms-writing-mode: tb-rl;
	-ms-writing-mode: vertical-rl;
	writing-mode: vertical-rl;
	-webkit-column-width: 20em;
	-moz-column-width: 20em
	-ms-column-width: 20em;
	column-width: 20em
	-moz-column-gap: 50px;
	-webkit-column-gap: 50px;
	-ms-column-gap: 50px;
	column-gap: 50px;
	column-rule-style: dashed;
	column-rule-width: 1px;
	column-rule-color: rgb(128, 128, 128);
	column-fill: auto;
	margin: 0 auto;
	line-height: 2.0em;
	width: 100%;
	height: 21em;
}

.vr-box {
	position: relative;
	right:5px;
}

writing-modeが縦書き・横書き・文字の流れる方法を指定する中枢。
columnが段組み関係。
縦書きではcolumn-widthが1段あたりの「高さ」になる。20emを指定しているので約20文字分の高さが1段となる。
column-gap関係は段と段の間の指定。
横書きでは行の高さ、縦書きでは行の幅であるline-heightを2.0emと広めに取っているがこれはルビ振りを前提としている。ルビを振らないなら2.0emは間延びし過ぎに思えるかも。

横書き段組みでは段の高さを意識することは少ないかもしれない。おそらくはなるべく複数の段で高さを均等に表示するのが好まれるかと。(column-fill: balance; 初期値) 縦書きの段組みで1コンテンツの詰め方を自動にするとブロック内のコンテンツが少ない場合でも(おそらく)4段で組まれることになる。この場合、すごく幅の狭い4段で表示されることになる。レイアウトによってはコンテンツの横がスッカラカンの広い空間になるかも。縦書きの段組みではコンテンツエリアに対してできるだけ前詰めの指定を行うべきかと。 (column-fill: auto; を指定)
ブロック要素の横幅いっぱいを使って前詰めしようとするので1段や2段で十分なコンテンツ量なら期待通りにそうなる。

また、各段の高さについては前述のようにcolumn-widthを指定しているが、これが効かないことがあるので別途heightを指定する。この場合、heightは.vr-contブロックの高さではなく1段の高さという点が注意。別途高さ調整が入っているならheight > column-widthになるようにした方が良いかと。上の例では別途(書いていないが)paddingで高さ1em分削られる前提で21em > 20emとしている。

Javascript

今回はWordpress用として書く。おそらく(殆どのWordpressサイトでは) jQueryを無視するわけにはいかない筈。(←書き方ね、$付きで書くと怒られるので・・)

/Wordpress DIR/wp-content/themes/使用中のテンプレDIR/footer.php
( </body> の直前くらいに挿入するなど)
<script type="text/javascript">
    //ページ読み込み後に実行
    jQuery(document).ready(function () {
        reDesign();
    });
    //ブラウザサイズ変更時に再実行
    jQuery(window).resize(function () {
        reDesign();
    });

    function reDesign() {
        var scH = jQuery(".vr-cont").prop('scrollHeight'); //高さ取得
        var primH = (scH + 50) + 'px';  //#primaryの高さは更に+50px

        jQuery('#primary').css({ height: primH });  //高さを指定して反映
    };
</script>

オーバーフロー分を含むコンテンツのブロックの高さを取得して、その高さをそのまま、または必要に応じて触ってから、スタイルシートで指定して反映させる。
そのコンテンツの高さを得るために、これらの処理はページを読み込んでから実行する。2行目の.ready()がページ読み込み後に実行する指定。
上の例では#primaryだけに高さを設定しているが、実際には他の要素であったり複数であったり様々な計算を加えなくてはならないかもしれない。

使用するテンプレートにもよるが、レスポンシブには対応する筈。ただし、ページ読み込み後に1度高さを取得してそれを基に反映させたっきりでは、ブラウザの窓の大きさ(幅)を変更した場合などにレイアウトが崩れることになる。つまりブラウザの窓の大きさが変わったときに再計算して反映させる必要がある。それはJavascriptの$(window).resize()でreDesign()を呼び出してやれば良い。多くのWordPressサイトではjQuery(window).resize()ね。

上の例は(ファイル配置が)WordpressのテンプレートのTwentySeventeenを想定して書いているが、TwentySeventeenでは正しく表示されないかもしれない。(TwentySeventeenでは試していないので)
Wordpressのテンプレートの構造を調べて配置を担っているブロック要素の高さに反映させること。

この記事ではコンテンツ本文に関わる部分の縦書きしか触っていないけど意外と簡単よね。下手にこねくり回さずにできるだけ単純化してやった方が上手くいくみたい。(ブラウザ別の話ね)

コンテンツ中に画像やフレームなどが存在すると段の変わり目付近にそれらが段の左端と次の段の右端に泣き別れで表示されることがある(特にChrome)。固定幅のコンテンツなら位置の調整が可能だろうが、完全レスポンシブだと調整が無理なので困ることに。この場合は画像やフレームを横書き(writing-mode: lr-tb or horizontal-tb)指定のブロック要素に入れて設置すると泣き別れにならずにその全体が次の段の右端に表示されることになるかと。なぜ横書きブロックでは正しく表示され縦書きだと泣き別れになるのかは不明。



1件のコメント

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です