CSS 指南

本文档包含关于如何在 Firefox 代码库中编写 CSS 的指南,它尤其与 Firefox 前端工程师相关。

基础知识

以下是一些基本技巧,如果您正在更改 CSS,可以优化代码审查。

  • 避免使用 !important,但如果您必须使用它,请确保很清楚您使用它的原因(理想情况下添加注释)。覆盖 CSS 部分包含更多相关信息。

  • 避免使用魔法数字;优先使用自动大小或对齐方法。一些需要避免的示例:

    • 绝对定位元素

    • 硬编码值,例如:vertical-align: -2px;。您应该避免此类“硬编码”值的原因是,它们并非在所有字体大小配置下都能正常工作。

  • 避免在 JavaScript 中设置样式。通常最好设置一个类,然后在 CSS 中指定样式。

  • classList 通常比 className 更好。这样可以减少覆盖现有类的可能性。

  • 仅当它在语义上是您想要表达的意思时,才使用诸如 :last-child 之类的通用选择器。如果不是,使用语义类名称更具描述性,通常也更好。

样板文件

确保每个文件都以标准版权标头开头(请参阅 许可证样板文件)。

在添加更多 CSS 之前

最好检查正在编写的 CSS 是否确实需要,因为可能已经编写了一个通用的组件,可以重复使用(无需或只需少量修改)。大多数情况下,通用组件已经遵循本指南中定义的 a11y/主题标准。因此,在可能的情况下,始终优先编辑通用组件而不是编写自己的组件。

此外,当您要设置样式的新元素从另一个元素重复使用某些样式时,最好引入一个通用类,这可以降低维护成本并减少代码重复。

格式

空格 & 缩进

  • 首选 2 个空格缩进

  • 在每个逗号后添加一个空格,**除了**颜色函数内。

linear-gradient(to bottom, black 1px, rgba(255,255,255,0.2) 1px)
  • 始终在 !important 之前添加一个空格。

省略 0 值的单位

这样做

margin: 0;

不要这样做

margin: 0px;

使用扩展语法

通常很难理解简写语法的作用,并且简写语法还会隐藏一些不需要的默认值。最好使用扩展语法来明确您的意图。

这样做

border-color: red;

不要这样做

border: red;

将多个选择器放在不同的行上

这样做

h1,
h2,
h3 {
  font-family: sans-serif;
  text-align: center;
}

不要这样做

h1, h2, h3 {
  font-family: sans-serif;
  text-align: center;
}

类名称命名标准

  • lower-case-with-dashes 最为常见。

  • 但有时也会使用 camelCase。请尝试遵循现有或相关代码的风格。

其他提示

  • 在属性选择器中假定 ="true"

    • 示例:使用 option[checked],而不是 option[checked="true"]

  • 除非确实是想要的目标,否则避免使用 ID 选择器,因为 ID 具有更高的特异性,因此更难覆盖。

  • 在可能的情况下,使用后代选择器是一种良好的性能实践

    • 例如:.autocomplete-item[selected] > .autocomplete-item-title.autocomplete-item[selected] .autocomplete-item-title 更有效率

覆盖 CSS

在覆盖任何 CSS 规则之前,请检查是否确实需要覆盖。有时,在复制粘贴旧代码时,可能会发生所讨论的代码包含不必要的覆盖。这可能是因为在此期间被覆盖的 CSS 已被删除。在这种情况下,删除覆盖应该可以解决问题。

最好也看看您要覆盖的规则是否仍然需要:也许组件的用户体验规范已更改,并且该规则实际上可以更新或删除。在这种情况下,不要害怕删除或更新该规则。

检查完上述两点后,检查您要覆盖的其他规则是否包含 !important,如果是,请尝试质疑它,因为它可能已过时。

之后,检查其他选择器的特异性;如果它导致您的规则被覆盖,您可以尝试降低其特异性,方法是简化选择器或更改规则在样式表中的位置。如果这不可行,您还可以尝试引入 :not() 来阻止其他规则应用,这对于不同的元素状态(:hover:active[checked][disabled])尤其相关。但是,切勿尝试增加您正在添加的规则的选择器,因为它很容易变得难以理解。

最后,在检查完上述所有内容后,您可以允许自己在添加注释说明原因的情况下使用 !important

使用 CSS 变量

添加新变量

在添加新的 CSS 变量之前,请考虑以下问题

  1. **变量值是否在运行时更改?** (无论是来自 JavaScript 还是由另一个 CSS 文件覆盖) **如果答案是否定**,请考虑使用预处理器变量或内联值。

  2. **变量值是否被多次使用?** **如果答案是否定,并且该值在运行时没有更改**,那么您可能不需要 CSS 变量。

  3. **是否有使用变量的替代方法,例如继承或使用 ``currentcolor`` 关键字?** 使用继承或使用 currentcolor 将避免重复值,这通常是一种良好的实践。

