多语言网站大规模CSS的有效开发和维护
考虑这个场景:您正在开发一个多语言web应用程序。如果您所针对的所有语言都是多语言网站大规模CSS的有效开发和维护,css,internationalization,multilingual,right-to-left,Css,Internationalization,Multilingual,Right To Left,考虑这个场景:您正在开发一个多语言web应用程序。如果您所针对的所有语言都是LTR或RTL,则不需要特定于语言的CSS规则。但是,如果目标语言是LTR和RTL语言的混合,则需要为每种语言指定页面的阅读方向 如果将dir='ltr'或dir='rtl'添加到元素中,从逻辑上讲,您应该期望它能够执行必要的操作 但是,您实际上需要在规则中切换所有右和左设置,例如文本方向和边距。您还需要更改规则,如边距:0 10px 0 20px至边距:0 20px 0 10px W3C标准可以通过允许方向相关规则增加
LTR
或RTL
,则不需要特定于语言的CSS规则。但是,如果目标语言是LTR
和RTL
语言的混合,则需要为每种语言指定页面的阅读方向
如果将dir='ltr'
或dir='rtl'
添加到
元素中,从逻辑上讲,您应该期望它能够执行必要的操作
但是,您实际上需要在规则中切换所有右
和左
设置,例如文本方向
和边距
。您还需要更改规则,如边距:0 10px 0 20px代码>至边距:0 20px 0 10px代码>
W3C标准可以通过允许方向相关规则增加两个值来避免这个问题。换句话说,它们可以允许如下内容,而不是-right
和-left
(如margin right
和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 */
本质上,在当前可以输入左
或右
方向词的所有规则/值中,您可以改为在附近或远处编写
鉴于当前CSS版本的弱点,我正在寻找一些建议,以简化双向大型web应用程序的创建和维护。不幸的是,CSS是基于左和右的概念运行的,这是正确的行为。有一些工具可以帮助您将CSS从LTR迁移到RTL,据我所知,这是一个可以翻转-左/右属性的工具,等等。我认为如果您想要这样做,您必须使用类似的工具
有一个解决方案,但我不知道有任何浏览器支持它。即使他们这样做了,它也很可能会受到传统浏览器支持的阻碍(但这什么时候不是问题?)
撇开所有的技术挑战不谈,一旦完成了,我想可以很好地实现它,您仍然必须确保将每个对左/右的引用外部化,然后使用类似于移动浏览器响应设计中使用媒体查询的方式。因为您将问题改为预先考虑而不是事后考虑
不太合乎逻辑
您声明,“如果您将dir='rtl'
或dir='ltr'
属性添加到
元素中,逻辑上您希望它发挥神奇作用。”神奇之处显然是转换,“在文本方向
和边距
等规则中,所有右
带左
和所有左
带右
”
然而,我不同意你所希望的在所有情况下都是合乎逻辑的结果。有一些文本方向和边距的使用不一定与主站点的文本方向相关。对于边距,这似乎是不言而喻的,因为很多时候边距可能是不可否认的e用于对与文本完全无关的元素进行某种形式的定位。文本方向
不会自动翻转可能不太明显,但仍然有效。假设有一个英文(LTR)站点,其中包含阿拉伯语(RTL)的块引号。现在将主语言转换为希伯来语(RTL)但仍然有阿拉伯语的引语——这不应该自动转换为LTR,因为这是不正确的
浮动元素、绝对定位元素等(使用右
和左
值)可能会因为文本方向
而被定位,也可能不会被定位
因此,基本上,它归结为这样一个事实:当一个人设计一个多语言的网站时,它将翻转文本方向
,在每个阶段,他必须考虑基于LTR或RTL配置的元素应该做什么
这意味着,在我看来,CSS没有弱点。任何弱点都存在于设计实现中。
设计中的纯人类先见之明
因此,好的方法是选择你的标准方向(比如LTR),并用直接的CSS将其作为你的“基本”计划
然后,对于由于RTL的更改而要翻转的元素,您可以编写额外的CSS来说明这一点,方法是将一个类应用于目标的
,或者使用属性选择器,如body[dir=RTL]
。然后仔细考虑所做的每个元素是否应该受到该更改的影响,如果是,则添加css(使用附加的方向选择器添加特定性以覆盖):
这就是像or这样的预处理器(Dave在他的回答中较少提及)可能会有帮助的地方(见下面我的更新),但这仍然是一个需要深思熟虑的解决方案
如果您不想让代码充斥着多余的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;
}
}
您可以为RTL css创建一个单独的样式表,该样式表在站点确定为该特定方向时加载。其可能的缺点是,它将“切换”代码与原始代码分开,因此维护可能更具挑战性(关于主代码中受RTL转换影响的元素的良好注释文档可以弥补这一缺陷)
(更新)使用更少的帮助?
下面是一个关于通过LESS这样的预处理器使过程更加简洁的想法。这个例子使用了LESS 1.4(目前处于beta版)中的功能
想法1
- 优点:将所有值更改为一个选择器更改
- 缺点:在参数中编写值需要更多的工作
构建一个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;
}
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;
}
.test1 {
.padding-near(10px, 30px, 2px, 40px);
.margin-near(0, 10px, 0, 20px);
.float-near(right);
}
.test2 {
.float-near(left);
}
想法2
- 进阶
//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 {
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;
}
ul, menu, dir {
-webkit-margin-before: 1em;
-webkit-margin-after: 1em;
-webkit-margin-start: 0px;
-webkit-margin-end: 0px;
-webkit-padding-start: 40px;
}