问题
This question likely has no single direct answer, but hopefully will lead to some best practices or common patterns to use when adapting an existing styles framework to new web component development.
For my case, I have a component <custom-avatar>
, and it's all set up properly with self-contained styles and functionality, everything is just peachy.
In certain use cases, the application display needs to stack avatars, just one slightly overtop one other at a diagonal, and the pattern I'm following is using a simple component <custom-composite-avatar>
. All this does is wrap the slotted content in a <div>
with the correct styling class, but key aspect is retaining the composability for flexible re-use, like so:
<custom-composite-avatar>
<custom-avatar title="first"></custom-avatar>
<custom-avatar title="second"></custom-avatar>
</custom-composite-avatar>
The tricky bit lies in the styles, which are imported from a monorepo that provides the same BEM-ish CSS and component CSS modules to other flavors of the component library like React, Vue, etc. I have the avatar
and composite-avatar
styles imported just fine, but forcing the intended overlap display is defined with the hierarchical selector .my-composite-avatar.my-composite-avatar--medium .my-avatar {}
So with .my-composite-avatar
class applied to the div wrapper within <custom-composite-avatar>
and the .my-avatar
class applied to the wrapper within the <custom-avatar>
and it's own Shadow DOM, that parent/child CSS selector is no good.
I doubt there is a silver bullet for this, but this seems like it will be a rather common scenario as more people migrate to Web Components while using existing styling systems. What approach makes the most sense to ensure that the composite component remains composable, and adaptation of existing selectors pain-free (or at least easy to communicate to other devs)? can this be solved with ::host
or ::slotted
, or will these cases require significant re-work?
Thanks for reading, your ideas are appreciated!
回答1:
I would advice to become good friends with CSS properties
because they trickle down into shadowDOMs following CSS selectors.
- CSS Custom Properties(variables)
- and getPropertyValue
- and setProperty if you want to be brutal and make Custom Elements change the outside world.
example
I have an <SVG-ICON>
element taking configuration from attributes OR CSS properties
with my favorite lines of code (from this component):
let val = this.getAttribute(attr)
||
getComputedStyle(this)
.getPropertyValue("--svg-icon-" + attr)
.replace(/"/g, "")
.trim();
Allows for your standard attribute configuration:
<svg-icon name="configuration" fill="grey"></svg-icon>
But more powerful (simplified example):
<style>
body {
--svg-icon-fill: "grey";
}
svg-icon[selected] {
--svg-icon-fill: "green";
}
</style>
<svg-icon name="messages" selected></svg-icon>
<svg-icon name="configuration"></svg-icon>
CSS = Custom String Scripting
It doesn't often happen, but sometimes the simplest code makes me very happy.
There is no Styling restriction!
These 2 lines allow any String you want in CSS properties:
.replace(/"/g, "")
.trim();
Example
<style>
[name*="globe"] {
--svg-icon-tile: "rect:0,0,24,24,0,fill='blue'";
--svg-icon-stroke: white;
}
</style>
<svg-icon name="feather-icons-globe"></svg-icon>
The --svg-icon-tile
has nothing to do with CSS, it is read (and parsed) by the <SVG-ICON>
connectedCallback()
code to generate a SVG background/tile for all icons named globe.
The double-quotes aren't required, but without them your IDE will complain about invalid CSS.
Have fun coding... you will pull some hairs when you start with calc() in your CSS properties...
But you can take 'CSS' to another level.
PS.
And monitor the future of ConstructAble StyleSheets aka ConstructIble StyleSheets aka Constructed Sheets aka AdoptedStyleSheets:
https://developers.google.com/web/updates/2019/02/constructable-stylesheets
https://chromestatus.com/feature/5394843094220800
来源:https://stackoverflow.com/questions/61327555/using-existing-css-selectors-to-apply-styles-across-the-shadow-dom-to-custom-ele