编写更好的 CSS 代码 (Part Ⅲ)

在早期的 Web 开发中,页面的布局和定位通常要用表格和各种 hack 技术来实现。与那时相比,CSS 已经得到了长足的发展。如今,开发人员可以很轻松地编写出适用于所有主流浏览器的 CSS 代码,在实现复杂布局时也不会像以前那样绞尽脑汁。这不仅使响应式布局变得更容易,还可以通过删除冗余的代码来发布体积更小的样式。在本文中,我们将使用现代技术来降低代码的复杂程度,通过一些较新的技术来编写出更好的 CSS 代码。

使用逻辑属性支持 RTL

如果你的应用只支持单一的语言(比如 en-US),而且没有做国际化相关工作,那么在编写 CSS 时,你可能并不需要关注文字 LTR(left-to-right,左对齐)和 RTL(right-to-left,右对齐)的差异。我们可以很放心地去使用 margin-leftpadding-right、以及绝对定位等属性。

但如果你的应用是国际化的,要支持多个地区的语言,那情况就完全不同了。在阿拉伯语、希伯来语等这些 RTL 的语言环境中,文本是从右向左读的,而不是从左向右读的。根据已有经验,页面上的大多数视觉元素要进行左右颠倒,并沿着与文本相同的方向进行布局(尽管很少有例外)。

实现 RTL 的传统方法:首先要从 LTR 的角度去编写 CSS,然后使用 dir 属性确定 RTL 样式的范围。这里通常使用物理维度的属性和值,这些属性和值的基本方向是固定的(top、right、 bottom 和 left)。下面是一个示例:

.element {
  /* LTR CSS */
  margin-left: 8px;
}

 

html[dir="rtl"] .element {
  /* RTL CSS */
  margin-left: unset;
  margin-right: 8px;
}

在 LTR 模式下,我们的元素会有一个左外边距。在 RTL 模式下,元素需要的是一个右外边距。所以,我们取消左外边距,与此同时将右边距设置了相同的值。在页面中根据语言情况来决定哪种样式生效(RTL 版本具有更高的优先级)。但你会发现,当你处理越来越多的样式时,这个过程也变得越来越枯燥。为了实现国际化,我们额外开发了大量的重复代码。

下面列举了一些我们经常使用的物理属性:

  • margin-[top|right|bottom|left]
  • padding-[top|right|bottom|left]
  • border-[top|right|bottom|left]

让我们感到欣慰的是,CSS 已经开始支持逻辑属性了。与物理属性相比,逻辑属性更易于适应不同的书写模式。在逻辑属性中没有物理维度的概念,只用 start 和 end 等来描述文本方向。因此,可以使用更少的代码来实现上面的功能:

.element {
  margin-inline-start: 8px;
}

逻辑属性,通常由三部分组成,属性名称(margin)、流动方向 (block 或 inline)、起止方向 (start 或 end),以及相关的子属性(例如 colorwidth 等)。所以与 border-left-color 对应的 逻辑属性是 border-inline-start-color。在 LTR 模式下,start 等价于 left,在 RTL 模式下,等价于 right。在这两种模式下,UI 样式与期望的效果是一致的,但只需要编写一个样式规则即可适应这两个模式。

在最近所有的 CSS 新特性中,逻辑属性可以算做是我最喜欢的一个。即使你的应用程序暂不支持 RTL,你仍然可以使用逻辑属性,因为它们可以无缝地用于 LTR。带来额外的好处是,如果未来有需要的话,可以快速实现应用程序的国际化。使用逻辑属性没有任何坏处,所需要的只是转变开发视角。可以阅读「是时候了解 CSS 逻辑属性了」,进一步了解逻辑属性。

当你需要重构的代码越多,逻辑属性带来的收益越大。就在去年,我使用逻辑属性对一个已有项目重构(因为我们的应用程序支持 RTL),结果我删除了近 700 行不必要的 CSS。

逻辑属性示例

我们可以使用很多的逻辑属性和相关的属性值。在下面的章节中,列出了一些最常见并广泛使用的 CSS 逻辑属性,以及它们与物理属性的对应关系。值得注意的是,并不是所有的物理属性都有与之对应的逻辑属性。两个示例包括变换平移和长方体阴影偏移。

边距

我们可以把 margins、 padding、borders 替换成对应的逻辑属性,这样就会自动完成对 RTL 和 垂直书写模式的支持。下面的表格中列出了对应的关系:

物理属性 逻辑属性
[margin|padding|border]-left [margin|padding|border]-inline-start
[margin|padding|border]-right [margin|padding|border]-inline-end
[margin|padding|border]-top [margin|padding|border]-block-start
[margin|padding|border]-bottom [margin|padding|border]-block-end
border-bottom-width border-block-end-width
border-left-color border-inline-start-color

如果从单个边框属性来看,逻辑属性的命名确实比较冗长。但与维护两套样式(一套用于 LTR,另一套用于 RTL)相比,它肯定就不那么冗长。

定位

包含 absolute、relative 和 fixed 在内的定位也可以通过逻辑属性来完成:

物理属性 逻辑属性
top inset-block-start
bottom inset-block-end
left inset-inline-start
right inset-inline-end

宽高

如果需要支持垂直书写模式,则有以下逻辑属性:

物理属性 逻辑属性
width inline-size
height block-size

因为宽度是对称(没有方向性),对 RTL 样式没有任何影响。在使用它们时,我们不需要做额外的工作。

逻辑属性值

除了一些属性之外,还有一些属性值也是具有逻辑性的:

物理规则 逻辑规则
text-align: right; text-align: end;
justify-content: left; justify-content: start;
float: left; float: inline-start;
float: right; float: inline-end;

浏览器支持情况

编写更好的 CSS 代码 (Part Ⅲ)插图

本文主要介绍使用 CSS 逻辑属性的支持不同语言的书写模式,这样可以使 CSS 的代码更加整洁。本文是整个系列的第三篇文章,点击下面的链接可以阅读前两篇文章:

发表评论

后才能评论