guest@mukunda.com:/blog# ./cat 2023/getting-around-existing-css-for-overlays.txt
Name: Getting Around Existing CSS for Overlays
Date: Jan 22, 2023
Despite starting my CSS adventures probably two decades ago,
I'd never heard about "specificity" until now. I figured CSS
just did things top-down. That makes sense to me, and I
don't see why specificity was ever implemented to begin
with. What we get are side effects that make it hard to put
two separate components together. On top of that odd rule,
there is no easy way to undo element-level styles.
Say a site has this CSS:
h1 {
font: stupid;
}
You have an overlay injected onto the site. You figure that
this should do the trick to undo any styles:
#overlay-panel {
all: initial;
...
}
However, it doesn't. If you have:
<div id="overlay-panel">
<h1>Title</h1>
</div>
It is going to render in the stupid font, because the h1
rule is targeting any plain h1 specifically, so that h1 will
not inherit from our initial rule.
To get around this is VERY tedious. It would be quite
convenient if there was a CSS "barrier" feature that we
could use to block any previous stylesheets.
This is what I ended up doing (after some trial and error of
many approaches!):
First, I keep everything in a unique selector, as to avoid
touching anything on the underlying site. This sets up our
base styles that will be inherited by subelements.
#mypanel {...}
Next, I use a wildcard "revert" style for everything. Revert
should cause inheritance for properties that inherit
(inheriting from the base properties that I defined, and not
what the underlying site defined), and otherwise reset any
other properties.
#mypanel * { all: revert }
However, we can't just do this, since it breaks some
features. For example, with SVG, it overrides properties
that are introduced by element attributes. Same for
"contenteditable".
To get around the SVG problem, I excluded all SVG elements
from the rule. If a site is styling SVG directly, it will
cause problems, but I'm not going to care about that case.
@namespace svg "http://www.w3.org/2000/svg";
#mypanel *:not(svg|*) { all: revert }
For contenteditable, I just reintroduced the properties that
it overwrites. I don't actually see why this rule should be
overwriting "attribute" styles (which I figured would have a
high specificity), but this is the hand we're dealt, I
guess.
#mypanel div[contenteditable] {
-webkit-user-modify: read-write;
overflow-wrap: break-word;
-webkit-line-break: after-white-space;
}
This is pretty ugly to me, working with implementation-
specific properties like that, but I don't see any other
choice.
If anyone has a better way to create a barrier between a
site and extension elements, I'm interested in hearing your
approach.
Send the author a comment
<< Index