-
Notifications
You must be signed in to change notification settings - Fork 27.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
"Shadow CSS" babel transformation #249
Comments
Actually I just realized that it'll be much faster to use an approach for prefixing the CSS that does not involve parsing and creating an AST. Something like what buble does for ES6 |
Could you make the "component-name" the tag name rather than a class? So the output would look something like: <head>
<style id="component-name-styles">component-name p { color: red }</style>
</head>
<component-name>
<p></p>
</component-name> You shouldn't need any runtime prefixers too this way ( If you want to do more than prefix (upper bound isolation) and instead transform each rule set to a specific class ( |
The idea of the component name prefix is to prevent collisions. Tag name is In fact I think the best would be {package.name}{component_name}_tag On Wed, Nov 16, 2016 at 2:56 PM Pedram Emrouznejad notifications@github.com
|
Something about this smells funny. Why not go all-in on Shadow DOM and not have to worry about classnames? |
It's still not clear to me how to server-render shadow CSS (and what the backwards compatibility story is) |
It all comes down to this (h/t @treshugart for letting me know) tl;DR there's no proposal yet for how this could be done, but there's preliminary interest. But I'm trying to think ahead. Even if a proposal is made, submitted, discussed, approved and rolled out in early-adopting Chrome, we'll need a fallback. The best fallback I can think of for style isolation is described in the OP. |
Sorry wasn't very clear: I agree with component name prefixing. It's just a little easier to generate the fallback CSS and nicer when the component name prefix is the
As far as I can tell, what you proposed won't solve this. Try running through a more complicated example: What would the output be if instead of |
Why not just keep the selectors as-is and bump their specificity of +0010 by adding a unique identifier class? .foo {}
#hello {}
p a {}
h1 #foo [href] {}
* {} becomes /* ._aB1bC is unique for each component */
.foo._aB1bC {}
#hello._aB1bC {}
p._aB1bC a._aB1bC {}
h1._aB1bC #foo._aB1bC [href]._aB1bC {}
*._aB1bC {} The css part is pretty straightforward, maybe patching the "dom" i.e. adding the class to each element is a bit more tricky but definitely doable. To style the "shadow dom" from outside then we can provide the user with an helper that will patch its styles by adding the same class name: <style for="Component">
#hello { color: red }
</style> becomes <style>
._aB1bC-ext #hello._aB1bC {} { color: red }
</style> Also should work for external files <link rel="stylesheet" href="..." for="Component"> CSS as annotation? /* @shadow^Component */
#hello {}
/* @shadow$ */
/* or */
/* <style for="Component"> */
#hello {}
/* </style> */ |
one thing to note is that <css>
p { color: red }
</css> is invalid jsx, since <css>{`
p { color: red }
`}</css> |
Great point. Still much better than the dangerous html attr 😇 On Tue, Nov 22, 2016 at 5:05 AM Sunil Pai notifications@github.com wrote:
|
Just gonna leave this here: https://twitter.com/kevinSuttle/status/791326383234543618 :) |
Polymer has separated out its shady dom css shimmer as a standalone lib: https://github.com/webcomponents/shadycss The way that works is to prefix all nodes within the shadow tree with an element instance prefix ( |
@ebidel this is an hack but wouldn't it be enough to render the entire page/app/root component into shadow dom? edit: I am referring to the use-case described above, where anything would use this pseudo-ShadowDOM. Obviously it is not possible with mixed DOM unless as you said we use native shadow dom. |
@giuseppeg something like https://github.com/Polymer/shop/blob/master/index.html#L55? Yea, I suppose that could work, but it would require authors to use that pattern or a build/runtime solution to move things around :\ There would potentially still be main page styles that could leak into the app/root component. |
@pemrouz what's the problem with |
@pemrouz keep in mind that this technique involves a runtime classname prefixer as well, to support dynamic expressions |
If you're talking about recursive nested components of the same kind, that'd be a collision, but since the styles are likely to be the same, probably not an issue. We never ran into that though |
@rauchg I guess that converting selectors to classes can result in specificity bugs |
By the way in conversation with @pemrouz we realized that we can avoid the class conversion step by adding an attribute to every node, and then rewriting the selectors to always target that attribute in addition to tag/class. I think that addresses most problems! |
@rauchg yeah that's what I was suggesting a few comments ago. |
Hrmm, I guess that might work actually! :) I don't imagine there should be much runtime overhead either 👍. Wonder what Polymer folk think about this approach @ebidel @addyosmani? Specifically if it can be genericized to work independently of next? I guess this kinda works particularly well for you because of the templating layer (JSX), although this approach could definitely work separately too. For recursive components, you're right. Probably shouldn't matter if they are the same component. But if you needed to, you could include an instance number in the prefix. But then just need to be conscious the styles tags in your head don't spiral out of control if you're creating a lot components. Probably best to avoid doing this until someone complains. Few other points discussed offline further with @rauchg:
|
@ebidel explained that this is in fact how the Shady DOM CSS shimmer works.
Imho anything should be suffixed with an unique class name, see my example.
This would be awesome! Do you think that it is possible to split the transpilation in two phases? The first one being patching the styles and returning some metadata with the unique stylesheet id (like CSS Modules do with classnames). Then use those info to apply the given stylesheet id as classname to each html tag in the scope. The benefit of splitting the transpilation in two phases is that we can have implementations of the second one in many languages I guess 🎉 |
I have an example in the works that's independent of Next. It'll work similarly to glamor or any other React-oriented styling system |
Sincere apologies @giuseppeg, missed your post 😞. What you posted was definitely based on the same concept..
I believe he confirmed my initial thoughts that lower bound encapsulation is not possible (see "There's nothing that prevents upper-bound bleed-in"). Which is also why I'm more curious as to what they think of this approach..
Definitely, styles can and should be transformed AOT.
Looking forward to this 👍 |
Done as a separate module |
When we land #26 and #21, it'll be interesting to explore a transformation that takes something like:
into
Some notes on the transpilation process:
Once browsers add support for server-rendered shadow CSS (#22), this is a transformation that would only be necessary for legacy browsers
The text was updated successfully, but these errors were encountered: