Repository navigation
Description
I'm submitting a ... (check one with "x")
[ ] bug report => search github for a similar issue or PR before submitting
[*] feature request
[ ] support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question
Current behavior
Neither ::slotted(some-ng-content-projected-child) nor ::content doesn't have any effect.
Expected behavior
Current Shadow DOM specification (or W3C Working Draft) has defined "slot" (previously "content") tag, which "ng-content" tries to emulate. Styling slotted (or ng-contained...) components should be possible using ::slotted() selector.
Specs for ":slotted()":
https://drafts.csswg.org/css-scoping/#selectordef-slotted
An usage example taken from https://developers.google.com/web/fundamentals/primers/shadowdom/
Styling distributed nodes
::slotted(compound-selector) matches nodes that are distributed into a "slot".
Let’s say we’ve created a name badge component:
<name-badge> <h2>Eric Bidelman</h2> <span class="title"> Digital Jedi, <span class="company">Google</span> </span> </name-badge>The component’s shadow DOM can style the user’s "h2" and .title:
<style> ::slotted(h2) { margin: 0; font-weight: 300; color: red; } ::slotted(.title) { color: orange; } /* DOESN'T WORK (can only select top-level nodes). ::slotted(.company), ::slotted(.title .company) { text-transform: uppercase; } */ </style>
As of now, shimming is of course needed, since there is no native support for "slotted", at least not for most browsers.
Reproduction of the problem
You can find a plunker about the issue:
https://plnkr.co/edit/4rFsfL9HBY87cesDgN9P?p=preview
What is the motivation / use case for changing the behavior?
There are several probable use cases for this, including that clear example from developers.google.com Shadow DOM guide.
Most critical one is as I do see the issue, is that you have several native "components" (h1, tr, td) projected into your component using "ng-content" ("slot"), that act's as a custom container, such as in above "name-badge" example.
A specific example I have is that I do have a custom table-like component, and want to style contained "tr" elements accordingly. Eg. I would like to set all odd rows for that said table-like components to have a dark gray background, and all even rows to have a light yellow background. I honestly don't know how to handle that without using ::slotted() (or ::content) or alternatively ditch the ViewEncapsulation completely, which is not desired.
In addition to "slot" / "::slotted()", there is a partially overlapping feature of Shadow DOM style hooks, but support for that is also missing for Angular2: #10663
In previous Angular2 versions you were able to style derived ng-contents as expected, but that was considered a misbehavior and "fixed" for RC.5 or RC.6, as you can see from comments for closed bug #7400
With Shadow-piercing combinator ">>>" (previously "/deep/") being deprecated, "slotted" and Shadow DOM style hooks are the only remaining hope for non-insane way for styling contained native elements, without breaking the view encapsulation.
#5345 is also related to this issue.
Please tell us about your environment:
- Angular version: 2.0.0-rc.X
2.0.0.-rc.7 - Browser: [all | Chrome XX | Firefox XX | IE XX | Safari XX | Mobile Chrome XX | Android X.X Web Browser | iOS XX Safari | iOS XX UIWebView | iOS XX WKWebView ]
Chrome 52, Firefox 48, IE 11, Edge. All, I guess. - Language: [all | TypeScript X.X | ES6/7 | ES5]
all - Node (for AoT issues):
node --version=
Not relevant
Activity
tbosch commentedon Nov 5, 2016
Implementation hint:
ngprojected-<comp-id>to it::slottedto select elements with this attribute and the current component id.ovangle commentedon Nov 26, 2016
Does it make sense to use
::slottedif<slot>isn't supported when usingViewEncapsulation.Native?rvalimaki commentedon Nov 26, 2016
Oh well, all html tags got stripped in above comment. Let's try again:
I haven't used native view encapsulation, but
<ng-content>is an Angular2 spesific version of<host>tag, formerly known as<content>tag.For some reason, Angular2 team did choose to not rename the
<ng-content>to<ng-host>when the native<content>tag was renamed to<host>tag.ovangle commentedon Nov 28, 2016
@rvalimaki
Now that all the browser vendors have agreed to ship v1 of the shadow DOM api, it would make more sense if the angular api was updated to reflect it, rather than mangling the
::slottedselector to work with angular.It would be possible to deprecate
<ng-content>and associated classes gracefully in favour of<ng-slot>and to keep the/deep/combinator forng-contentas-is during the deprecation period.Named slots have a distinct advantage over ng-content in angular anyway, since
ContentChild(string)selects by template reference variable, but<ng-content>selects by css selector. If<ng-slot>was used, the template reference variable would determine the named slot into which the component/element should be distributed.rvalimaki commentedon Nov 28, 2016
@ovangle
Fair enough. But I'd say then Angular2 should support
::contentselector with<ng-content>until the change. For a developer perspective, I'd rather haver either working::contentor::slotted, but the current situation is when we lack support for both of the ways is not that good.Given that it's already said so that
/deep/or>>>is already deprecated and will be totally removed in the future without any other feature that could even remotely replace it, I do not continue using that way. Sadly, as current status of affairs is as it is, we had to fall back to usingViewEncapsulation.Nonefor all generic container type components. I'd say that's about 5-10% of all our components we use, so probably that's not that big issue.titusfx commentedon Jul 12, 2017
I was redirected from here. And I can't find the solution.
How can I do an equivalent of
.some-class > * { /*styles*/}where the child of.som-classis an<ng-content>( where? )
ericmartinezr commentedon Jul 12, 2017
#17677
rvalimaki commentedon Jul 21, 2017
@ericmartinezr
While that feature supporting ::ng-deep is something, it's kind of a step backwards, as it's already deprecated when released and will be removed in the future. Also browsers will not include such or similar functionality in the future at all, though they do include the "lite-version" of that functionality using the ::slotted(), as described in this bug report.
robwormald commentedon Sep 15, 2018
Shadow DOM V1 support is in, so
::slottedis now supported natively.rvalimaki commentedon Sep 15, 2018
@robwormald:
Excellent news that .Native ::slotted() is now supported.
What about implementinh ::slotted() also for ViewEncapsulation.Emulated so that emulation would be more 1:1?
zoechi commentedon Sep 15, 2018
Shouldn't
ViewEncapsulation.Emulatedjust be deprecated now that all browsers supportNative?emilio-martinez commentedon Sep 16, 2018
@zoechi Shadow Dom v1 isn't supported at all in IE and Edge, hasn't reached stable on Firefox, and seems to be buggy in Safari (https://caniuse.com/#feat=shadowdomv1), so the support is definitely not there yet.
Regardless, I think even if it did, the usefulness of Emulated encapsulation would not be obviated; for example, Shadow Dom doesn't have a standard way of being serialized yet, so Emulated would still be helpful when paired with SSR
oliverjanik commentedon Oct 9, 2018
@robwormald Can you stop closing unresolved issues?
The title clearly states ::slotted support for ViewEncapsulation.Emulated and that does not work.
cyraid commentedon Oct 10, 2018
So it being closed, it means I can use ::slotted instead of ::ng-deep?
rvalimaki commentedon Oct 12, 2018
@oliverjanik @cyraid
::slotted is now partially implemented, when using ViewEncapsulation.Native, but not with ViewEncapsulation.Emulated.
What I did request in original request was implementation for both .Native (fixed) and .Emulated (not fixed). As I thought we could use .Emulated until everything works perfectly in .Native, and then finally migrate to .Native, the whole idea being .Emulated emulating .Native as closely as possible to make such migration possible.
We already abandoned the idea of using ::slotted as there was not going to be quick fix for the issue, and started using ViewEncapsulation.None for most of our "container type" components. Obviously that sucks a bit more than a bit, but works to some degree. ::slotted support itself is a dumbed down version of ::ng-deep, but that's beyond Angular team, as that's how web standards ended up and they say they had good performance etc. related reasons for that.
Heads up @robwormald
angular-automatic-lock-bot commentedon Sep 14, 2019
This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.
Read more about our automatic conversation locking policy.
This action has been performed automatically by a bot.