颜色输入:深入探讨跨浏览器差异

Avatar of Ana Tudor
Ana Tudor

DigitalOcean 为您旅程的各个阶段提供云产品。立即开始使用 $200 免费信用额度!

在本文中,我们将深入了解 <input type='color'> 元素的内部结构、浏览器不一致性、为什么它们在特定浏览器中以特定方式显示,以及如何深入研究。深入了解此输入可以帮助我们评估是否可以实现特定的跨浏览器外观,以及如何以最少的工作量和代码来实现。

以下是我们的重点内容

但在深入研究之前,我们需要了解…

可访问性问题!

我们遇到了一个重大问题:对于完全依赖键盘的用户来说,此输入在 Safari 和 Windows 上的 Firefox 中无法正常工作,但在 Mac 和 Linux 上的 Firefox 中可以正常工作(我只在 Fedora 上进行了测试,因此如果您使用其他发行版无法正常工作,请随时在评论中告诉我)。

在 Windows 上的 Firefox 中,我们可以使用 Tab 键将焦点移至输入框,然后按 Enter 键打开一个对话框……然后我们无法使用键盘导航!

我尝试过使用 Tab 键、箭头键和键盘上的所有其他键……没有任何效果!我至少可以使用 Alt + F4 关闭对话框。后来,我在 Bugzilla 上的错误单 中发现了一个解决方法:使用 Alt + Tab 切换到另一个窗口,然后再次使用 Alt + Tab 返回,这样就可以使用键盘导航选择器对话框了。

Safari 中的情况更糟。如果未启用 VoiceOver,则输入框甚至无法获得焦点 (错误单)。即使使用 VoiceOver,也无法在输入框打开的对话框中进行 Tab 键导航。

如果您想在实际网站上使用 <input type='color'>,请告知浏览器需要解决此问题!

如何查看内部结构

在 Chrome 中,我们需要打开开发者工具,转到 **设置**,然后在 **首选项** 部分的 **元素** 下,勾选 **显示用户代理影子 DOM** 选项。

如何在 Chrome 中查看输入框内部的结构。

然后,当我们返回检查元素时,就可以看到其影子 DOM 的内部结构了。

在 Firefox 中,我们需要转到 about:config 并确保 devtools.inspector.showAllAnonymousContent 标志设置为 true

如何在 Firefox 中查看输入框内部的结构。

然后,我们关闭开发者工具,再次检查输入框时,就可以看到其内部结构了。

不幸的是,在 Chromium 之前的 Edge 中,我们似乎没有此选项。

内部结构

在开发者工具中显示的结构因浏览器而异,就像范围输入一样。

在 Chrome 中,影子 DOM 的顶部有一个 <div> 包装器,我们可以使用 ::-webkit-color-swatch-wrapper 访问它。

在它里面,我们还有另一个 <div>,我们可以使用 ::-webkit-color-swatch 访问它。

Chrome 开发者工具的屏幕截图,显示 <input type='color' data-recalc-dims= 的影子 DOM。在最顶部,我们有一个 div,它是色板包装器,可以使用 ::-webkit-color-swatch-wrapper 访问。在它里面,还有另一个 div,它是色板,可以使用 ::-webkit-color-swatch 访问。此 div 的 background-color 设置为父颜色输入的值。”/>
Chrome 中的内部结构。

在 Firefox 中,我们只看到一个 <div>,但它没有标签,所以我们该如何访问它呢?

凭直觉,考虑到此 <div>background-color 设置为输入的 value 属性,就像 ::-webkit-color-swatch 组件一样,我尝试了 ::-moz-color-swatch。结果它有效!

Firefox 开发者工具的屏幕截图,显示 <input type='color' data-recalc-dims= 的内部结构。与 Chrome 不同,这里我们只有一个 div,它是色板,可以使用 ::-moz-color-swatch 访问。此 div 的 background-color 设置为父颜色输入的值。”/>
Firefox 中的内部结构。

但是,我后来了解到,在 Firefox 中,我们有一个更好的方法来弄清楚这一点!

