19

考虑这种情况:您正在开发一个多语言 Web 应用程序。如果您定位的所有语言都是LTRRTL,则您不需要特定语言的 CSS 规则。但是,如果您的目标语言是混合LTR语言RTL,则需要为每种语言指定页面的阅读方向。

如果您向元素添加dir='ltr'或,则从逻辑上讲,您应该期望它应该执行必要的魔术。dir='rtl'<body>

但是,您实际上需要在 和 等规则中切换所有和right设置。您还需要更改规则,例如lefttext-directionmarginmargin: 0 10px 0 20px;margin: 0 20px 0 10px;

W3C 标准可以通过为与方向相关的规则允许另外两个值来避免这个问题。换句话说,代替-rightand -left(如margin-rightand margin-left),它们可以允许如下内容:

div.foo { margin-near: 100px; } 
/* This would be equivalent to margin-left in LTR, and margin-right in RTL */

div.bar { margin-far: 100px; } 
/* This would be equivalent to margin-right in LTR, and margin-left in RTL */

本质上,在您当前可以输入leftright基于方向的单词的所有规则/值中,您可以改为编写nearor far

鉴于当前 CSS 版本的弱点,我正在寻找一些建议来简化创建维护双向大型 Web 应用程序。

4

7 回答 7

7

由于您将问题更改为预先考虑而不是事后考虑。

不太合乎逻辑

您说,“如果您从逻辑上添加dir='rtl'dir='ltr'归因于<body>元素,您希望它会发挥作用。” 魔术显然是转换,“所有都right在规则中,就像and 。”leftleftrighttext-directionmargin

但是,我不同意在所有情况下,您想要的必然是合乎逻辑的结果。有些实例text-directionmargin使用不一定与text-direction主站点相关。因为margin,这似乎是不言而喻的,因为很多时候margin可能用于某种形式的与文本完全无关的元素的定位。这text-direction不会自动翻转可能不太明显,但仍然有效。假设一个有一个英语 (LTR) 站点,其中包含阿拉伯语 (RTL) 的块引用。现在将主要语言转换为希伯来语(RTL),但仍然有阿拉伯语的引用——不应自动转换为 LTR,因为它是不正确的。

由于. _ right_lefttext-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;
}

这就是像LESSSASS (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;
}
于 2013-04-24T12:55:23.227 回答
6

不幸的是,CSS 在左右的概念上运行,这是正确的行为。有一些工具可以帮助您将 CSS 从 LTR 迁移到 RTL - 我知道的一个工具是CSS Janus,它可以翻转 -left/-right 属性等等。

于 2012-10-13T18:38:32.213 回答
4

我想如果你想要这个,你必须使用像lesscss这样的东西。

有一个标准可以解决这个问题,但我不知道有任何浏览器支持它。即使他们这样做了,它也可能会受到旧版浏览器支持的阻碍(但什么时候这不是问题?)。

除了所有的技术挑战,一旦完成,我想要很好地实现它,你仍然必须确保将每个对左/右的引用外部化,然后使用类似于媒体查询在响应式设计中的使用方式移动浏览器。

于 2012-10-13T18:42:18.807 回答
3

我使用 Closure 样式表,这些东西就像命令行标志一样简单。

我将所有内容定义为 LTR(direction:ltr在必要时使用),然后--output-orientation=RTL在编译期间使用,我得到了为我生成的翻转 CSS。最后,在确定区域设置(在服务器上)时,我还确定要注入模板的 CSS。

Closure 中 LR 翻转的更多信息位于https://code.google.com/p/closure-stylesheets/#RTL_Flipping

于 2013-04-28T16:11:09.783 回答
0

有关尝试使用 SASS/LESS 克服弱点的一种解决方案的更多背景信息,请查看http://anasnakawa.github.io/bi-app-sass/

于 2013-08-21T15:37:01.340 回答
0

在问了这个问题三年后,我知道我看到了使用逻辑方向词汇而不是四向词的趋势。

CSS 逻辑属性现在解决了这个问题。Flex 模型使用start/end关键字 Blink 现在支持start/end/before/after关键字。诶

ul, menu, dir {
    -webkit-margin-before: 1em;
    -webkit-margin-after: 1em;
    -webkit-margin-start: 0px;
    -webkit-margin-end: 0px;
    -webkit-padding-start: 40px;
}
于 2016-06-02T06:58:21.237 回答
0

在发布这个问题大约四年后,这个需求最终将由 w3 解决。https://drafts.c​​sswg.org/css-logical/

接受物理方向关键字值(顶部、底部、左侧或右侧)的属性被重新定义为也接受适当的流相关方向关键字。在这种情况下,可以使用流量相关值代替相应的物理值。对于采用多个关键字的属性,不允许组合流量相关值和物理值(除非在未来的规范中另有规定)。

于 2017-10-07T10:28:44.057 回答