For example, we can match value of an attribute given we know the entire attribute name. For example, if I know there are elements with the foo
attribute, then I can find elements that have a foo
attribute starting with bar
:
<style>
[foo|=bar] { /* ... */ }
</style>
But what if I want to find element that have attribute starting with some
, so that I can match two of the following elements:
<div something="foo"></div> <!-- select this -->
<div some="bar"></div> <!-- select this -->
<div awesome="bar"></div> <!-- but not this -->
I would like to select both divs with the attributes starting with some
, but there’s no way to specify this.
Assume that we don’t know what the attribute values will be, they might be different depending on what the user is specifying via the attribute.
It would be neat if there was a way to match expressions against attribute names, not just values. Unless I missed it, I haven’t seen any way to do that, but I think it is a legitimate desire because all of HTML is just text, so why not be able to match more of it, not just attribute values?
One thing that Angular does is autogenerate attribute names from CSS classes, for example, something like compiling from
<style>
.component-name { /* ... */ }
</style>
<div class="component-name"></div>
to
<style>
[component-name-1234] { /* ... */ }
</style>
<div component-name-1234></div>
where 1234
is a collision-free generated identifier to ensure that the style matching is unique.
If you know the component’s name is component-name
, it is literally impossible for a parent component to style a child component because it is impossible to guess what the random ID is.
However, if attribute names were matchable against patterns, then a parent component could override child styles.
When using JSS, it mostly provides encapsulation by generating class names similarly to Angular, but it applies to class names (which are attribute values) rather than attribute names, so it is possible to override styling if absolutely needed.
For example, here’s how class names are generated with JSS:
const {classes} = jss.createStyleSheet({
fancyButton: {
background: "blue";
}
}).attach()
document.querySelector('.some-container').innerHTML = `
<button class="${classes.fancyButton}"></button>
`
then the class name given to the <button>
matches the generated clash-free class name that is inside the <style>
that is appended into the <head>
by JSS.
However, we can still override the style if necessary because we have the power of matching patterns against attribute values, and given that I know fancyButton
is converted into something like fancy-button-1234
in the output <style>
, I can write
<style>
[class|=fancy-button] { /* ... */ }
</style>
and I can override styles in there without having to know what the generated ID of the class name is.
There’s also other possible uses. Suppose I want to style all elements that have on*
attributes to define event handlers. If we had attribute name matching, then it would be easy. Suppose attribute name matching works similarly to value matching:
<style>
[^=on] { outlined: 1px solid red }
</style>
The ^=
symbol is leading, which means it is matching the following attribute name, and now I’ve outlined all elements that have inline event handlers.
It would be possible to also match the attribute value besides matching the attribute name. For example, I want to style all elements that have an inline event handler that calls the foo()
function
<style>
[^=on^="foo("] { outlined: 1px solid red }
</style>
And boom, they are all outlined!
Maybe ^=on
is not specific enough, or clashes with something else; we could select elements with mouse handlers of any sort:
<style>
[^=onmouse] { outlined: 1px solid red }
</style>
Let’s pick any element with data attributes:
<style>
[^="data-"] { outlined: 1px solid red }
</style>
Etc, I’m sure there’d be more interesting uses.