推动 Web 发展意味着使其对开发者和用户都更加友好。这意味着要解决当前 Web 所面临的问题;对于让响应式 RTL 设计和开发更容易实现,这一点尤其重要。
在继续讨论前沿 RTL 主题之前,这里有一个包含实际示例的视频教程,可以帮助你回顾一下如何正确地编写当今的 RTL 代码
承接上一篇文章,现在我们来深入探讨一下关于从右到左 UI 实现的一些高级主题。在第一部分中,我们介绍了 RTL 的基础知识。在第二部分中,我们将介绍关于双向 (BIDI) 用户界面的前沿技巧。这是 Web 的 Alpha 状态,我们可以看看 RTL 的未来会有什么发展。
前沿的 RTL
Web 上的 RTL UI 设计和开发的核心是 CSS 属性,就像 Web 开发的各个方面一样,这些属性一直在不断改进。
以下是可以从今天开始在多个现代浏览器的 Alpha 版本中开始使用的 CSS 属性。(随着浏览器更新的发布,此信息可能会发生变化。)
文本对齐:过去,我们曾经使用 text-align left
或 right
来显式设置文本的水平对齐方式(例如 text-align: left
)。现在,我们可以使用 start
和 end
值来代替它们。例如,text-align: start
将根据内容设置为 RTL 或 LTR 而产生不同的结果。start
在 LTR 中表示左侧,在 RTL 中表示右侧,而 end
则相反。
使用 left/right 的示例
#content {
text-align: left:
}
html[dir="rtl"] #content {
text-align: right;
}
使用 start/end 的示例
#content {
text-align: start;
}
使用 start/end 时,不需要使用 RTL 规则。
浏览器支持:Chrome 1.0+、Safari 3.1+、Firefox 3.6+、Android、iOS。目前 Internet Explorer 不支持。
填充、边距和边框:这些属性有一些改进。
它们中的每一个现在都可以添加 -inline-start
或 -inline-end
后缀,例如,你可以写 padding-inline-end
或 margin-inline-start
。这些新的关键字与文本对齐中的 start 和 end 具有相同的结果:padding-inline-start
在 LTR 中等效于 padding-left
,在 RTL 中等效于 padding-right
。margin-inline-end
在 LTR 中等效于 margin-right
,在 RTL 中等效于 margin-left
。
使用 left/right 的示例
#content {
padding-left: 12px:
margin-right: 20px;
}
html[dir="rtl"] #content {
padding-left: 0;
padding-right: 12px;
margin-left: 20px;
margin-right: 0px;
}
使用 start/end 的示例
#content {
padding-inline-start: 12px:
margin-inline-end: 20px;
}
同样,不需要使用 RTL 规则;例如,margin-inline-end
在 LTR 中将充当 margin-right
,在 RTL 中将充当 margin-left
。
浏览器支持:仅限 Firefox 41+
绝对定位:left
和 right
是始终是绝对定位的关键 CSS 属性,但很快你将使用新的 offset-inline-start
和 offset-inline-end
属性为用户编写更加智能的 CSS 代码。
值得一提的是,top 和 bottom 可以用 offset-block-start
和 offset-block-end
代替。
使用 left/right 的示例
#content {
position: absolute;
left: 5rem;
}
html[dir="rtl"] #content {
left: auto;
right: 5rem;
}
使用 start/end 的示例
#content {
offset-inline-start: 5rem;
}
再一次,start/end 概念为我们省去了 CSS 文件中的规则。
浏览器支持:仅限 Firefox 41+
浮动:float: left
和 float: right
已经存在并被使用很长时间了,但很快你就能在 Firefox Nightly 中使用 float: inline-start
和 float: inline-end
。inline-start
将在从左到右 (LTR) 布局中将元素浮动到左侧,在从右到左 (RTL) 布局中将元素浮动到右侧。
使用 start/end 的示例
#content {
float: left;
}
html[dir="rtl"] #content {
float: right;
}
使用 start/end
#content {
float: inline-start;
}
浏览器支持:Firefox 44(即将登陆 Firefox Nightly)。
Firefox OS 为你提供了尝试一些最新的 CSS 属性实现的机会 - Mozilla Wiki 上有一个关于所有新 BIDI 相关 CSS 属性和值 的参考页面。
Web 组件:Web 组件是可重用的用户界面小部件 (有关更多信息,请参阅 MDN)。如果你使用过 Web 组件,你就会知道在 Shadow DOM 中定义的 CSS 样式是作用域化的,因此默认情况下,你无法从组件的作用域 CSS 中使用 html[dir=”rtl”]
获取页面的方向。但是,Shadow DOM 引入了一个新的选择器,称为 :host-context()
,它可以用来根据匹配的父元素选择 Shadow 宿主元素。
让我们用一个例子来解释一下 - 假设你的 Shadow DOM 树中有一个名为 back 的元素。在没有 Shadow DOM 的正常情况下,你只需使用 html[dir=”rtl”] .back {}
,但你无法在 Web 组件内部使用此语法。作用域化和封装,记住吗?当 .back
在 Web 组件作用域内时,等效的选择器看起来像这样
.back:host-context(html[dir="rtl"]) { }
目前,这种语法的确切浏览器支持状态尚不清楚,但你可以使用 此 polyfill 来弥补支持方面的不足。
想要使用 Shadow CSS 的 polyfill,但仍然想要在支持它的浏览器(如 Firefox(目前隐藏在 dom.webcomponents.enabled
标志后面)和 Google Chrome)中使用 Web 组件中的 RTL 吗?你可以使用 Mutation Observers 来观察 document.documentElement.dir
属性。观察器的代码将类似于以下示例
var dirObserver = new MutationObserver(updateShadowDir);
dirObserver.observe(document.documentElement, {
attributeFilter: ['dir'],
attributes: true
});
此外,不要忘记在页面加载后,在观察器逻辑之后立即第一次初始化你的函数
updateShadowDir();
你的 updateShadowDir()
函数将看起来像这样
function updateShadowDir() {
var internal = myInnerElement.shadowRoot.firstElementChild;
if (document.documentElement.dir === 'rtl') {
internal.setAttribute('dir', 'rtl');
} else {
internal.removeAttribute('dir');
}
};
这是你应该在 JavaScript 方面做的事情 - 现在,由于你的 Web 组件的第一个子元素具有不断变化的 dir 属性,因此你的 CSS 将依赖它作为选择器,而不是 HTML 元素。假设你使用的是一个 span - 你的选择器将看起来像这样
span[dir="rtl"] rest-of-the-selectors-chain { … }
这可能看起来有点 hacky,但幸运的是,未来更加光明,所以让我们看看 W3C 在未来关于从右到左方面会为我们带来什么。
Web 上 RTL 的未来
通知服务器文本方向:目前,在文本输入和文本区域中,当提交表单时,页面/表单元素的方向会丢失。然后,服务器必须自己想办法估计发送给他们的文本的方向。
为了解决这个问题,并提供更多关于发送的文本及其方向的信息,W3C 在 HTML5 表单规范中添加了一个新属性,称为 dirname
,浏览器供应商将在未来实现它。
正如规范中所述,在表单控件元素上包含 dirname
“能够提交元素的方向,并在提交表单时提供包含此值的字段的名称。如果指定了此类属性,其值必须不为空字符串”。
翻译:将此属性添加到你的 <input> 或 <textarea> 中,会使它们的方向与发送到服务器的 GET 或 POST 字符串一起传递。让我们看一个真实世界的例子 - 首先,假设你有以下表单
<form action="result.php" method="post">
<input name="comment" type="text" dirname="comment.dir"/>
<button type=submit>Send!</button>
</form>
提交表单后,发送到服务器的 POST 字符串将包含一个名为 comment 的字段,以及另一个名为 comment.dir
的字段。如果用户在文本区域中输入 Hello 并提交它,则结果字符串将是
comment=Hello&comment.dir=ltr
但如果他们输入 “مرحبا”,它将看起来像这样
comment=%D9%85%D8%B1%D8%AD%D8%A8%D8%A7&comment.dir=rtl
注意:为了使阿拉伯字符在浏览器中以正确的形式显示在 URL 中,这些字符使用 UTF-8 编码,每个阿拉伯字母现在使用 4 个字符,并在中间用 % 符号隔开。
例如,如果你有以下链接:http://ar.wikipedia.org/wiki/نجيب_محفوظ
当你访问它时,浏览器中的链接将转换为
http://ar.wikipedia.org/wiki/%D9%86%D8%AC%D9%8A%D8%A8_%D9%85%D8%AD%D9%81%D9%88%D8%B8
更好地管理 RTL 中的背景和图像:厌倦了使用 transform: scaleX(-1)
来镜像你的背景图像了吗?W3C 正在引入一个名为 rtlflip
的新 CSS 关键字,使用方式如下
background-image: url(backbutton.png) rtlflip;
这个关键字可以让你免去使用 transform: scaleX(-1)
属性手动镜像图像的麻烦。
它还可以用来设置列表项标记的样式,如下所示
list-style-image:url('sprite.png#xywh=10,30,60,20') rtlflip;
规范页面 还指出,这个关键字可以与 CSS3 Images 中指定图像的所有其他可能方式一起使用,例如 url
、sprite
、image-list
、linear-gradient
和 radial-gradient
。
国际化 API
我们在 一篇介绍性文章 中介绍过 JavaScript 国际化 API。让我们回顾一下与处理从右到左内容相关的重要的鲜为人知的部分。
国际化 API 支持多种语言及其派生语言。例如,它不仅支持阿拉伯语,还支持阿拉伯语-埃及、阿拉伯语-突尼斯以及所有其他变体。
使用东阿拉伯数字而不是西阿拉伯数字:在一些阿拉伯语变体中,使用东阿拉伯数字 (١٢٣) 而不是西阿拉伯数字 (123)。国际 API 允许我们指定何时显示 ١٢٣ 和何时显示 123。
console.log(new Intl.NumberFormat('ar-EG').format(1234567890));
这表示我们要将 1234567890 格式化为阿拉伯-埃及数字。
输出:١٬٢٣٤٬٥٦٧٬٨٩٠
console.log(new Intl.NumberFormat('ar-TN').format(1234567890));
这里我们说我们要以阿拉伯-突尼斯格式输出同一个数字;由于突尼斯使用西方阿拉伯语,所以输出结果为:1234567890
以伊斯兰历/回历显示日期,而不是公历: 在斋月期间,谷歌将 google.com/ramadan 改为显示与该节日相关的內容。显示的最重要信息之一是回历中的月日。谷歌使用了一个 polyfill 来获取此信息。使用国际化 API,您可以用一行 JavaScript 代码提取相同的信息,而无需整个 JavaScript 库。
这是一个例子
console.log(new Intl.DateTimeFormat("fr-FR-u-ca-islamicc").format(new Date()));
这行代码表示我们要将当前日期格式化为伊斯兰历日期,并以 fr-FR 数字(西方阿拉伯语)显示。输出:16/12/1436
console.log(new Intl.DateTimeFormat("ar-SA-u-ca-islamicc").format(new Date()));
这与上面相同,但格式化为在使用东阿拉伯数字的阿拉伯-沙特阿拉伯地区显示。
输出:١٦/١٢/١٤٣٦
最后的话
在本文中,我们总结了关于在 Web 上以正确方式进行 RTL 的深入分析。我们希望这将有助于鼓励您开始在您的网站/产品中添加 RTL 支持!如果您是 Firefox OS 贡献者,这将是您向 Gaia 添加 RTL 的指南。
与往常一样,如果您有任何问题,请在下面的评论中告诉我们!
关于 Ahmed Nefzaoui
RTL(从右到左)专家。前端 Web 开发人员。Firefox OS UI 黑客和 Mozilla 技术演讲者。
一条评论