【CSS3】Firefoxでwriting-modeが使えなくて困ったのでどうにかした話
- 2014/09/08
- atsuko.a

こんにちはフロントエンドエンジニアのあつこです(ΦωΦ)
前回の記事の流れ的にAPIの話をするのかと思いきや、早速しません。
先日Firefoxでドはまりしたのでその時の対処方を備忘録的に。
(APIの話の続きは次に書きます、多分・・・)
ちなみに8月中に滑りこみでスイカを食べました。唯一の夏体験…
事の発端
私は主に自社サービス開発のチームにおりまして、先日もサービスの管理画面のコーディングをしておりました。
で、表組の表示切り替えにタブっぽい表現を使うことになりました。
ソースはこんな感じ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<ul class="tablink1"> <li class="current">tab1</li> <li><a href="#">tab2</a></li> <li><a href="#">tab3</a></li> <li><a href="#">tab4</a></li> <li><a href="#">tab5</a></li> <li><a href="#">tab6 sample text</a></li> </ul> <ul class="tablink2"> <li><a href="#">tab1</a></li> <li><a href="#">tab2</a></li> <li class="current">tab3</li> <li><a href="#">tab4</a></li> <li><a href="#">tab5</a></li> <li><a href="#">tab6 sample text</a></li> </ul> |
縦タブと横タブの判別はクラス名のclass="tablink1"/class="tablink2"でしています。
CSSはこちら
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
/* tab */ /* 共通 */ .tablink1, .tablink2 { margin: 20px 0; } .tablink1 li, .tablink2 li { float: left; line-height: 30px; } .tablink1 li > *, .tablink2 li > * { display: block; font-size: 13px; } .tablink1 li a, .tablink2 li a { background: #141C26; color: #fff; } .tablink1 li a:hover, .tablink2 li a:hover { background: #858585; text-decoration: none; } .tablink1 li.current > *, .tablink2 li.current > * { background: #06BA8F; } /* 横タブ */ .tablink1 { border-bottom: 1px solid #ccc; } .tablink1 li { margin-right: 2px; } .tablink1 li > * { height: 30px; padding: 0 12px; border-radius: 2px 2px 0 0; } .tablink1 li.current { border-radius: 2px 2px 0 0; } /* 縦タブ */ .tablink2 { width: 30px; border-left: 1px solid #ccc; } .tablink2 li { margin-bottom: 2px; /* 縦書き */ writing-mode: tb-rl; -webkit-writing-mode: vertical-rl; -moz-writing-mode: vertical-rl; -ms-writing-mode: vertical-rl; -o-writing-mode: vertical-rl; writing-mode: vertical-rl; } .tablink2 li > * { width: 30px; padding: 12px 0; border-radius: 0 2px 2px 0; } .tablink2 li.current { border-radius: 0 2px 2px 0; } |
tablink2の縦書はCSS3のwriting-modeで実装しています。
ちなみに日本語が入るとこんな感じ。
英字→横書きが縦になる、日本語→フォント自体が立つ、という表示になっていますがこれもその他のプロパティで変えることが出来るようです。
そしてこれをFirefoxで開くと
ファッ!?
横並びはよしとして、縦書が何だか面白いことになっています。
どうやらwriting-modeが有効になっていないようです。
writing-modeとは
そもそもwriting-modeとはIEの独自プロパティで5.5から実装されていたようです。
値はlr-tb/lr-bt/rl-tb/rl-bt/tb-lr...など実は結構あるのですがあくまでもIEの独自実装です。
それとは別にWC3が出している「CSS Writing Modes Level 3」というものがありまして、多文化の筆記様式をサポートするためにCSSの機能を定義しています。
筆記様式というのは例えば英語と日本語とアラビア語、等言葉を表記した際の向きや読み順の方法を指しています。
2014/3/20時点で勧告候補となっていて、Webkit系のブラウザにベンダープレフィクス付きで先行実装されているようです(・ω・)
その中の1つにwriting-modeプロパティがありまして、指定出来る値はIEのwriting-modeと異なります。
horizontal-tb | 上から下へ読む横書き デフォルト |
---|---|
vertical-rl | 右から左へ読む縦書き |
vertical-lr | 左から右へ読む縦書き |
上でも書いたようにWebkitの先行実装+IEの独自実装だったためFirefoxでは再現できなかったという訳ですね。
Firefoxでどうにか縦書にしたい
さて、CSSのみで縦書実装が出来ないことが判明したわけでどうにかしないといけません。
- 縦書を諦める(横並びのタブだけで何とかする)
- JS(jQuery)のプラグインでどうにかする
- CSSの回転で無理やり何とかする
選択肢は↑の3択になりました。
画面の構成上1(諦める)は出来なかったので、大人しくプラグインを探し始めたのですが中々しっくり来るものが無く結局CSSの回転とJSを使ってごにょごにょすることにしました。
また、その他要素との兼ね合いでulごとごそっと回す方法が出来ないので、子要素をグリグリ回したいと思います。
考えた手順はこう
- Firefoxだけ横並びにする
- それぞれのタブの縦横の大きさを取得する
- タブの中身(a/span)を90度回転させる
- タブの外側(li)を元のタブの大きさにする
- ↑を全てのタブにやったら縦に並べる
1.CSS側の準備
まず、縦タブの見た目をFirefoxだけ横に戻します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
@-moz-document url-prefix() { // Firefoxハック .tablink2 { width: auto; } .tablink2 li > * { width: auto; height: 30px; padding: 0 12px; border-radius: 2px 2px 0 0; transform-origin: 0 0; /* 回転の基準 */ margin-left: 30px; /* 謎のmargin30px */ } .tablink2 li.current { width: auto; } } |
Firefox用のCSSハックなんて初めて使いました。(いつもIEばっかりだから…)
するとこうなります
角丸等含め、liの中身が横に並んでおります。
謎のmargin30pxは後で解説します。
2.jQueryでごにょごにょする
これは簡単
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// firefox tab vertical var userAgent = window.navigator.userAgent.toLowerCase(); var appVersion = window.navigator.appVersion.toLowerCase(); if (userAgent.indexOf('firefox') != -1) { // ユーザーエージェント判別でFirefoxの時だけ処理する var tabs = $('.tablink2').find('li').children(); // タブ(li)の中身(a/span)を取得する for(var i = 0; i<tabs.length; i++){ var tab = $(tabs[i]); var tabWid = tab.outerWidth() + 1; // 横幅の取得 var tabHei = tab.outerHeight(); // 縦幅の取得 tab.css({ 'transform': 'rotate(90deg)' // タブの中身を90度回転させる }).outerWidth(tabWid); // タブの中身の横幅を指定する tab.parent('li').width(tabHei).height(tabWid); // タブの外側の大きさを整える } $('.tablink2').width(30); // 親要素(ul)の横幅を整える } |
何故大きさを取得してから回転させているかというと、CSSのプロパティtransformは親要素に干渉しないので子要素が回転したとしても回転する前の大きさを保持するんですね。
transformの結果子要素がはみ出そうが小さくなろうが親要素は全く反応しません、すごい。
なので、わざわざ子要素の大きさをお知らせしてあげるために、一旦大きさを取得しています(`・ω・´)シャキーン
ちなみに、CSSの方で指定している謎のmargin30pxもtransformの調節のために使っています。
図解してみました。
そうしてできたのがこちら
Firefoxで開いてみます…ドキドキ
わーい!タブが縦になってるよー!!!ワーイヽ(゚∀゚)メ(゚∀゚)メ(゚∀゚)ノワーイ
ちなみに日本語を入れるとこうなる。
ポイントとしてはこちら
- CSSとJSの併用なので処理が重すぎない
- FirefoxのみCSSとイベントが発火するので、その他ブラウザはもっと早い
- 横書きの要素を回転させているので、Firefoxでは文字が立たない(WEBフォントでどうにかなるかも…)
文字が立たないのはどうしようもなかったのですが、WEBフォントを入れるほどの優先度ではなかったのでそのままにしました。
タブの量が多くなると処理的にulごと回した方がよくなるかな、と思います。
あと、Operaは見てない。
おまけ:CSS Writing Modes Level 3について
前述の通りこれは様々な文化圏の筆記様式をサポートするためのCSSの機能群ですが、これにはwriting-modeの他にも以下のものが勧告候補として含まれています。
direction | 文字の表記方向を指定する。右→左/左→右 |
---|---|
unicode-bidi | ユニコードの表記方向を上書きする 上書きの方向はdirectionで指定する |
caption-side | 表に対して付けるキャプションの位置を指定する (値の一部が勧告対象) |
text-combine-upright | 縦中横(縦書の文中にある横書き文字)の指定 |
CSS Writing Modes Level 3が正式に勧告されると、多文化圏への適応以外にも、今回のようなレイアウトもCSSのみで実装できるようになりそうですね٩(๑❛ᴗ❛๑)۶
それでは今日はこのへんで!