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

Changhao Han
Changhao Han

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

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

CSS Grid 作为一种相对较新的布局系统,也很难正确正确。它的语法非常灵活多样(仅搜索网格备忘单),可以通过多种方式实现相同的布局,而灵活的大小调整和隐式跟踪会使您更难以推断布局的行为。正因如此,我们着手在开发者工具中提供专用 CSS 网格工具,让开发者能够更好地了解其 CSS 代码的作用,以及如何获得合适的布局。

工具设计

Chrome 和 Edge 携手合作

CSS 网格工具同时吸引了 Chrome DevTools 和 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

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

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

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

持久叠加层

在推出 CSS 网格工具之前,DevTools 中的叠加层非常简单:将鼠标悬停在某个元素上(无论是在开发者工具的 DOM 树窗格中,还是直接在检查的页面中),您就会看到一个描述此元素的叠加层。您将鼠标悬停在其上后,叠加层便会消失。对于网格叠加层,我们希望有所不同:可以同时突出显示多个网格,并且当常规的悬停叠加层仍正常运行时,网格叠加层可以保持开启状态。

例如:

ALT_TEXT_HERE

然而,开发者工具中的叠加层在设计时并未考虑到这种多元素的持久性机制(它是许多年前创建的)。因此,我们必须重构叠加层设计才能使其正常运行。我们在现有的突出显示工具套件添加了新的 GridHighlightTool,该工具后来发展为可同时突出显示所有持久叠加层的全局 PersistentTool。对于每类持续性叠加层(网格、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 树中显示的元素获得计算的样式更新时,DevTools 无法获得通知。要想了解某个元素何时变为或停止成为 Grid 容器,唯一的现有方法是不断查询浏览器以获取每个元素的最新样式信息。费用高昂昂贵得让人望而却步。

为了让前端更容易知道元素何时更新了元素样式,我们添加了用于样式更新轮询的新 CDP 方法。要获取 DOM 节点的样式更新,我们首先告诉浏览器我们要跟踪的 CSS 声明。对于 Grid 标志,我们要求浏览器跟踪以下内容:

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

然后,我们会发送一个轮询请求,如果 Elements 面板中有 DOM 节点的 tracked 样式更新,浏览器会向开发者工具发送一个更新节点列表,并解析现有的轮询请求。每当开发者工具想要再次收到样式更新通知时,都可以发送此轮询请求,而不是不断从每个节点轮询后端。开发者工具还可以通过向浏览器发送新列表来更改所跟踪的 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 树标记和布局窗格,并为未来 Chrome 开发者工具中的布局工具(例如 Flexbox 和容器查询)铺平了道路。还为 Grid 和 Flexbox 编辑器奠定了基础,使开发者能够以交互方式更改网格和 Flexbox 对齐方式。我们会在日后详细介绍。

下载预览渠道

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

与 Chrome 开发者工具团队联系

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

  • 请通过 crbug.com 提交建议或反馈。
  • 在开发者工具中使用更多选项   了解详情   > 帮助 > 报告开发者工具问题来报告开发者工具问题。
  • 请发送电子邮件至 @ChromeDevTools
  • 请对我们的开发者工具新功能 YouTube 视频或开发者工具提示 YouTube 视频发表评论。