読者です 読者をやめる 読者になる 読者になる

縦書きでレスポンシブなブログを作った

趣味で会社の人のサイトを作った。縦書きでレスポンシブなブログ。prismic.ioNext.jsで作った。

ウェブデザインに縦書きを活かすことは難しい。部分的に取り入れることはできても、縦書きの文章を主要な要素として扱うのはかなり難がある。というのも、ウェブサイトは縦にスクロールするのが当たり前だけど、普通に縦書きで実装すると横スクロールになるからだ。

横書きでは文章は上から下に流れ、ページは縦スクロールになる。対して縦書きの場合、文章は右から左に流れるため、横スクロールになる。スクロール操作が不自然だと目に見えてユーザービリティが低下するので、どうしても当たり前のスクロールができるようにしたい。

幸い、縦書きにしながら縦スクロールにする方法はひとつある。新聞や雑誌のように段組にすることだ。

それはcolumnsを利用すれば、一見簡単にできそうな感じはする。けど、僕が望む仕様を実現しようとすると案外難航した。僕の今回の実装は次のような仕様になっている。

  • 縦書き
  • 段が最初の右端から左端、あふれたら次の段からという風に順番に埋められる
  • 文章の量には依存しない
  • レスポンシブ

columnsは、全ての段の高さを揃えようとする。そのため、最初の段から順番にブロックの中を埋めていくことはできない。ハック的に解決するしかなかった。

.ArticleBody {
  width: 100%;
  max-width: 100%;
  height: 14rem;
  writing-mode: vertical-rl;
  columns: 14rem;
}

高さを固定することで、最初の段からはみ出そうになるまで別の段にテキストが流れることはなくなる。はみ出した分は次の段へ移り、おおよそ望む形になる。

ただそうすると、要素自体の高さは一段分にしかならない。これでは次に続く要素がこの要素と重なってしまう。JavaScriptで要素の高さ分のpaddingを設定することで解決した。

const adjustSize = el => {
  const fullHeight = el.scrollHeight
  const defaultHeight = Number(getComputedStyle(el).height.replace('px', ''))
  el.style.paddingBottom = `${fullHeight - defaultHeight}px`
}

scrollHeightは要素のスクロール分も含めた高さを返す。正直これまでscrollHeightの存在を知らなかったんだけど、コンソールに勘で$0.scro...とか打ってたら候補で出てきたのでびっくりした。

この段組の仕組み自体はIE11を含むクロスブラウザで動作する(このサイトでは対応してない)。ただ、Firefoxの挙動が壊れていて、デベロッパーツールでスタイルを付け外しすると直るって感じだった。今回はsetTimeoutで擬似的に再現した。

ついでに言うと、Firefoxは縦書き周りのバグがかなり厳しくて、今回作ったサイトではFirefoxだけ別のデザインにした部分がある。あと、CSS VariablesとかLogical Propertiesを使いたかったので、IEとEdgeは無視した。

この段組の実装は結構珍しいアイデアな気がしてて、さっき縦書きアワードのやつ一通りみたけどやってる人がいなかったので世界初の可能性がある。なんか金とか欲しい。

Firefoxの実装が直ったら仕事でも使えなくは無いかな、という感じだと思う。ちょっと怖いけど。

ちなみにcolumn-fill: autoではやりたいようにならなかった。


裏側の仕組みもちょっと遊んでみてる。

このブログの記事は僕が書いていくという訳ではない。なのでGitにマークダウンのファイル作るとかじゃなくて、CMSで管理したいということだった。

まともにWordpressとかでCMS環境を作るのはつらいしやりたくない。データベースとか勝手に管理してくれて、REST APIだけ提供してくれるようなのないかなーと思ってたら、案外いろいろあるらしい。なんとなくprismic.ioというやつを選んだ。

使い方は、カスタムフィールドみたいなのをJSONで定義して(GUIもある)、後はそれに合わせたフォームを提供してくれるのでデータを追加していくだけ。基本的にはいい感じなんだけど、フォームにIME周りのバグが結構あって、使えても社内ツールくらいかなと思った。

他にもTumblrとかGoogle Spread Sheetで管理するのも試したけど、これの優位点は自由にフォーマットを決められて画像の管理もしてくれるところだった。

CMSの更新時にはWebhookを飛ばしてくれるので、そのときにCIでビルドしてデプロイしたら静的サイトとして作れる。けど、ビルド環境作るのがだるくてさぼった。代わりにNext.jsを使った。

Next.jsはReactでIsomorphicなウェブアプリを作るためのフレームワーク。ビルド環境とかルーティングの仕組みとかが組み込まれてて、驚異的に楽。ただ、CSS in JSが前提なので普通のCSSを書く環境作るのがめんどくさかったのは良くなかった。CSS in JSの類のものがCSSの根本的な難しさを解決するとは思わない。SPAの人たちがみんなそこに向かってるのはどうなんだろう……。


ということで結構楽しかったです。ソースとかここです。