由于您将问题更改为预先考虑而不是事后考虑。
不太合乎逻辑
您说,“如果您从逻辑上添加dir='rtl'
或dir='ltr'
归因于<body>
元素,您希望它会发挥作用。” 魔术显然是转换,“所有都right
在规则中,就像and 。”left
left
right
text-direction
margin
但是,我不同意在所有情况下,您想要的必然是合乎逻辑的结果。有些实例text-direction
和margin
使用不一定与text-direction
主站点相关。因为margin
,这似乎是不言而喻的,因为很多时候margin
可能用于某种形式的与文本完全无关的元素的定位。这text-direction
不会自动翻转可能不太明显,但仍然有效。假设一个有一个英语 (LTR) 站点,其中包含阿拉伯语 (RTL) 的块引用。现在将主要语言转换为希伯来语(RTL),但仍然有阿拉伯语的引用——不应自动转换为 LTR,因为它是不正确的。
由于. _ right
_left
text-direction
所以基本上,它归结为这样一个事实,当一个人设计一个旨在以一种可以翻转的方式提供多语言的网站时text-direction
,人们必须在每个阶段考虑元素应该基于 LTR 或 RTL 配置做什么。
这意味着,在我看来,CSS 没有弱点。任何弱点都在设计实现中。
设计中的纯人类远见
因此,好的方法是选择您的标准方向(例如 LTR),并将其作为您使用直接 CSS 的“基本”计划。
然后,对于由于 RTL 更改而想要翻转的元素,您可以编写额外的 CSS 来解决这个问题,方法是将类应用于<body>
目标,或者使用属性选择器,如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
您可以为在站点确定为该特定方向时加载的 RTL css 提供单独的样式表。这样做的可能缺点是它将“切换”代码与原始代码分开,因此维护可能更具挑战性(关于受主代码中 RTL 转换影响的元素的良好注释文档可以弥补这一点)。
(更新)使用 LESS 来帮助?
这是通过像 LESS 这样的预处理器使过程更简洁的想法。此示例使用LESS 1.4(当前处于测试阶段)的功能。
理念一
- 优点:将所有值更改为一个选择器更改。
- 缺点:在参数中编码值需要做更多的工作。
构建一个 mixin 以将所需的选择器应用于
.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
- 优点:允许您使用与您想要的相似的语法;可以很容易地修改为与 LESS 1.3.3 一起使用。
- 缺点:如果在一个选择器中更改了多个值,则会产生过多的输出 css。
使用您在 CSS 中所期望的语法构建一些辅助 mixin
//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;
}