我们可以进入 Firefox 开发者工具设置,在 Inspector 部分,确保已选中“显示浏览器样式”选项。然后,我们返回 Inspector 并选择 <input type='color'> 内部的 <div>。在用户代理样式中,我们会看到一个为 input[type='color']::-moz-color-swatch 设置的规则!

动画 GIF。显示如何在 Firefox 开发者工具中启用查看应用的用户代理样式:设置 data-recalc-dims= Inspector > 选中显示浏览器样式复选框。”/>
在 Firefox 开发者工具中启用查看浏览器样式。

在 Chromium 之前的 Edge 中,我们甚至无法看到内部的结构。我尝试过 ::-ms-color-swatch,但它不起作用,::-ms-swatch 也不起作用(我考虑过它,因为对于 input type='range',我们有 ::-webkit-slider-thumb::-moz-range thumb,但只有 ::-ms-thumb)。

经过一番搜索,我发现的只有 这个 2016 年提出的问题。Chromium 之前的 Edge 似乎不允许我们为此输入内部的任何内容设置样式。好吧,这很糟糕。

如何查看浏览器样式

在所有浏览器中,我们都可以选择不应用任何自己的样式,然后查看计算的样式。

在 Chrome 和 Firefox 中,我们还可以看到影响当前选定元素的用户代理样式表规则集(尽管我们需要在 Firefox 中显式启用此功能,如上一节所述)。

Chrome 开发者工具和 Firefox 开发者工具的屏幕截图,显示在哪里查找用户代理样式:元素 data-recalc-dims= Chrome 中的样式和 Inspector > Firefox 中的样式。”/>
在 Chrome 和 Firefox 中检查浏览器样式。

这通常比计算的样式更有用,但也有例外,我们仍然应该始终检查计算的值。

在 Firefox 中,我们还可以查看 form 元素的 CSS 文件,位于 view-source:resource://gre-resources/forms.css

Screenshot showing view-source:resource://gre-resources/forms.css open in Firefox to allow us seeing user agent styles for form elements.
在 Firefox 中检查浏览器样式。

输入元素本身

现在我们将查看不同浏览器中一些属性的默认值,以清楚了解我们真正需要显式设置哪些内容才能获得自定义的跨浏览器结果。

在处理 <input> 元素时,我总是首先想到要检查的属性是 box-sizing。此属性的初始值在 Firefox 中为 border-box,但在 Chrome 和 Edge 中为 content-box

Comparative screenshots of DevTools in the three browsers showing the computed values of box-sizing for the actual input.
<input type='color'>box-sizing 值在 Chrome、Firefox 和 Edge 中的比较(从上到下)。

我们可以看到 Firefox 在 <input type='color'> 上将其设置为 border-box,但 Chrome 似乎根本没有设置它,因此它保留了 content-box 的初始值(我怀疑 Edge 也一样)。

无论如何,这意味着如果我们要为此元素设置 borderpadding,我们还需要显式设置 box-sizing,以便在所有这些浏览器中获得一致的结果。

font 属性的值在每个浏览器中都不同,但由于此输入框中没有文本,因此我们真正关心的是 font-size,它在我检查过的所有浏览器中都是一致的:13.33(33)px。至少在 Chrome 中,这个值看起来确实像是从 40px 除以 3 得到的。

Comparative screenshots of DevTools in the three browsers showing the font values for the actual input.
<input type='color'>font 值在 Chrome、Firefox 和 Edge 中的比较(从上到下)。

在这种情况下,计算的样式对 Firefox 更有用,因为如果我们查看浏览器样式,我们不会获得太多有用的信息。

Screenshot of what we get if we look at the browser styles where the font was set for Firefox. The value for the font is -moz-field, which is an alias for the look of a native text field. Expanding this to check the longhands shows us empty instead of actual values.
有时浏览器样式毫无用处(Firefox 屏幕截图)。

margin 在所有这些浏览器中也是一致的,计算结果为 0

Comparative screenshots of DevTools in the three browsers showing the margin values for the actual input.
<input type='color'>margin 值在 Chrome、Firefox 和 Edge 中的比较(从上到下)。

