开发者工具中的 CSS 网格工具

韩长浩
Changhao Han

我们为什么要开发 CSS 网格工具?

CSS Grid 是一个非常强大的 CSS 布局系统,可让网站开发者构建复杂的二维布局,并设置有关网格中每个子项的大小、对齐和排序方式。CSS Grid 是在 Flexbox 流行之后引入的,两者合力帮助开发者实现更好的自适应设计,而无需复杂的对齐技巧或 JavaScript 辅助的布局。

CSS 网格作为一个相对较新的布局系统,实现起来也很困难。它的语法非常灵活(只需要搜索网格备忘单),有很多方法可以实现相同的布局,而灵活的尺寸调整和隐式跟踪让更难解释布局是“是”还是“未按预期运行”。正因如此,我们着手在开发者工具中提供专用 CSS 网格工具,以便开发者更好地了解其 CSS 代码的作用,以及如何获得正确的布局。

工具设计

Chrome 与 Edge 携手打造

CSS 网格工具同时吸引了 Chrome 开发者工具和 Edge DevTools 的注意力。我们从一开始就决定合作。我们分享了这两个团队提供的产品、工程和设计资源,并每周就此开展了协调工作。

特性摘要

CSS 网格工具有三项主要功能:

  1. 特定网格的持久叠加层,有助于提供尺寸和排序信息
  2. DOM 树中的标记,用于突出显示 CSS 网格容器并切换网格叠加层
  3. 一个边栏窗格,可让开发者对 DOM 叠加层的显示方式进行个性化设置(例如,更改规则的颜色和宽度)
  4. Styles 窗格中的 CSS 网格编辑器

接下来,让我们深入了解一下。

网格持久性叠加层

在开发者工具中,叠加层是一种强大的工具,可提供单个元素的布局和样式信息:

ALT_TEXT_HERE

这些额外信息会叠加在相关元素上。以前,当您将鼠标悬停在网格上且开发者工具已打开时,叠加层会显示其框模型信息,但会将内容突出显示为网格项,而不会说明这种情况的原因。我们要为 CSS 网格叠加层添加两个主要部分:

  • 我们希望显示有关网格的更多实用信息,例如作者的尺寸和间隙
  • 我们希望使叠加层具有粘性,以便同时查看多个网格,并且可以看到叠加层在更改元素样式时更新网格信息

我们来看看我们是如何做到这两点的。

编写的尺寸与计算出的尺寸

调试 CSS 网格时遇到的一个难点在于定义网格轨迹大小的方法多种多样。例如,您可以组合使用像素值、百分比值、分数、重复函数和 minmax 函数来创建通用的轨道尺寸:

.grid-cards {
    display: grid;
    width: 200px;
    height: 300px;
    grid-template-rows: 20% 0.3fr 100px minmax(100px, auto);
    grid-template-columns: repeat(3, minmax(200px, 1fr));
}

不过,很难将这些“制作”的轨道大小映射到浏览器为我们计算出的“计算出的轨道大小”。为了消除这种缺陷,我们在叠加层上并排提供了以下两项信息:

ALT_TEXT_HERE

点之前的字符串是编制的值,点之后的字符串表示实际计算的值。

以前,开发者工具无法获取授权值。理论上,我们可以通过某种方式在开发者工具中自行解析编写的值,并根据 CSS 网格规范计算这些值。这会涉及许多复杂的场景,本质上就是重复 Blink 的工作。因此,在 Blink 样式团队的帮助下,我们从样式引擎中得到了一个新的 API,该 API 会公开“级联值”级联值是 CSS 属性在 CSS 级联之后的最终有效值。这是在样式引擎编译所有样式表之后,但在实际计算任何值(例如百分比、分数等)之前胜出的值。

现在,我们使用此 API 在网格叠加层中显示编写的值

永久性叠加层

在 CSS 网格工具推出之前,开发者工具中的叠加层非常简单:将鼠标悬停在某个元素上,无论是在开发者工具的“DOM 树”窗格中,还是直接在检查的页面中,您会看到一个描述此元素的叠加层。将鼠标悬停在其他位置,叠加层就会消失。对于网格叠加层,我们希望进行如下更改:多个网格可以同时突出显示,网格叠加层可以保持启用状态,而常规的悬停叠加层仍可正常使用。

例如:

ALT_TEXT_HERE

不过,开发者工具中的叠加层并不是在设计时考虑了这种多元素、持久的机制(它在多年前创建过)。因此,我们必须重构叠加层设计,才能使其发挥作用。我们在现有的突出显示工具套件添加了新的 GridHighlightTool,该工具后来演变为全局 PersistentTool,用于同时突出显示所有持久性叠加层。对于每种持久叠加层(Grid、Flex 等),我们在持久性工具中都保留相应的配置字段。每次叠加层突出显示工具检查要绘制的内容时,也会包含这些配置。

为了让开发者工具可以控制需要突出显示的内容,我们为网格持久叠加层创建了新的 CDP 命令:

# Highlight multiple elements with the CSS Grid overlay.
command setShowGridOverlays
  parameters
    # An array of node identifiers and descriptors for the highlight appearance.
    array of GridNodeHighlightConfig gridNodeHighlightConfigs

其中,每个 GridNodeHighlightConfig 都包含有关要绘制哪个节点以及如何绘制的信息。这使我们能够添加多项持久机制,而不会破坏当前的悬停行为。

