What colour is that iframe?
I have a colleague who has been insisting lately that that the <iframe>
element was a mistake and should be deprecated. After recent adventures, I’m more pursuaded than ever (which is to say, not very pursuaded at all, but still, he has a point).
Mixing <iframe>
s and support for dark mode creates a real tangle of a web and it’s something we came across recently when we discovered some of our Datawrapper embeds were getting an unexpected off-black background in some browsers.
What we want, and were expecting, is for the <iframe>
background to be transparent so the embedding page’s background colour can shine through. But after reading through the documentation, some other explanations, and the trials and tribulations of others facing similar challenges, I didn’t feel that much closer to a solution.
It appeared as though the browser was applying a default background colour which we couldn’t control or remove without modifying the embedded document (which we couldn’t do easily since we didn’t control it).
Where is that opaque background coming from?
What it took me too long to figure out is that the default canvas background colour is applied to <iframe>
documents (not the <iframe>
element, but the page being embedded) by browsers only when there is a colour scheme mismatch. Presumably this is in the spec and I had just failed to understand what I was reading, but the first I actually saw it was burried deep in a comment thread on the W3C CSSWG drafts GitHub repository.
If the color scheme of an iframe differs from embedding document iframe gets an opaque canvas bg appropriate to its color scheme
To understand this better it helps to know1 how browsers determine the color-scheme
of a document. It seems to work something like this:
- Is there any information about what colour schemes the document supports (meta tag or CSS)? This will likely either be
light
,dark
, or both, or it won’t exist. - In the case of expressed support for a single
light
ordark
— use that scheme. - If support for both
light
anddark
is expressed, check the user’s preference (which defaults tolight
if there isn’t one) and use that. - If no support is expressed, default to
light
and use that2.
The browser does this for both the embedded document and the document (or element) in which it is embedded. Once the calculated scheme of each frame is known, we can know the default background colour of the embed’s canvas.
parent | iframe | default iframe document background |
---|---|---|
light |
light |
transparent |
light |
dark |
browser’s dark scheme default background colour |
dark |
light |
browser’s light scheme default background colour |
dark |
dark |
transparent |
There are a lot of combinations to think about and you can see how they all work on this demo page.
Element colour schemes
Another thing I’d failed to appreciate is that it’s possible to define the supported colour schemes on individual elements. So, for example, in a page which only supports a light
colour scheme, you could tell the browser that a specific element on that page only supports a dark
scheme.
This turned out to be the key to solving our particular problem.
We had a page that only supported a light colour scheme, but has a section with dark styling. Within that darkly styled section we wanted to embed an <iframe>
that only supports dark mode.
In this scenario, you end up with an opaque background colour on the embed because the document colour schemes don’t match. Unfortunately, the default dark background colour didn’t match the dark background colour of our darkly styled section.
To fix it, mark the specific section as only supporting a dark colour scheme:
.dark-section {
color-scheme: dark;
}
Hey presto, a transparent background!
Demo and testing
To help figure this all out, I created a demo page to have a play around with how browsers behave when embedding documents with different combinations of colour scheme support.
You can have a play yourself and use browser tools to simulate different user colour scheme preferences. But a word of warning: as of early 2023 these browser devtools appear to be a bit buggy and you need to refresh the page each time you switch colour scheme preference to be sure you’re seeing the correct result.
- I don’t actually know this is how it works. If you do know how it works — especially if I’ve got it wrong in material ways — I’d love to know about it.↩
- This might be further complicated by silly browser preferences like forced dark mode.↩