每个浏览器对`border`的处理都不一样。在 Chrome 和 Edge 中,我们都有`solid 1px`的边框,但`border-color`不同(Chrome 为`rgb(169, 169, 169)`,Edge 为`rgb(112, 112, 112)`)。在 Firefox 中,`border`为`outset 2px`,`border-color`为… `ThreeDLightShadow`?!

Comparative screenshots of DevTools in the three browsers showing the border values for the actual input.
Chrome、Firefox 和 Edge 中`<input type='color'>`的`border`值对比(从上到下)。

`ThreeDLightShadow`是怎么回事?如果你没听说过,别担心!它是一个(现在已过时的)CSS2 系统值,在 Windows 上的 Firefox 中,它在**计算**样式选项卡中显示为`rgb(227, 227, 227)`。

Screenshot of Computed panel search in Firefox on Windows, showing that the ThreeDLightShadow keyword computes to rgb(227, 227, 227).
Windows 上 Firefox 中`<input type='color'>`的计算`border-color`。

请注意,在 Firefox 中(至少在 Windows 上),操作系统缩放级别(设置系统显示缩放和布局更改文本、应用程序和其他项目的尺寸)会影响`border-width`的计算值,即使在我检查过的其他属性中似乎没有发生这种情况,并且似乎与`border-style`有关。

Screenshot showing the Windows display settings window with the zoom level options dropdown opened.
Windows 上的缩放级别选项。

最奇怪的是,对于不同的缩放级别,计算出的`border-width`值似乎毫无意义。如果我们保留初始的`border-style: outset`,我们会得到

  • 125%时为`1.6px`
  • 150%时为`2px`
  • 175%时为`1.7px`
  • 200%时为`1.5px`
  • 225%时为`1.8px`
  • 250%时为`1.6px`
  • 300%时为`1.66667px`

如果我们设置`border-style: solid`,对于`50%`的倍数的缩放值,我们会得到一个计算出的`border-width`为`2px`,与设置的一样,而对于其他所有缩放级别,则得到与`border-style: outset`相同的计算值。

Chrome 和 Edge 的`padding`相同(`1px 2px`),而 Firefox 再次不同。

Comparative screenshots of DevTools in the three browsers showing the padding values for the actual input.
Chrome、Firefox 和 Edge 中`<input type='color'>`的`padding`值对比(从上到下)。

Firefox 的`padding`看起来像是`1px`。这正是它被设置为的值,没有任何迹象表明有任何东西覆盖它——如果一个属性被覆盖,那么它将显示为灰色并带有删除线。

Screenshot of Firefox DevTools highlighting how the border set on input[type='color'] overrides the one set on input and the look (grey + strike-through) of overridden properties.
在 Firefox 中发现覆盖。

但计算出的值为`0 8px`!此外,这个值不依赖于操作系统的缩放级别。所以,到底发生了什么?!

Firefox DevTools 的屏幕截图,显示了`<input type='color' data-recalc-dims=`上的计算 `padding` 值不是在输入上设置的值,即使没有覆盖似乎正在发生。”/>
Firefox 中`padding`的计算值与在输入上设置的值不匹配。

现在,如果你真的尝试过检查颜色输入,仔细查看了它的样式,而且你的大脑和我的工作方式不同(这意味着你会阅读你面前的内容,而不是仅仅扫描你感兴趣的一件事,完全忽略其他所有事情……)那么你可能已经注意到有一些东西覆盖了`1px`的`padding`(而且应该被标记为这样)——流相关填充

Screenshot of Firefox DevTools showing the flow-relative padding overriding the old padding due to higher specificity of selector (input[type='color'] vs. input).
Firefox 中的流相关`padding`覆盖。

天啊,谁知道那些带有很多字母的属性实际上是相关的?感谢Zoltan 发现并让我知道。否则,我可能还需要两天才能弄清楚这一点。

这就引出了一个问题,即其他浏览器和/或其他属性是否也可能发生相同类型的覆盖。

Edge 不支持 CSS 逻辑属性,所以在那个方面答案是“否”。

在 Chrome 中,`<input type='color'>`没有显式设置`margin`、`border` 或`padding`的任何逻辑属性,因此没有覆盖。

在 Firefox 中,我们可能在`margin`或`border`上遇到了相同的情况,但对于这两个属性,恰好流相关的属性没有为我们的输入显式设置,因此同样没有覆盖。

即使这样,它绝对是将来需要关注的事情!

接下来是尺寸,我们的输入在 Chrome 和 Edge 中的`width`为`44px`,在 Firefox 中为`64px`。

Comparative screenshots of DevTools in the three browsers showing the width values for the actual input.
Chrome、Firefox 和 Edge 中`<input type='color'>`的`width`值对比(从上到下)。

它的`height`在所有三个浏览器中都是`23px`。

Comparative screenshots of DevTools in the three browsers showing the height values for the actual input.
Chrome、Firefox 和 Edge 中`<input type='color'>`的`height`值对比(从上到下)。

请注意,由于 Chrome 和 Edge 的`box-sizing`为`content-box`,它们的`width`和`height`值不包括`padding`或`border`。但是,由于 Firefox 的`box-sizing`设置为`border-box`,它的尺寸包括`padding`和`border`。

Comparative screenshots of DevTools in the three browsers showing the layout boxes.
Chrome、Firefox 和 Edge 中`<input type='color'>`的布局框对比(从上到下)。

这意味着 Chrome 和 Edge 中的`content-box`为`44px`x`23px`,Firefox 中为`44xpx`x`19px`;Chrome 和 Edge 中的`padding-box`为`48px`x`25`,Firefox 中为`60px`x`19px`;Chrome 和 Edge 中的`border-box`为`50px`x`27px`,Firefox 中为`64px`x`23`。

我们可以清楚地看到 Chrome 中是如何设置尺寸的,我假设 Edge 中也是以同样的直接方式设置的,即使 Edge 不允许我们追踪这些东西。Firefox 没有显示这些尺寸是被显式设置的,甚至不允许我们在计算选项卡中追踪它们来自哪里(例如,它在`border`等其他属性上是这样做的)。但是,如果我们查看在`input[type='color']`上设置的所有样式,我们会发现尺寸被设置为流相关的(`inline-size`和`block-size`)。

Screenshot of the Firefox user agent styles showing flow relative dimensions being set on input[type='color'].
Firefox 中`<input type='color'>`尺寸是如何设置的。

我们检查的最后一个属性是实际输入的正常状态的`background`。在这里,Edge 是唯一一个有`background-image`(设置为从上到下的渐变)的浏览器,而 Chrome 和 Firefox 都有一个`background-color`设置为`ButtonFace`(另一个已过时的 CSS2 系统值)。奇怪的是,这应该是`rgb(240, 240, 240)`(根据这个资源),但它在 Chrome 中的计算值为`rgb(221, 221, 221)`。

Comparative screenshots of DevTools in the three browsers showing the background values for the actual input.
Chrome、Firefox 和 Edge 中`<input type='color'>`的`background`值对比(从上到下)。

更奇怪的是,如果我们真的在 Chrome 中查看我们的输入,它看起来确实有一个渐变的`background`!如果我们截图,然后使用一个颜色拾取器,我们会发现它有一个从`#f8f8f8`到`#ddd`的从上到下的渐变。

Screenshot of the input in Chrome. A very light, almost white, grey to another light, but still darker grey gradient from top to bottom can be seen as the background, not the solid background-color indicated by DevTools.
Chrome 中实际的输入是什么样子的。它似乎有一个渐变,尽管我们从 DevTools 中得到的信息告诉我们它没有。

此外,请注意,在 Edge 中,只更改`background-color`(或其他与尺寸无关的属性,如`border-radius`)也会更改`background-image`、`background-origin`、`border-color`或`border-style`。

Animated gif. Shows the background-image, background-origin, border-color, border-style before and after changing the seemingly unrelated background-color - their values don't get preserved following this change.
Edge:更改`background-color`的副作用。

其他状态

我们可以通过单击 Chrome 和 Firefox 中`样式`面板中的**`:hov`**按钮,以及 Edge 中同一`样式`面板中的**`a:`**按钮,查看应用于元素的一系列其他状态的样式。这将显示一个区域,我们可以在其中检查所需的状态。

Screenshot collage highlighting the buttons that bring up the states panel in Chrome, Firefox and Edge.
查看 Chrome、Firefox、Edge 中的其他状态(从上到下)。

