質問を後付けではなく先見の明の1つに変更したので。
それほど論理的ではありません
あなたは、「論理的に要素に追加dir='rtl'
またはdir='ltr'
属性を付ける<body>
と、それが魔法を実行することを期待します」と述べています。どうやら魔法は、「とのようなルールですべてとすべてで」変換right
するleft
ことleft
です。right
text-direction
margin
しかし、すべての場合において、あなたが望むものが必ずしも論理的な結果であることに同意しません。必ずしもメインサイトのに関連していないインスタンスtext-direction
と使用法があります。の場合、これは自明のように思われます。テキストとはまったく関係のない要素の何らかの形の配置に何度も使用される可能性があるためです。それが自動的に反転することはあまり明白ではないかもしれませんが、それでも有効です。アラビア語(RTL)のブロック引用符が含まれる英語(LTR)サイトがあるとします。これで、主要言語をヘブライ語(RTL)に変換しますが、アラビア語の引用符が残っています。これは、正しくないため、自動的にLTRに切り替わらないようにする必要があります。margin
text-direction
margin
margin
text-direction
フロート要素、絶対位置要素など(right
およびleft
値を使用)のようなものは、のためにそのまま配置される場合とされない場合がありますtext-direction
。
つまり、基本的には、多言語対応のサイトを設計するtext-direction
際に、LTRまたはRTLの構成に基づいて要素が何をすべきかを各段階で検討する必要があるという事実に要約されます。
これが意味することは、私の意見では、CSSには弱点がないということです。弱点は設計の実装にあります。
デザインにおける純粋な人間の予見
したがって、適切な方法は、標準の方向(LTRなど)を選択し、それをストレートCSSを使用した「基本」計画にすることです。
次に、RTLの変更のために反転する要素について、<body>
ターゲットにクラスを適用するか、のような属性セレクターを使用して、それを説明する追加のCSSをコーディングしますbody[dir=rtl]
。次に、各要素を検討して、その変更の影響を受けるかどうかを検討します。影響を受ける場合は、cssを追加します(方向セレクターを追加して、オーバーライドする特異性を追加します)。
.someClass {
color: red;
margin: 0 10px 0 20px;
float: right;
}
body[dir=rtl] .someClass {
margin: 0 20px 0 10px;
/* kept float as right */
}
.someOtherClass {
border: 1px 10px 1px 1px;
margin: 0 30px 0 50px;
float: left;
}
body[dir=rtl] .someOtherClass {
border: 1px 1px 1px 10px; /* changed border for text */
margin: 0 50px 0 30px;
float: right;
}
これは、 LESSやSASS(SCSS) (Daveが彼の回答でLESSに言及)のようなプリプロセッサが役立つことが証明できる場所です(以下の私の更新を参照)が、それでも事前の検討が必要なソリューションです。
余分なCSSでいっぱいのコードを望まない場合
サイトがその特定の方向であると判断されたときにロードされるRTLcss用に別のスタイルシートを持つことができます。これの考えられる欠点は、「切り替え」コードを元のコードから分離するため、メンテナンスがより困難になる可能性があることです(メインコードのRTL変換の影響を受ける要素に関する優れたコメントドキュメントでこれを補うことができます)。
(更新)LESSを使用して支援しますか?
これは、LESSのようなプリプロセッサを使用してプロセスをより簡潔にすることについての考えです。この例では、LESS 1.4(現在ベータ版)の機能を使用しています。
アイデア1
- 利点:すべての値を1つのセレクター変更に変更したままにします。
- 短所:引数に値をコーディングするための作業が増えます。
ミックスインを作成して、目的のセレクターをに適用します
.rtl(...) {
//getting the number of arguments
//(weeding out nested commas in parenthesis to do it)
//they are expected to be grouped in pairs of TWO,
//as (property, value, property, value, etc.)
@mainArgs: @arguments;
@numArgs: unit(`"@{mainArgs}".replace(/\([^)]*\)/g,"").split(',').length`);
//keep everything in one selector
body[dir=rtl] & {
//start the loop at 1
.rtlPropLoop(@numArgs);
}
//loop to change all properties
.rtlPropLoop(@total; @index: 1; @prop: extract(@mainArgs, @index); @value: extract(@mainArgs, (@index + 1))) when (@index =< @total) {
//need to define all properties that could be switched
//I've done just four here
.setProp(ML) { //margin left
margin-left: @value;
}
.setProp(MR) { //margin right
margin-right: @value;
}
.setProp(FL) { //float
float: @value;
}
.setProp(TD) { //text direction
text-direction: @value;
}
//... define more possible values to switch
//call setProp
.setProp(@prop);
//continue loop
.rtlPropLoop(@total, (@index + 2));
}
//end loop
.rtlPropLoop(@total, @index) when (@index > @total) {}
}
次に、必要に応じて他のセレクターで使用します
.test {
margin: 0 20px 0 10px;
float: right;
.rtl(ML, 20px, MR, 10px, FL, left);
}
.test2 a span {
float: left;
text-direction: rtl;
.rtl(TD, ltr, FL, right);
}
この完成したコードの作成
.test {
margin: 0 20px 0 10px;
float: right;
}
body[dir=rtl] .test {
margin-left: 20px;
margin-right: 10px;
float: left;
}
.test2 a span {
float: left;
text-direction: rtl;
}
body[dir=rtl] .test2 a span {
text-direction: ltr;
float: right;
}
アイデア2
- 利点:必要な構文と同様の構文を使用できます。LESS1.3.3で動作するように簡単に変更できます。
- 短所:1つのセレクターで複数の値が変更されると、過剰な出力cssが生成されます。
CSSで期待するような構文でヘルパーミックスインを構築する
//define global variable for opposite direction
@oppDir: rtl;
//generic helper mixins used inside other helpers
//to auto flip right/left values
.flipSides(left) {
@newSide: right;
}
.flipSides(right) {
@newSide: left;
}
//specific property helper mixins
.padding-near(@top, @right, @bottom, @left) {
padding: @top @right @bottom @left;
body[dir=@{oppDir}] & {
padding: @top @left @bottom @right;
}
}
.margin-near(@top, @right, @bottom, @left) {
margin: @top @right @bottom @left;
body[dir=@{oppDir}] & {
margin: @top @left @bottom @right;
}
}
.float-near(@side) {
float: @side;
.flipSides(@side);
body[dir=@{oppDir}] & {
float: @newSide;
}
}
それらを使用して、各方向の近距離と遠距離の両方を一度に定義します
.test1 {
.padding-near(10px, 30px, 2px, 40px);
.margin-near(0, 10px, 0, 20px);
.float-near(right);
}
.test2 {
.float-near(left);
}
この完成したコードの作成(.test1
反対方向の繰り返しに注意してください)
.test1 {
padding: 10px 30px 2px 40px;
margin: 0 10px 0 20px;
float: right;
}
body[dir=rtl] .test1 {
padding: 10px 40px 2px 30px;
}
body[dir=rtl] .test1 {
margin: 0 20px 0 10px;
}
body[dir=rtl] .test1 {
float: left;
}
.test2 {
float: left;
}
body[dir=rtl] .test2 {
float: right;
}