总的来说,最好首先考虑如何在没有 CSS 变量的情况下干净地编写一些 CSS,然后再考虑 CSS 变量如何改进该 CSS。

使用变量

根据变量的命名方式使用变量

这样做

xul|tab:hover {
  background-color: var(--in-content-box-background-hover);
}

不要这样做

#certificateErrorDebugInformation {
  background-color: var(--in-content-box-background-hover);
}

本地化

文本方向

  • 对于边距、填充和边框,使用 inline-start/inline-end 而不是 left/right示例:使用 margin-inline-start: 3px; 而不是 margin-left: 3px

  • 对于 RTL 感知定位 (左/右),使用 inset-inline-start/inset-inline-end

  • 对于 RTL 感知浮动布局,可以使用 float: inline-start|inline-end 代替 float: left|right

  • border-{top/bottom}-{left/right}-radius 的 RTL 感知等效项为 border-{start/end}-{start/end}-radius

  • 当没有可用的特殊 RTL 感知属性时,请使用伪类 :-moz-locale-dir(ltr|rtl)(对于 XUL 文件)或 :dir(ltr|rtl)(对于 HTML 文件)。

  • 请记住,虽然选项卡内容的滚动条在 RTL 中仍然显示在右侧,但溢出滚动条将显示在左侧。

  • 编写 padding: 0 3px 4px; 而不是 padding: 0 3px 4px 3px;。这使填充的对称性更加明显(因此 RTL 不会成为问题)。

注意

有关更多信息,请参阅 CSS 逻辑属性和值

编写跨平台 CSS

Firefox 支持许多不同的平台,并且这些平台中的每一个都可能包含许多不同的配置

  • Windows 7、8 和 10

    • 默认主题

    • Aero basic (Windows 7、8)

    • Windows classic (Windows 7)

    • 高对比度 (所有版本)

  • Linux

  • macOS

文件结构

  • browser/ 目录包含 Firefox 特定的样式

  • toolkit/ 目录包含所有工具箱应用程序(Thunderbird 和 SeaMonkey)共享的样式

在这两个目录中的每一个下,都有一个 themes 目录,其中包含 4 个子目录

  • shared

  • linux

  • osx

  • windows

shared 目录包含所有 3 个平台共享的样式,而其他 3 个目录分别包含其平台的样式。

对于新的 CSS,在可能的情况下,请尝试优先使用 shared 目录,而不是为 3 个平台特定目录编写相同的 CSS,尤其是在大型 CSS 块中。

内容 CSS 与主题 CSS

以下目录也包含 CSS

  • browser/base/content/

  • toolkit/content/

这些目录包含内容 CSS,它应用于所有平台,即被认为对于浏览器正确运行至关重要的样式。要确定某些 CSS 是主题端还是内容端,了解某些 CSS 属性会倾向于哪一方很有用:color - 99% 的情况下它将是主题 CSS,overflow - 99% 内容。

99% 主题

70% 主题

70% 内容

99% 内容

font-*, color, *-color, border-*, -moz-appearance [1]

line-height, padding, margin

cursor, width, max-width, top, bottom [2],等等

overflow, direction, display, *-align, align-*, *-box-*, flex-*, order

如果某些 CSS 与布局或功能相关,则它可能是内容 CSS。如果它与美学相关,则它可能是主题 CSS。

导入样式表时,最好先导入内容 CSS,然后再导入主题 CSS,这样主题值就可以覆盖内容值(这可能是您想要的),并且您希望将它们都放在全局值之后,因此您的导入将如下所示

<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/content/path/module.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/skin/path/module.css" type="text/css"?>

颜色

对于 Firefox 界面(面板、工具栏按钮等)的常用区域,mozilla-central 通常会提供一些有用的 CSS 变量,这些变量会根据不同的平台配置调整为正确的值,因此使用这些 CSS 变量可以明确地节省一些测试时间,因为您可以假设它们已经可以正常工作。

使用 currentcolor 关键字或继承也是一种好的做法,因为有时所需的值已经存在于颜色中或父元素上。这与使用 -moz-context-properties: fill; 的图标结合使用时尤其有用,其中图标可以根据文本颜色自动调整到正确的平台颜色。也可以将 currentcolor 与其他属性(如 opacityfill-opacity)一起使用,以获得平台颜色的不同不透明度。

高对比度模式

内容区域

在 Windows 高对比度模式下,在内容区域中,Gecko 会对页面颜色进行一些自动颜色调整。这些调整的一部分包括使所有 box-shadow 变得不可见,因此如果您使用 box-shadow 属性创建焦点环或边框,则需要注意这一点:如果希望边框/焦点环在高对比度模式下保持可见,请考虑使用 borderoutline。此类错误的一个示例是 错误 1516767

另一个需要注意的调整是,启用高对比度模式时,Gecko 会删除所有 background-image。如果图像渲染很重要,请考虑使用实际的 <img> 标签(对于 HTML 文档)或 list-style-image(对于 XUL 文档)。