请注意,在 Firefox 中,检查一个类只会将用户样式视觉上应用到选定的元素,而不是浏览器的样式。因此,例如,如果我们检查`:hover`,我们将看不到`:hover`样式应用到我们的元素。但是,我们可以看到 DevTools 中显示的匹配选中状态的选定元素的用户代理样式。

此外,我们不能这样测试所有状态,让我们从这样一个状态开始。

:disabled

为了查看样式在这个状态下的变化,我们需要手动将`disabled`属性添加到我们的`<input type='color'>`元素中。

嗯… 任何浏览器都没有太多变化!

在 Chrome 中,我们看到`background-color`略有不同(在`:disabled`状态下为`rgb(235, 235, 228)`,而在正常状态下为`rgb(221, 221, 221)`)。

Chrome DevTools screenshot showing the background being set to rgb(235, 235, 228) for a :disabled input.
Chrome `:disabled` 样式。

但只有查看 DevTools 中的信息才能清楚地看到这种差异。从视觉上,我可以看到一个`:disabled`的输入和一个没有`:disabled`的输入之间有轻微的差异,如果它们并排放置的话,但我事先不知道的话,光看它们是无法区分哪个是哪个的,如果我只看到一个,我无法仅通过观察来判断它是否已启用,除非点击它。

Disabled and enabled input side by side in Chrome. There is a slight difference in background-color, but it's pretty much impossible to tell which is which just by looking at them.
Chrome 中的禁用(左)和启用(右)`<input type='color'>`。

在 Firefox 中,我们为`:disabled`状态设置的与正常状态设置的值完全相同(好吧,除了光标,实际上,除了特殊情况外,它不会产生不同的结果)。怎么回事,Firefox?!

Firefox 中设置的样式对比,用于`<input type='color' data-recalc-dims=`,处于其正常状态和`:disabled`状态。在`:disabled`情况下设置的`padding`和`border`与在正常情况下设置的完全相同。”/>
Firefox `:disabled`(顶部)与正常(底部)样式。

在 Edge 中,`border-color`和`background`渐变都不同。

Chrome DevTools screenshot showing border-color and the background-image being set to slightly different values for a :disabled input.
Edge `:disabled` 样式(通过检查计算的样式)。

我们有以下正常状态的样式

border-color: rgb(112, 112, 112);
background-image: linear-gradient(rgb(236, 236, 236), rgb(213, 213, 213));

以及`:disabled`状态的样式

border-color: rgb(186, 186, 186);
background-image: linear-gradient(rgb(237, 237, 237), rgb(229, 229, 229));

如果查看代码,则差异很明显,并且从视觉上来说比 Chrome 更好,尽管它可能仍然不够好

Disabled and enabled input side by side in Edge. There is a slight difference in background-image and a bigger difference in border-color, but it still may be difficult to tell whether an input is enabled or not at first sight without having a reference to compare.
Edge 中的禁用(左)和启用(右)`<input type='color'>`。
:focus

这是我们可以通过切换 DevTools 伪类来测试的一种状态。理论上是这样。实际上,它并不能在所有浏览器中真正帮助我们。

从 Chrome 开始,我们可以看到在这种状态下有一个 outline,并且 outline-color 计算为 rgb(77, 144, 254),这是一种蓝色。

Chrome DevTools 截图,显示了一个具有 <code data-recalc-dims=:focus.”/> 的输入的轮廓。"/>
Chrome :focus 样式。

非常直观且易于识别。

继续转向 Firefox,事情开始变得复杂!与 Chrome 不同,从 DevTools 切换 :focus 伪类对输入元素没有任何作用,但通过聚焦它(通过 Tab 键点击),border 变成了蓝色,并且我们得到了一个点状的矩形——但 DevTools 中没有显示任何正在发生的事情。

Animated gif. Shows how, on :focus, our input gets a blue border and a dark inner dotted rectangle.
当用 Tab 键切换到我们的输入以 :focus 它时,Firefox 中会发生什么。

