yuw27b’s blog

技術メモと雑記

writing-modeがFirefoxでも使えるようになっていた

CSSで縦書きテキスト

CSSのみで縦書きテキストを実現するには、writing-modeプロパティを使いますが、Firefoxだけが長いあいだ未対応でした。
Can I use... Support tables for HTML5, CSS3, etc

2015年11月現在、この仕様は勧告候補の段階なので、ブラウザによってベンダープレフィックスが必要だったり、指定する値の記述方法がばらばらだったりもします。
そして、未対応だったFirefoxは、バージョン41からは標準で対応するようになったとのこと(ベンダープレフィックスもなし!)。
Firefox 41 for developers - Mozilla | MDN

ほぼ全てのブラウザが対応したことに

IEは(値の記述方法は独自仕様ですが)6から使えますし、ChromeSafariはベンダープレフィックス付きで対応しているので、Firefoxが対応したことでほぼ足並みが揃ったことになります。

現時点で各ブラウザに対応させるには、こんな感じになります。

writing-mode: tb-rl; /*IE*/
-o-writing-mode: vertical-rl; /*Opera*/
-webkit-writing-mode: vertical-rl; /*Chrome, Safari*/
writing-mode: vertical-rl; /*Firefox, Edge*/

※縦書きで、行が右から左へ進む場合の指定方法です

まだフォールバックが必要?

writing-modeに対応したFirefox41のリリースは2015年9月22日と(これを書いている時点からすると)かなり最近なので、基本的に自動アップデートがかかるとはいえ、まだ40以前のバージョンのユーザーもいるかも?という不安もあります。
さらに、FirefoxにはESRという法人向けの延長サポート版が存在していて、こちらはまだバージョン38です。これが2016年5月末までのサポート予定とのことなので、やはりそれまでは何かしらフォールバックを用意したほうが良さそうです。

フォールバックも書いてみた

縦書きのテキストが横書きになってしまった場合、コンテンツのレイアウトにかなり影響が出るので、それを回避するべく以下のような方法をとりました。

  • writing-modeが使えない場合、横書きのテキストを90度回転させる
  • 回転はCSSのtransformプロパティで行う(これはFirefox16から対応している)
  • ブラウザがFirefox40以前かどうか、という点はJavaScriptで判別する

日本語の場合はテキストが横倒しになるので、writing-modeが適用された状態と全く同じにはなりませんが、フォールバックということで、そこまでの対応としました。

Chrome(writing-modeに対応)
f:id:yuw27b:20151110231711j:plain

Firefox38(writing-modeに非対応)
f:id:yuw27b:20151110231718j:plain

HTML

<div class="box">
    <p class="text">日本語のテキスト<br />改行</p>
</div>


CSS

.box {
	margin: 20px;
	border: solid 1px #E00;
        line-height: 0;
}

.text {
	display: inline-block;
	margin: 0;
	font-size: 18px;
	line-height: 1.5;
	color: #000;
	background: #CCC;
	writing-mode: tb-rl;
	-o-writing-mode: vertical-rl;
	-webkit-writing-mode: vertical-rl;
	writing-mode: vertical-rl;
}

.text-rotate { /*writing-mode fallback*/
	transform-origin: 0 0;
	transform: rotate(90deg) translateY(-100%);
}


JavaScript(※DOMを読み込み終わってから実行)

  var ua = window.navigator.userAgent;
  if (!('indexOf' in Array.prototype) || ua.indexOf('Firefox') === -1) {
    return;
  }
  var browser_str = ua.match(/Firefox\/.*$/);
  var version = parseFloat(browser_str[0].replace(/^Firefox\//, ''), 10);
  if (version < 41) {
    document.querySelector('.text').classList.add('text-rotate');
  }

包含ブロック(.box)に赤い枠線を、テキストの要素(.text)にはグレーの背景をつけました。
テキストの要素(.text)に「display: inline-block」を指定しているのは、rotateを使用した(フォールバックの)場合に、.textの高さが.boxの横幅100%になってしまうからです。

また、画像で分かるように、rotateを使用した場合は包含ブロックの高さは伸びません。
包含ブロックがテキストの要素(.text)よりも縦に長い場合は問題ありませんが、必要に応じてmin-heightを指定するなどすると良さそうです。