should be marked as such) — the flow-relative padding !Flow-relative padding
overrides in Firefox. Dang, who knew those properties with lots of letters were actually relevant? Thanks to Zoltan for noticing and letting me know. Otherwise, it probably would have taken me two more days to figure this one out.
This raises the question of whether the same kind of override couldn’t happen in other browsers and/or for other properties.
Edge doesn’t support CSS logical properties, so the answer is a “no” in that corner.
In Chrome, none of the logical properties for margin
, border
or padding
are set explicitly for
, so we have no override.
Concerning other properties in Firefox, we could have found ourselves in the same situation for margin
or for border
, but with these two, it just so happens the flow-relative properties haven’t been explicitly set for our input, so again, there’s no override.
Even so, it’s definitely something to watch out for in the future!
Moving on to dimensions, our input’s width
is 44px
in Chrome and Edge and 64px
in Firefox.
The width
values for
compared in Chrome, Firefox and Edge (from top-to-bottom). Its height
is 23px
in all three browsers.
The height
values for
compared in Chrome, Firefox and Edge (from top-to-bottom). Note that, since Chrome and Edge have a box-sizing
of content-box
, their width
and height
values do not include the padding
or border
. However, since Firefox has box-sizing
set to border-box
, its dimensions include the padding
and border
.
The layout boxes for
compared in Chrome, Firefox and Edge (from top-to-bottom). This means the content-box
is 44px
x23px
in Chrome and Edge and 44xpx
x19px
in Firefox, the padding-box
is 48px
x25
in Chrome and Edge and 60px
x19px
in Firefox and the border-box
is 50px
x27px
in Chrome and Edge and 64px
x23
in Firefox.
We can clearly see how the dimensions were set in Chrome and I’d assume they were set in the same direct way in Edge as well, even if Edge doesn’t allow us to trace this stuff. Firefox doesn’t show these dimensions as having been explicitly set and doesn’t even allow us to trace where they came from in the Computed tab (as it does for other properties like border
, for example). But if we look at all the styles that have been set on input[type='color']
, we discover the dimensions have been set as flow-relative ones (inline-size
and block-size
).
How
dimensions have been set in Firefox. The final property we check for the normal state of the actual input is background
. Here, Edge is the only browser to have a background-image
(set to a top to bottom gradient), while Chrome and Firefox both have a background-color
set to ButtonFace
(another deprecated CSS2 system value). The strange thing is this should be rgb(240, 240, 240)
(according to this resource ), but its computed value in Chrome is rgb(221, 221, 221)
.
The background
values for
compared in Chrome, Firefox and Edge (from top-to-bottom). What’s even stranger is that, if we actually look at our input in Chrome, it sure does look like it has a gradient background
! If we screenshot it and then use a picker, we get that it has a top to bottom gradient from #f8f8f8
to #ddd
.
What the actual input looks like in Chrome. It appears to have a gradient, in spite of the info we get from DevTools telling us it doesn’t. Also, note that changing just the background-color
(or another property not related to dimensions like border-radius
) in Edge also changes the background-image
, background-origin
, border-color
or border-style
.
Edge: side-effects of changing background-color
. Other states We can take a look at the styles applied for a bunch of other states of an element by clicking the :hov
button in the Styles
panel for Chrome and Firefox and the a:
button in the same Styles
panel for Edge. This reveals a section where we can check the desired state(s).
Taking a look at other states in Chrome, Firefox, Edge (from top to bottom). Note that, in Firefox, checking a class only visually applies the user styles on the selected element, not the browser styles. So, if we check :hover
for example, we won’t see the :hover
styles applied on our element. We can however see the user agent styles matching the selected state for our selected element shown in DevTools.
Also, we cannot test for all states like this and let’s start with such a state.
:disabled
In order to see how styles change in this state, we need to manually add the disabled
attribute to our
element.
Hmm… not much changes in any browser!
In Chrome, we see the background-color
is slightly different (rgb(235, 235, 228)
in the :disabled
state versus rgb(221, 221, 221)
in the normal state).
Chrome :disabled
styling. But the difference is only clear looking at the info in DevTools. Visually, I can tell tell there’s a slight difference between an input that’s :disabled
and one that’s not if they’re side-by-side, but if I didn’t know beforehand, I couldn’t tell which is which just by looking at them, and if I just saw one, I couldn’t tell whether it’s enabled or not without clicking it.
Disabled (left) versus enabled (right)
in Chrome. In Firefox, we have the exact same values set for the :disabled
state as for the normal state (well, except for the cursor, which realistically, isn’t going to produce different results save for exceptional cases anyway). What gives, Firefox?!
Edge :disabled
styling (by checking computed styles). We have the following styles for the normal state:
border-color: rgb(112, 112, 112);
background-image: linear-gradient(rgb(236, 236, 236), rgb(213, 213, 213));
And for the :disabled
state:
border-color: rgb(186, 186, 186);
background-image: linear-gradient(rgb(237, 237, 237), rgb(229, 229, 229));
Clearly different if we look at the code and visually better than Chrome, though it still may not be quite enough:
Disabled (left) versus enabled (right)
in Edge. :focus
This is one state we can test by toggling the DevTools pseudo-classes. Well, in theory. In practice, it doesn’t really help us in all browsers.
Starting with Chrome, we can see that we have an outline
in this state and the outline-color
computes to rgb(77, 144, 254)
, which is some kind of blue.
What happens in Firefox when tabbing to our input to :focus
it. If we check Firefox’s forms.css
, it provides an explanation for the dotted rectangle. This is the dotted border
of a pseudo-element, ::-moz-focus-inner
(a pseudo-element which, for some reason, isn’t shown in DevTools inside our input as ::-moz-color-swatch
is). This border
is initially transparent
and then becomes visible when the input is focused — the pseudo-class used here (:-moz-focusring
) is pretty much an old Firefox version of the new standard (:focus-visible
), which is currently only supported by Chrome behind the Experimental Web Platform features flag.
Firefox: where the inner dotted rectangle on :focus
comes from. What about the blue border
? Well, it appears this one isn’t set by a stylesheet, but at an OS level instead. The good news is we can override all these styles should we choose to do so.
In Edge, we’re faced with a similar situation. Nothing happens when toggling the :focus
pseudo-class from DevTools, but if we actually tab to our input to focus it, we can see an inner dotted rectangle.
What happens in Edge when tabbing to our input to :focus
it. Even though I have no way of knowing for sure, I suspect that, just like in Firefox, this inner rectangle is due to a pseudo-element that becomes visible on :focus
.
:hover
In Chrome, toggling this pseudo-class doesn’t reveal any :hover
-specific styles in DevTools. Furthermore, actually hovering the input doesn’t appear to change anything visually. So it looks like Chrome really doesn’t have any :hover
-specific styles?
In Firefox, toggling the :hover
pseudo-class from DevTools reveals a new rule in the styles panel:
Firefox :hover
styling as seen in DevTools. When actually hovering the input, we see the background
turns light blue and the border
blue, so the first thought would be that light blue is the -moz-buttonhoverface
value and that the blue border
is again set at an OS level, just like in the :focus
case.
Firefox: computed background-color
of an
on :hover
. In Edge, toggling the :hover
pseudo-class from DevTools gives our input a light blue (rgb(166, 244, 255)
) background
and a blue (rgb(38, 160, 218)
) border
, whose exact values we can find in the Computed tab:
Edge: computed background-color
and border-color
of an
on :hover
. :active
Checking the :active
state in the Chrome DevTools does nothing visually and shows no specific rules in the Styles panel. However, if we actually click our input, we see that the background
gradient that doesn’t even show up in DevTools in the normal state gets reversed.
What the actual input looks like in Chrome in the :active
state. It appears to have a gradient (reversed from the normal state), in spite of the info we get from DevTools telling us it doesn’t. In Firefox DevTools, toggling the :active
state on does nothing, but if we also toggle the :hover
state on, then we get a rule set that changes the inline padding
(the block padding
is set to the same value of 0
it has in all other states), the border-style
and sets the background-color
back to our old friend ButtonFace
.
Firefox :active
styling as seen in DevTools. In practice, however, the only thing that matches the info we get from DevTools is the inline shift given by the change in logical padding
. The background
becomes a lighter blue than the :hover
state and the border
is blue. Both of these changes are probably happening at an OS level as well.
The computed background-color
and border-color
of an
on :active
viewed in Edge. This is the takeaway: if we want a consistent cross-browser results for
, we should define our own clearly distinguishable styles for all these states ourselves because, fortunately, almost all the browser defaults — except for the inner rectangle we get in Edge on :focus
— can be overridden.
The swatch wrapper This is a component we only see in Chrome, so if we want a cross-browser result, we should probably ensure it doesn’t affect the swatch inside — this means ensuring it has no margin
, border
, padding
or background
and that its dimensions equal those of the actual input’s content-box
.
In order to know whether we need to mess with these properties (and maybe others as a result) or not, let’s see what the browser defaults are for them.
Fortunately, we have no margin
or border
, so we don’t need to worry about these.
The margin
and border
values for the swatch wrapper in Chrome. We do however have a non-zero padding
(of 4px 2px
), so this is something we’ll need to zero out if we want to achieve a consistent cross-browser result.
The padding
values for the swatch wrapper in Chrome. The dimensions are both conveniently set to 100%
, which means we won’t need to mess with them.
The size values for the swatch wrapper in Chrome. Something we need to note here is that we have box-sizing
set to border-box
, so the padding
gets subtracted from the dimensions set on this wrapper.
The box model for the swatch wrapper in Chrome. The background
is set to transparent
, so that’s another property we don’t need to worry about resetting.
The background
values for the swatch wrapper in Chrome. There’s one more property set on this element that caught my attention: display
. It has a value of flex
, which means its children are flex items.
The display
value for the swatch wrapper in Chrome. The swatch This is a component we can style in Chrome and Firefox. Sadly, Edge doesn’t expose it to allow us to style it, so we cannot change properties we might want to, such as border
, border-radius
or box-shadow
.
The box-sizing
property is one we need to set explicitly if we plan on giving the swatch a border
or a padding
because its value is content-box
in Chrome, but border-box
in Firefox.
The box-sizing
values for the swatch viewed in Chrome (top) and Firefox (bottom). Fortunately, the font-size
is inherited from the input itself so it’s the same.
The font-size
values for the swatch viewed in Chrome (top) and Firefox (bottom). The margin
computes to 0
in both Chrome and Firefox.
The margin
values for the swatch viewed in Chrome (top) and Firefox (bottom). This is because most margins haven’t been set, so they end up being 0
which is the default for
elements. However, Firefox is setting the inline margins to
auto
and we’ll be getting to why that computes to
0
in just a little moment.
The inline margin
for the swatch being set to auto
in Firefox. The border
is solid 1px
in both browsers. The only thing that differs is the border-color
, which is rgb(119, 119, 119)
in Chrome and grey
(or rgb(128, 128, 128)
, so slightly lighter) in Firefox.
The border
values for the swatch viewed in Chrome (top) and Firefox (bottom). Note that the computed border-width
in Firefox (at least on Windows) depends on the OS zoom level, just as it is in the case of the actual input.
The padding
is luckily 0
in both Chrome and Firefox.
The padding
values for the swatch viewed in Chrome (top) and Firefox (bottom). The dimensions end up being exactly what we’d expect to find, assuming the swatch covers its parent’s entire content-box
.
The box model for the swatch viewed in Chrome (top) and Firefox (bottom). In Chrome, the swatch parent is the
wrapper we saw earlier, whose
content-box
is
4px
x
15px
. This is equal to the
margin-box
and the
border-box
of the swatch (which coincide as we have no
margin
). Since the
padding
is
0
, the
content-box
and the
padding-box
for the swatch are identical and, subtracting the
1px
border, we get dimensions that are
38px
x
13px
.
In Firefox, the swatch parent is the actual input, whose content-box
is 44px
x19px
one. This is equal to the margin-box
and the border-box
of the swatch (which coincide as we have no margin
). Since the padding
is 0
, the content-box
and the padding-box
for the swatch are identical and, subtracting the 1px
border, we get that their dimensions are 42px
x17px
.
In Firefox, we see that the swatch is made to cover its parent’s content-box
by having both its dimensions set to 100%
.
The size values for the swatch viewed in Chrome (top) and Firefox (bottom). This is the reason why the auto
value for the inline margin
computes to 0
.
But what about Chrome? We cannot see any actual dimensions being set. Well, this result is due to the flex
layout and the fact that the swatch is a flex item that’s made to stretch such that it covers its parent’s content-box
.
The flex
value for the swatch wrapper in Chrome. Final thoughts Phew, we covered a lot of ground here! While it may seem exhaustive to dig this deep into one specific element, this is the sort of exercise that illustrates how difficult cross-browser support can be. We have our own styles, user agent styles and operating system styles to traverse and some of those are always going to be what they are. But, as we discussed at the very top, this winds up being an accessibility issue at the end of the day, and something to really consider when it comes to implementing a practical, functional application of a color input.
Remember, a lot of this is ripe territory to reach out to browser vendors and let them know how they can update their implementations based on your reported use cases. Here are the three tickets I mentioned earlier where you can either chime in or reference to create a new ticket:
The post Color Inputs: A Deep Dive into Cross-Browser Differences appeared first on CSS-Tricks .