实时网格徽章

为了帮助开发者轻松打开和关闭网格叠加层,我们决定在 DOM 树中的网格容器旁边添加小标记。这些标志还可以帮助开发者识别其 DOM 结构中的网格容器。

ALT_TEXT_HERE

DOM 树的变更

由于 Grid 标记并不是我们要在 DOM 树中显示的唯一标记,因此我们希望尽可能简化标记添加过程。ElementsTreeElement(负责在开发者工具中创建和管理各个 DOM 树元素的类)已更新,增加了几种用于配置标志的新公共方法。如果一个元素有多个标志,则这些标志按标志类别排序;如果它们属于同一类别,则按标志名称的字母顺序排序。可用类别包括 SecurityLayout 等,而 Grid 属于 Layout 类别。

此外,我们从一开始就提供内置的无障碍功能支持。每个互动标志都需要提供默认和有效的 aria-label,而只读标志则使用其标志名称 aria-label

我们如何获得实时样式更新?

许多 DOM 更改都会实时反映在开发者工具 DOM 树中。例如,新添加的节点会瞬间出现在 DOM 树中,而移除的类名称也会瞬间消失。我们希望网格徽章状态也能反映相同的最新信息。但事实证明,实现起来很难,因为当 DOM 树中显示的元素获取计算的样式更新时,开发者工具无法收到通知。了解某个元素何时成为或不再是网格容器的唯一现有方式是不断向浏览器查询每个元素的最新样式信息。这会非常昂贵。

为了让前端更轻松地知道元素的样式更新时间,我们添加了用于轮询样式更新的新 CDP 方法。为了获取 DOM 节点的样式更新,我们首先告知浏览器我们要跟踪的 CSS 声明。对于网格标记,我们会要求浏览器跟踪以下信息:

{
  "display": "grid",
  "display": "inline-grid",
}

然后,我们会发送轮询请求,当 Elements 面板中有 DOM 节点的已跟踪样式更新时,浏览器会向开发者工具发送已更新节点的列表并解析现有的轮询请求。每当开发者工具想要再次收到有关样式更新的通知时,都可以发送此轮询请求,而不是从每个节点不断轮询后端。开发者工具还可以通过向浏览器发送新列表来更改所跟踪的 CSS 声明。

布局窗格

虽然 DOM 树标记有助于发现 CSS 网格,但有时我们需要查看特定页面中所有 CSS 网格的列表,并轻松打开和关闭它们的持久叠加层,以调试其布局。因此,我们决定专门为布局工具创建一个专用的边栏窗格。这样,我们就能获得一个专用空间,用来收集所有网格容器,并配置网格叠加层的所有选项。在这个 Layout 窗格中,我们还可以将未来会占用大量布局的工具(例如 Flexbox容器查询)也放到这里。

按计算的样式查找元素

为了在 Layout 窗格中显示 CSS 网格容器列表,我们需要按计算的样式查找 DOM 节点。事实证明,这也并不简单,因为当开发者工具打开时,并非所有 DOM 节点都能被开发者工具所知。相反,Devtools 只知道一小部分节点(通常位于 DOM 层次结构的顶层),只是为了启动 Devtools DOM 树。出于性能原因,只有在收到进一步请求时,才会提取其他节点。这意味着,我们需要使用新的 CDP 命令来收集网页中的所有节点,并按计算的样式对节点进行过滤:

# Finds nodes with a given computed style in a subtree.
experimental command getNodesForSubtreeByStyle
  parameters
    # Node ID pointing to the root of a subtree.
    NodeId nodeId
    # The style to filter nodes by (includes nodes if any of properties matches).
    array of CSSComputedStyleProperty computedStyles
    # Whether or not iframes and shadow roots in the same target should be traversed when returning the
    # results (default is false).
    optional boolean pierce
  returns
    # Resulting nodes.
    array of NodeId nodeIds

这使开发者工具前端能够获取页面中的 CSS 网格容器列表(可能会穿透 iframe 和影子根),并在“布局”窗格中呈现这些容器。

总结

CSS 网格工具是首批支持网络平台功能的开发者工具设计工具项目之一。它在开发者工具中首次推出了许多基本工具(例如持久性叠加层、DOM 树标记和 Layout 窗格),并为 Chrome DevTools 中的未来布局工具(例如 Flexbox 和 Container 查询)铺平了道路。它还为 Grid 和 Flexbox 编辑器奠定了基础,使开发者能够以交互方式更改 Grid 和 Flexbox 对齐方式。以后我们会一一介绍。

下载预览渠道

不妨考虑将 Chrome Canary 版开发者版Beta 版用作默认开发浏览器。通过这些预览渠道,您可以使用最新的开发者工具功能,测试先进的网络平台 API,并先于用户发现您网站上的问题!

与 Chrome 开发者工具团队联系

使用以下选项讨论博文中的新功能和变化,或讨论与开发者工具有关的任何其他内容。

  • 请通过 crbug.com 向我们提交建议或反馈。
  • 使用开发者工具中的更多选项   了解详情   > Help > Report a DevTools issues,报告开发者工具问题。
  • 您可以前往 @ChromeDevTools 发 Twitter 微博。
  • 请在 YouTube 视频或“开发者工具提示”YouTube 视频中留言说明“开发者工具的新变化”。