如果我们检查 Firefox 的 forms.css,它会为点状矩形提供解释。这是伪元素的点状 border::-moz-focus-inner(一个伪元素,出于某种原因,在 DevTools 中未显示在我们的输入内部,因为 ::-moz-color-swatch 是)。这个 border 最初是 transparent,然后在输入聚焦时变得可见——这里使用的伪类 (:-moz-focusring) 基本上是新标准 (:focus-visible) 的旧版 Firefox 版本,目前仅在 Chrome 中通过 **Experimental Web Platform features** 标志支持。

Firefox DevTools screenshot where the inner dotted rectangle on :focus comes from: it is set as a transparent border on the ::-moz-focus-inner pseudo-element and it becomes visible when the input should have a noticeable :focus indicator.
Firefox::focus 上的内部点状矩形来自哪里。

蓝色 border 怎么样呢?好吧,看起来它不是由样式表设置的,而是由 OS 级别设置的。好消息是,如果我们选择这样做,我们可以覆盖所有这些样式。

在 Edge 中,我们面临着类似的情况。从 DevTools 切换 :focus 伪类时不会发生任何事情,但如果我们实际上用 Tab 键切换到我们的输入以聚焦它,我们可以看到一个内部点状矩形。

Animated gif. Shows how, on :focus, our input gets an inner dotted rectangle.
当用 Tab 键切换到我们的输入以 :focus 它时,Edge 中会发生什么。

虽然我不知道确切的原因,但我怀疑,就像在 Firefox 中一样,这个内部矩形是由于一个伪元素在 :focus 时变得可见。

:hover

在 Chrome 中,切换此伪类不会在 DevTools 中显示任何特定于 :hover 的样式。此外,实际上将鼠标悬停在输入上似乎不会在视觉上改变任何东西。所以看起来 Chrome 真的没有任何特定于 :hover 的样式吗?

在 Firefox 中,从 DevTools 切换 :hover 伪类会在样式面板中显示一条新规则

Screenshot of Firefox DevTools showing the rule set that shows up for the :hover state.
Firefox :hover 样式,如 DevTools 所示。

当实际将鼠标悬停在输入上时,我们看到 background 变成了浅蓝色,border 变成了蓝色,所以第一个想法是浅蓝色是 -moz-buttonhoverface 的值,并且蓝色 border 再次在 OS 级别设置,就像在 :focus 的情况下一样。

动画 GIF。显示,当实际将鼠标悬停在我们的 <input type='color' data-recalc-dims= 上时,它会获得一个浅蓝色背景和一个蓝色边框。”"/>
Firefox 中 :hover 上实际发生的事情。

但是,如果我们查看计算后的样式,我们会看到与正常状态下相同的 background,因此,尽管在 forms.css 样式表中具有该规则,但该蓝色 background 也可能是在 OS 级别设置的。

Screenshot of Firefox DevTools showing the computed value for background-color in the :hover state.
Firefox::hover<input type='color'> 的计算 background-color

在 Edge 中,从 DevTools 切换 :hover 伪类会为我们的输入提供一个浅蓝色 (rgb(166, 244, 255)) 的 background 和一个蓝色 (rgb(38, 160, 218)) 的 border,其确切值可以在 **Computed** 选项卡中找到

Screenshot of Edge DevTools showing the computed value for background-color and border-color in the :hover state.
Edge::hover<input type='color'> 的计算 background-colorborder-color
:active

在 Chrome DevTools 中检查 :active 状态在视觉上没有任何作用,并且在 Styles 面板中没有显示任何特定规则。但是,如果我们实际点击我们的输入,我们会看到,即使在 DevTools 中没有显示正常状态下的渐变,它也会反转。

Screenshot of the input in :active state in Chrome. A very light, almost white, grey to another light, but still darker grey gradient from bottom to top can be seen as the background, not the solid background-color indicated by DevTools.
Chrome 中 :active 状态下实际输入的外观。它似乎有一个渐变(与正常状态相反),尽管我们从 DevTools 中获取的信息告诉我们它没有。

在 Firefox DevTools 中,在 DevTools 中切换 :active 状态没有任何作用,但如果我们也切换 :hover 状态,那么我们会得到一个规则集,该规则集会更改内联 padding(块 padding 设置为与所有其他状态中相同的 0 值),border-style 并且将 background-color 设置回我们老朋友 ButtonFace