如果您未使用 Windows,则在其他平台上测试这些调整的一种方法是

  • 转到 about:preferences

  • 单击“语言和外观”部分的“字体和颜色”子部分中的“颜色...”按钮

  • 在“使用以上选择覆盖页面指定的颜色”下,选择“始终”选项

Chrome 区域

前面提到的自动调整仅适用于在内容区域中呈现的页面。Firefox 的 Chrome 区域使用创作时的颜色,因此使用预定义变量、currentcolor 或继承对于与系统主题集成非常有用,并且几乎无需任何麻烦。

否则,作为最后的手段,使用 系统颜色 也适用于非默认 Windows 主题或 Linux。通常,使用以下颜色

  • -moz-Field:文本框或字段背景颜色,也用作列表框或树的背景颜色。

  • -moz-FieldText:文本框或字段文本颜色,也用作列表框或树的文本颜色。

  • -moz-Dialog:窗口或对话框背景颜色。

  • -moz-DialogText:窗口或对话框文本颜色。

  • GrayText:在禁用项上用作文本颜色。不要将其用于未禁用的文本以弱化文本,因为它不能保证未禁用文本具有足够的对比度。

  • ThreeDShadow:用作元素上的边框。

  • ThreeDLightShadow:用作元素上的浅色边框。

使用背景/文本对尤其重要,以确保在所有情况下都尊重对比度。切勿将自定义文本颜色与系统背景颜色混合使用,反之亦然。

请注意,使用系统颜色仅对 Chrome 区域有用,因为内容区域颜色无论如何都会被 Gecko 覆盖。

编写媒体查询

布尔媒体查询

这样做

@media (-moz-mac-yosemite-theme: 0) {

不要这样做

@media not all and (-moz-mac-yosemite-theme) {

为最常见的配置设置权限 CSS

最好将最常见的配置(例如操作系统的最新版本或默认主题)放在媒体查询之外。在以下示例中,-moz-mac-yosemite-theme 针对 macOS 10.10 及更高版本,因此它应该优先于 macOS 10.9 的样式。

这样做

@media (-moz-mac-yosemite-theme: 0) {
  #placesList {
    box-shadow: inset -2px 0 0 hsla(0,0%,100%,.2);
  }
}

不要这样做

#placesList {
  box-shadow: inset -2px 0 0 hsla(0,0%,100%,.2);
}

@media (-moz-mac-yosemite-theme) {
  #placesList {
    box-shadow: none;
  }
}

主题支持

Firefox 内置了 3 个主题:默认、浅色和深色。内置的浅色/深色主题有点特殊,因为它们会加载 compacttheme.css 样式表。除此之外,Firefox 还支持各种可以从 AMO 安装的 WebExtension 主题。出于测试目的,这是一个 WebExtension 主题的示例。

编写主题友好型 CSS

  • 一些针对不同平台预先调整的 CSS 变量也针对主题进行了预先调整,因此再次建议您使用它们来支持主题。

  • 元素的文本颜色通常包含来自主题颜色的有价值的信息,因此 currentcolor/继承再次建议用于主题支持。

  • 除非该 CSS 不应影响 WebExtension 主题,否则切勿在 compacttheme.css 中专门为内置的浅色/深色主题编写 CSS。

  • 这些选择器可用于定位主题区域,但总的来说,建议您尽量避免使用它们,并使用 light-dark() 自动获取正确的颜色

    • :root[lwt-toolbar-field="light/dark"]:显式浅色或深色地址栏和搜索栏。

    • :root[lwt-toolbar-field-focus="light/dark"]:处于聚焦状态下的显式浅色或深色地址栏和搜索栏。

    • :root[lwt-popup="light/dark"]:显式浅色或深色箭头面板和自动完成面板。

    • :root[lwt-sidebar="light/dark"]:显式浅色或深色侧边栏。

  • 如果您想要主题区域的不同阴影,并且没有合适的 CSS 变量,则通常使用具有 alpha 透明度的颜色是一个好主意,因为它将保留原始主题作者的颜色色调。

变量

为了清楚起见,仅在启用主题时使用的 CSS 变量具有 --lwt- 前缀。

布局和性能

布局

混合使用 XUL flexbox 和 HTML flexbox 会导致未定义的行为。

CSS 选择器

当定位页面的根元素时,使用 :root 是最有效的方法。

重排和样式刷新

有关此内容的更多信息,请参阅 Firefox 前端工程师的性能最佳实践

其他

文本抗锯齿

在方便的情况下,避免在文本上设置 opacity 属性,因为它会导致文本以不同的方式进行抗锯齿。

HDPI 支持

建议使用 SVG,因为它在支持多种分辨率时可以保持 CSS 整洁。有关 SVG 用法的更多信息,请参阅 SVG 指南

但是,如果只有 1x 和 2x PNG 资产可用,则可以使用此 @media 查询来定位更高密度的显示器 (HDPI)

@media (min-resolution: 1.1dppx)