幅を節約したリスト表示

「Theme Rep」の「登録テーマ一覧」のパネルは、変更先のテーマを指定するインターフェイスですが、このパネルの幅が広過ぎると「記事リスト」に被るので幅を節約する必要がありました。

 

 

問題は、狭くなった幅で隠れるテーマの表示の仕方でした。 最初は JavaScriptでリストの文字列の長さを取得して、上限幅を越えた分のマイナスの「text-indent」を指定するコードを試作。 しかし、これは上手く動作せず、CSSの「direction: rtl」に目を着けました。

 

英語は左から右に文字を並べますが、「direction: rtl」は右から左へ並べる事を指定するものです。 この指定を使うと、文字を「よこはま」➔「まはこよ」という表示にでき、右から書き始める言語に対応できるわけです。

 

この「逆方向に並べる」機能を使えば、「overflow: hidden」で右端が隠れた枠の表示を、「右詰め」で左端が隠れた表示に変える事が出来ると考えたわけです。 この様な「右端を隠す」➔「左端を隠す」というデザインは、外側の枠幅と内側の表示要素の幅が固定の場合は簡単ですが、表示要素の幅が不定の場合は案外と難しいのです。

 

 

サンプルと「unicode-bidi」について 

実際の表示を見ると判り易いです。 下の6行のリストにポインターを乗せると、右に隠れた部分があれば、それが表示されます。

 

   登録テーマ一覧

  • テーマ1 ●▢▢▢▢▢(172)
  • テーマ2 ●▢▢▢▢▢▢▢▢▢▢▢▢▢▢▢▢(234)
  • ●テーマ3 ▢▢▢▢▢(172)
  • ●テーマ4 ▢▢▢▢▢▢▢▢▢▢▢▢▢▢▢▢(234)
  • ●テーマ5 ▢▢▢▢▢(172)
  • ●テーマ6 ▢▢▢▢▢▢▢▢▢▢▢▢▢▢▢▢(234)

 

◎「テーマ1」「テーマ2」は目的通りの結果です。「テーマ1」は溢れていないので変化せず、「テーマ2」は隠れていた部分が表示されます。行中に「●」がありますが、これは後で説明します。

 

「テーマ1」~「テーマ4」の HTML

<ul id="themes_ul">
    <li class="themes_li">テーマ1 ●▢▢▢▢▢(172)</li>
    <li class="themes_li">テーマ2 ●▢▢▢▢▢▢▢▢▢▢▢▢▢▢▢▢(234)</li>
    <li class="themes_li">●テーマ3 ▢▢▢▢▢(172)</li>
    <li class="themes_li">●テーマ4 ▢▢▢▢▢▢▢▢▢▢▢▢▢▢▢▢(234)</li>
</ul>

 

「テーマ1」~「テーマ4」の CSS

.themes_li {
    max-width: 360px;
    overflow: hidden;
    white-space: nowrap; }

.themes_li:hover {
    direction: rtl; }

 

CSSの上側の項は、「幅360px」以上の文字列の右端を隠す指定です。 下側の項は、ホバー時に行を「右から左の表記」に置換える指定です。 

 

◎「テーマ3」「テーマ4」は、「1、2」との違いは「●」が行頭に書かれている点だけで、CSSは同条件です。 ところが「3、4」は、妙な事が生じます。「●」が行末に送られた上で、幅が溢れている「4」は右詰めになり左側が溢れます。

 

「1、2」の「●」は移動しないのに、「3、4」は移動します。 この移動は、どうも行頭に「記号文字」や「句読点」がある場合に、これを文字列とは別種のものと判断して、順序を入れ替える様です。 これが「direction: rtl」の仕様と受け取るしかありません。

 

不要な置換えを抑止する 

「3、4」の様な「記号文字」がテーマに使われる事は、実際にあり得ます。 この妙な置換えを抑止しないと「direction: rtl」が使えません。

 

そこで、テーマの文字列を「span要素」等で囲み、その内部には「direction: rtl」が及ばない様にします。

 

「テーマ5」「テーマ6」の HTML

<ul id="themes_ul">
    <li class="themes_li"><span class="uni">●テーマ5 ▢▢▢▢▢(172)</span></li>
    <li class="themes_li"><span class="uni">●テーマ6 ▢▢▢▢▢▢▢▢▢▢▢▢▢▢▢▢(234)</span></li>
</ul>

 

テストしてみると、「span要素」で囲んだだけでは「3、4」と状況は同じです。つまり「direction: rtl」は継承されるという事です。

 

そこで、「span要素」に「uni」の class名を付けて、以下の指定をしました。

 

「テーマ5」「テーマ6」のために追加した CSS

.uni {
    unicode-bidi: plaintext; }

 

この厄除けが効いて、「テーマ5」「テーマ6」は「記号文字」の移動が無くなり、完全に目的を達しました。

 

「unicode-bidi」の指定可能な値には、継承を抑止できそうな「initial」「isolate」「unset」などの値がありますが、「plaintext」以外の値は全て無効でした。 こういう場合の抑止は「plaintext」しか無い様です。

 

 

まとめ 

「direction: rtl」の指定は「embedid」「override」が必要と、多くの場所で書かれています。

インラインレベル要素で direction プロパティに効果を持たせたいときは、unicode-bidi プロパティの値が embed もしくは override である必要があります。

これは、最初に書いた様に「よこはま」➔「まはこよ」の置換えを目的とする場合です。 このページの目的は本筋とは異なる利用で、この指定をしていないわけです。

 

「direction」を指定した結果は想定出来ない事が多く、実験しながら実装することになります。 上の例で、溢れない行が「右詰め」になりません。 全ての行は、親要素や先祖要素から「text-align: left」を継承していて、それに対して「direction: rtl」は無関係という事です。

 

良く調べると、「direction」は、行頭や行末の「記号文字」のみの配置を変えるのでは無い様です。 以下の全ての行は「plaintext」の抑止をせずに「direction: rtl」の指定をしただけの状態です。

 

  • 特殊な置き換えが生じます。
  • 、特殊な置き換えが生じます,
  • ▢■■■4bite(漢字)の記号文字,,, )(
  • + 123456-
  • + 123456-漢字
  • + 123456-漢字+(
  • + 123456-漢字+(789)

 

最後の4行は、記号文字・半角英数・漢字 などを追加して、倒置の規則を調べていますが、最後の行は以下の文字・文字列として区分けされて、全てが倒置されている事がわかります。

 

▪半角スペースも1区分になりうる

▪記号文字を含まない文字の連続は1区分として扱われる

 

このルールで 4、5、6 行の区分が説明できます。

「+」「 」「123456」「-」「漢字」「+」「(」

 

しかし、最後の 7行目の区分は以下の様に変化し、それだけで説明できません。

「+」「 」「123456」「-」「漢字+(789)」

 

この区分は複雑なルールに従っている様で、何処かに策定された仕様書があると思われます。「direction」を完全に使いこなすには、この区分の仕様を理解する必要がある様です。 なお、上の全ての行は、やはり「plaintext」で倒置を抑止できました。

 

以下に「direction」の機能を纏めたMDNの説明があります。 興味がある方は参照ください。