Screenshot of Firefox DevTools showing the rule set that shows up for the :active state.
Firefox :active 样式,如 DevTools 所示。

然而,在实践中,唯一与我们从 DevTools 获取的信息匹配的是逻辑 padding 更改带来的内联偏移。background 变得比 :hover 状态更浅的蓝色,border 为蓝色。这两项更改也可能是在 OS 级别发生的。

动画 GIF。显示,当实际点击我们的 <input type='color' data-recalc-dims= 时,它会获得一个浅蓝色背景和一个蓝色边框,此外由于内联填充的改变而在内联方向上滑动 1 像素。”"/>
Firefox 中 :active 状态下实际发生的事情。

在 Edge 中,从 DevTools 激活 :active 类会为我们提供与 :hover 状态完全相同的样式。但是,如果我们同时启用了 :hover:active 状态,事情会发生一些变化。我们仍然有一个浅蓝色的 background 和一个蓝色的 border,但两者现在都更暗 (rgb(52, 180, 227) 用于 background-colorrgb(0, 137, 180) 用于 border-color)

Screenshot of Edge DevTools showing the computed value for background-color and border-color in the :active state.
Edge 中 :active<input type='color'> 的计算 background-colorborder-color

这是重点:如果我们想要 <input type='color'> 的一致的跨浏览器结果,我们应该自己为所有这些状态定义我们自己的清晰可辨的样式,因为幸运的是,几乎所有浏览器默认值——除了我们在 Edge 的 :focus 上获得的内部矩形——都可以被覆盖。

色板包装器

这是一个我们只在 Chrome 中看到的组件,因此,如果我们想要跨浏览器的结果,我们应该确保它不会影响内部的色板——这意味着确保它没有 marginborderpaddingbackground,并且其尺寸等于实际输入的 content-box

为了知道我们是否需要修改这些属性(以及可能由此产生的其他属性),让我们看看浏览器默认值。

幸运的是,我们没有 marginborder,所以我们不用担心这些。

Chrome DevTools screenshot showing the margin and border values for the swatch wrapper.
Chrome 中色板包装器的 marginborder 值。

但是,我们确实有一个非零的 padding (4px 2px),因此,如果我们想要实现一致的跨浏览器结果,我们需要将其清零。

Chrome DevTools screenshot showing the padding values for the swatch wrapper.
Chrome 中色板包装器的 padding 值。

尺寸都方便地设置为 100%,这意味着我们不需要修改它们。

Chrome DevTools screenshot showing the size values for the swatch wrapper.
Chrome 中色板包装器的尺寸值。

这里需要注意的是,我们已将 box-sizing 设置为 border-box,因此 padding 会从此包装器上设置的尺寸中减去。

Chrome DevTools screenshot showing the box-sizing value for the swatch wrapper.
Chrome 中色板包装器的 box-sizing 值。

这意味着,虽然我们包装器的 padding-boxborder-boxmargin-box(由于没有 marginborder,因此都相等)与实际 <input type='color'>content-box 相同(在 Chrome 中为 44pxx23px),获得包装器的 content-box 需要从这些尺寸中减去 padding。结果是该框为 40pxx15px

Chrome DevTools screenshot showing the box model for the swatch wrapper.
Chrome 中色板包装器的框模型。

background 设置为 transparent,因此我们无需担心重置该属性。

Chrome DevTools screenshot showing the background values for the swatch wrapper.
Chrome 中色板包装器的 background 值。

此元素上还有一个属性引起了我的注意:display。它的值为 flex,这意味着它的子元素是 flex 项目。

Chrome DevTools screenshot showing the display value for the swatch wrapper.
Chrome 中色板包装器的 display 值。

颜色选取器

这是一个可以在 Chrome 和 Firefox 中进行样式设置的组件。遗憾的是,Edge 并没有将其公开以允许我们进行样式设置,因此我们无法更改可能需要的属性,例如 borderborder-radiusbox-shadow

如果我们计划为颜色选取器设置 borderpadding,则需要显式设置 box-sizing 属性,因为其值在 Chrome 中为 content-box,但在 Firefox 中为 border-box

