fix(viewer): restore sender colours in dark mode - #949
Open
shukiv wants to merge 1 commit into
Open
Conversation
Dark mode inverts the message body and then re-inverts colour containers so they come back to what the sender designed. Two rules stopped that second step happening on ordinary mail. The nested-container rule treats any colour container inside another as already correct. It never excluded body, and a mail whose own body carries a background — `body style="background:#fff"`, which is standard in transactional templates — therefore made every container in the message count as nested. Nothing was re-inverted and the whole email stayed inverted: white bodies rendering black. Colour containers wrapping media were skipped outright, which left the container's own colour inverted. A navy header band with a logo in it rendered pale blue. Re-invert it and cancel the per-image rule inside instead, which is what the background-image branch alongside it already does, and gives the image the same net treatment while restoring the band. The cancel needs a real attribute selector, not :where(), or the bare `img` rule outweighs it. Confirmed against a real message in a browser, reading computed styles before and after: the header band and body both went from filter "none" to being re-inverted, and the logo from a double transform to one.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
In dark mode, ordinary HTML mail comes out with the sender's colours wrong: a navy header band renders pale blue, a white message body renders black. Reported against a standard transactional template.
Cause
The dark-mode CSS inverts the body and then re-inverts colour containers so they return to what the sender designed. Two rules stopped that second step from happening.
1.
bodywas not excluded from the nested-container rule.A mail whose own body carries a background —
<body style="margin:0;padding:0;background:#fff;">, which is standard in transactional templates — makes every colour container in the message a descendant of a colour container. All of them getfilter: none, nothing is re-inverted, and the entire email stays inverted. That is the white-body-renders-black half.2. Colour containers wrapping media were skipped entirely.
The
:not(:has(img, video, …))guard means a header band containing a logo never gets re-inverted, so the band keeps the body's inversion. That is the navy-renders-pale-blue half.Change
Exclude
bodyfrom being an ancestor in the nested rule (and from the re-invert itself — it is already inverted by the rule above, so it must not flip back).Re-invert colour containers even when they wrap media, and cancel the per-image rule inside them — exactly what the
background-imagebranch immediately below already does. The image ends up with the same net treatment as before, while the container's colour is restored.That cancel needs a real attribute selector rather than
:where()::where()contributes no specificity, so a:where(…) :where(img)form loses to the bareimg { filter: … }rule and silently does nothing.Verification
Reproduced the exact markup from the reported message in a browser and read computed styles, before and after:
background:+ logo)noneinvert(1) hue-rotate(180deg)background:#ffffff)noneinvert(1) hue-rotate(180deg)<img>Rendering matches: navy band, white body, both restored.
tsc --noEmitclean;components/emailpasses (129 tests). Running on a production instance.Not addressed
Colours still do not round-trip perfectly through two
invert() hue-rotate()passes —hue-rotateis a linear approximation, so a saturated yellow logo comes back slightly warm. That is inherent to the technique rather than to these selectors, and this change does not make it worse: the image goes through two transforms either way.