Comparative screenshots of DevTools in the two browsers showing the computed values of box-sizing for the swatch component.
在 Chrome(顶部)和 Firefox(底部)中查看的颜色选取器的 box-sizing 值。

幸运的是,font-size 从输入本身继承而来,因此它是一样的。

Comparative screenshots of DevTools in the two browsers showing the computed values of font-size for the swatch component.
在 Chrome(顶部)和 Firefox(底部)中查看的颜色选取器的 font-size 值。

margin 在 Chrome 和 Firefox 中都计算为 0

Comparative screenshots of DevTools in the two browsers showing the computed values of margin for the swatch component.
在 Chrome(顶部)和 Firefox(底部)中查看的颜色选取器的 margin 值。

这是因为大多数边距都没有设置,因此它们最终都为 0,这是 <div> 元素的默认值。但是,Firefox 将内联边距设置为 auto,我们将在稍后解释为什么它会计算为 0

Screenshot of Firefox DevTools.
在 Firefox 中将颜色选取器的内联 margin 设置为 auto

border 在两个浏览器中都是 solid 1px。唯一不同的是 border-color,Chrome 中为 rgb(119, 119, 119),Firefox 中为 grey(或 rgb(128, 128, 128),因此略微浅一些)。

Comparative screenshots of DevTools in the two browsers showing the computed values of border for the swatch component.
在 Chrome(顶部)和 Firefox(底部)中查看的颜色选取器的 border 值。

请注意,在 Firefox 中(至少在 Windows 上),计算出的 border-width 取决于 OS 缩放级别,就像实际输入一样。

幸运的是,padding 在 Chrome 和 Firefox 中都是 0

Comparative screenshots of DevTools in the two browsers showing the computed values of padding for the swatch component.
在 Chrome(顶部)和 Firefox(底部)中查看的颜色选取器的 padding 值。

尺寸最终与我们预期的一样,假设颜色选取器覆盖了其父元素的整个 content-box

Comparative screenshots of DevTools in the two browsers showing the box model for the swatch component.
在 Chrome(顶部)和 Firefox(底部)中查看的颜色选取器的盒子模型。

在 Chrome 中,颜色选取器的父元素是我们之前看到的 <div> 容器,其 content-box4pxx15px。这等于颜色选取器的 margin-boxborder-box(它们重合,因为我们没有 margin)。由于 padding0,因此颜色选取器的 content-boxpadding-box 相同,减去 1px 边框后,我们得到的尺寸为 38pxx13px

在 Firefox 中,颜色选取器的父元素是实际的输入,其 content-box44pxx19px。这等于颜色选取器的 margin-boxborder-box(它们重合,因为我们没有 margin)。由于 padding0,因此颜色选取器的 content-boxpadding-box 相同,减去 1px 边框后,我们得到的尺寸为 42pxx17px

在 Firefox 中,我们看到颜色选取器通过将两个尺寸都设置为 100% 来覆盖其父元素的 content-box

Comparative screenshots of DevTools in the two browsers showing the size values for the swatch component.
在 Chrome(顶部)和 Firefox(底部)中查看的颜色选取器的尺寸值。

这就是为什么内联 marginauto 值计算为 0 的原因。

但是 Chrome 呢?我们看不到任何实际设置的尺寸。好吧,这个结果是由于 flex 布局以及颜色选取器是一个 flex 项目,它被设置为拉伸以覆盖其父元素的 content-box

Chrome DevTools screenshot showing the flex value for the swatch wrapper.
Chrome 中的颜色选取器容器的 flex 值。

最后的想法

哇,我们在这里涵盖了很多内容!虽然深入研究一个特定元素似乎很全面,但这正是说明跨浏览器支持有多困难的练习。我们有自己的样式、用户代理样式和操作系统样式要遍历,其中一些总是会保持原样。但是,正如我们在最上面讨论的那样,这最终成为一个可访问性问题,并且在实现颜色输入的实用、功能性应用程序时需要认真考虑。

请记住,其中很多内容都是可以向浏览器供应商寻求帮助的,让他们根据您报告的用例更新其实现。以下是我之前提到的三个问题,您可以参与其中或参考它们来创建新问题。