What Do /Deep/ and: :Shadow Mean in a CSS Selector

What does :host /deep/ selector mean?

It is used to allow styling child components when using emulated view encapsulation.

More about this can be found here:

https://angular.io/guide/component-styles

Btw /deep/ selector is now deprecated:

The shadow-piercing descendant combinator is deprecated and support is being removed from major browsers and tools. As such we plan to drop support in Angular (for all 3 of /deep/, >>> and ::ng-deep). Until then ::ng-deep should be preferred for a broader compatibility with the tools.

:host is used to address the hosting element - that is the one that you use to add the component somewhere (e.g. <app-component>).

Use the :host pseudo-class selector to target styles in the element that hosts the component (as opposed to targeting elements inside the component's template).

So the selector :host /deep/ .ui-autocomplete means "on current hosting element, go deep (search in child components too) and look for elements with class ui-autocomplete.

Here is some additional information about the view encapsulation feature:

https://blog.thoughtram.io/angular/2015/06/29/shadow-dom-strategies-in-angular2.html

What's the substitute for ::shadow and /deep/?

::shadow and /deep/ were removed for breaking encapsulation.

The substitutes are:

  • CSS variables.
    It already works natively with the recently launched Google Chrome 49. Read here:

    1. http://www.html5rocks.com/en/tutorials/webcomponents/shadowdom-201/
    2. https://developers.google.com/web/updates/2016/02/css-variables-why-should-you-care?hl=en
    3. http://blog.chromium.org/2016/02/chrome-49-beta-css-custom-properties.html
  • :host-context. Read here: http://www.html5rocks.com/en/tutorials/webcomponents/shadowdom-201/

The use of /deep/ and in Angular 2

  1. Is /deep/ here to stay? Do we have any source, a quote, or anything from any specification saying that it will be adopted? Or if it has officially been deprecated?

    The /deep/ syntax is obsolete, last seen in css-scoping in 2014, and its replacement >>> was deprecated about half a year ago in Chrome 45.

    The entire concept of the shadow-piercing descendant combinator is slated to be removed from the Shadow DOM entirely. Implementations may either remove it altogether or alias it to the regular descendant combinator (which depending on how the Shadow DOM is implemented in the future may or may not make sense).

  2. Can we suppress this error in Visual Studio Code without all-together disabling syntax checking?

    Unfortunately not.

    Angular allows both in emulated view encapsulation for compatibility purposes, but authors are strongly encouraged to use >>> going forward, since /deep/ is technically invalid now, and therefore unsupported in native view encapsulation.

CSS shadow dom : is there alternative to /deep selector?

How can I write the selector in the script to reach the .child element?

To reach an element in the Shadow DOM, you should use the shadowRoot property on the element.

var parent = document.querySelector( '#parent' )
var child = parent.shadowRoot.querySelector( '#child' )
child.classList.add( 'reached' )

Note : the Shadow DOM must have been created in the open mode.

var sh = parent.attachShadow( { mode: 'open' } )

var parent = document.querySelector( '#parent' )var sh = parent.attachShadow( { mode: 'open' } )sh.innerHTML = `<style>                    div.reached { color: green }                </style>                <div id="child">Child</div>                `var child = parent.shadowRoot.querySelector( '#child' )child.classList.add( 'reached' )
<div id="parent"></div>

Shadow Dom ::content css selector priority?

You don't actually need the /deep/ there if your div is coming from the light DOM.

I think you've got two selectors of equal importance: ::content div and .shadow div. One way to solve this would be to give your div a class, and let the overriding styles use that to boost their score.

ex: jsbin

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Polymer</title>
<script src="http://www.polymer-project.org/components/webcomponentsjs/webcomponents.js"></script>
<link rel="import" href="http://www.polymer-project.org/components/polymer/polymer.html">
<style>
.widget .special {
color: blue;
}
</style>
</head>
<body>

<polymer-element name="x-foo">
<template>
<style>
::content > div {
color: red;
}
</style>
<h1>Hello from x-foo</h1>
<content select="div"></content>
</template>
<script>
Polymer({

});
</script>
</polymer-element>

<x-foo class="widget">
<div class="special">Hello World</div>
</x-foo>

</body>
</html>

How and where to use ::ng-deep?

Usually /deep/ “shadow-piercing” combinator can be used to force a style down to child components. This selector had an alias >>> and now has another one called ::ng-deep.

since /deep/ combinator has been deprecated, it is recommended to use ::ng-deep

For example:

<div class="overview tab-pane" id="overview" role="tabpanel" [innerHTML]="project?.getContent( 'DETAILS')"></div>

and css

.overview {
::ng-deep {
p {
&:last-child {
margin-bottom: 0;
}
}
}
}

it will be applied to child components

What is the long-term alternative solutions to /deep/ OR ::ng-deep?

Currently there's no alternative right now, so we should all continue to use it, because it's practical.

When ViewEncapsulation.Native is properly supported by all browsers and supports styling across shadow DOM boundaries, ::ng-deep will probably be discontinued.

What is the ::content/::slotted pseudo-element and how does it work?

The ::content pseudo-element is being replaced in future implementations of Web Components / Shadow DOM with the ::slotted pseudo-element. Likewise, the element targeted by this pseudo-element has changed from <content to <slot> in the latest version of the Shadow DOM specification. You can see related discussion about that change here.

Currently browsers still support <content> and ::content.



Original answer:


Summary:

::content is essentially a way to dig deeper and style descendants of the ShadowHost, which normally aren't available to be styled, because your CSS doesn't know to look for the ShadowDOM fragment without ::content.


This answer assumes you are at least somewhat familiar with the <template> element and Web Components, specifically the ShadowDOM, which deals with ShadowTrees and their two main elements, ShadowHost and ShadowRoot.

Note - As of this writing, there is less than 50% support (even prefixed, off-by-default support) for Web Components across the five major browsers. While all modern browsers support <template>, only recent versions of Chrome and Opera support the ShadowDOM fully; with Firefox supporting parts of it after you toggle the requisite feature in about:config (dom.webcomponents.enabled) to true.

The goal of using the ShadowDOM is similar to MVC's separation of concerns. That is, we want to separate our content from our presentation and allow for encapsulated templates in our code to help make it more manageable. We have this already in various programming languages, but it's remained a problem for some time in HTML and CSS. Further, there can be conflicts with class names when styling elements in web apps.

Normally, we interact with the LightDOM (a sort of "Light Realm"), but sometimes it would be helpful to take advantage of encapsulation. Crossing into this sort of "Shadow Realm" (part of Web Components) is a new method to prevent the problems mentioned above by allowing encapsulation. Any styles applied to markup in your ShadowTree won't apply to markup outside of your ShadowTree, even if the exact same classes or selectors are used.

When the ShadowTree (which lives in the ShadowDOM) has a tree from the LightDOM distributed within it, and/or when the ShadowTree is rendered, the result is converted by the browser into what is called a composed tree.

When the browser renders your code, content is being distributed and inserted at new locations other than where it was physically typed. This distributed output is what you see (and what the browser sees), and is called the composed tree. In reality, the content is not originally typed in the order that it now appears, but you won't know this, and neither will the browser. This separation between "end result" and "original code", if you will, is one of the main benefits of encapsulation.

Web Components & the Future of CSS is a great 40-minute video on Web Components and specifically the ShadowDOM, pointed out to me by ZachSaucier.


Specific to your question, the ::content pseudo element applies to what are called distributed nodes. A distributed node is another term for whatever you put within the <content></content> tags. The content is distributed from its place in the original markup to wherever you have placed your <content> tags in the template.

So, when you need specificity in CSS, one way you can handle selectors normally is that you go to the parent element and add that in as part of the selector. Ex: if .container {} is not specific enough, you might use div .container {} or .main .container {} in order to make your selector work.

Thinking about the point of the ShadowDOM, which is scoping and encapsulation, you have to realize that this new ShadowTree you've created is a completely new (discrete) DOM fragment. It's not in the same "Light Realm" as the rest of your content; it's in a "Shadow Realm". So, how does the CSS know to target this "Shadow Realm"? By using the ::content pseudo-element!

The ::content pseudo-element selector acts as the parent element of distributed nodes.

HTML5Rocks has a great sequence of tutorials here, here, and here which cover more information and give some great examples (be sure to visit with Chrome or Opera until more browsers support these features).

For example, see this modified and improved (by Leo) version of the code from HTML5Rocks:

var div = document.querySelector('div');
var root = div.createShadowRoot();
var template = document.querySelector('template');

root.appendChild(template.content);
<template>
<style>
h3 { color: red; }
content[select="h3"]::content > h3 { color: green; }
::content section p { text-decoration: underline; }
</style>
<h3>Shadow DOM</h3>
<content select="h3"></content>
<content select="section"></content>
</template>

<div>
<h3>Light DOM</h3>
<section>
<div>I'm not underlined</div>
<p>I'm underlined in Shadow DOM!</p>
</section>
</div>

What does this symbol mean in CSS?

Universal selector *

  • *: What does "*" mean in CSS?

Combinators

  • Child >: What does the ">" (greater-than sign) CSS selector mean?
  • Following-sibling ~: What does the "~" (tilde/squiggle/twiddle) CSS selector mean?
  • Next-sibling +: What does the "+" (plus sign) CSS selector mean?
  • ~ vs +: Difference between CSS + selector and ~ selector

Pseudo-classes

  • :focus, :active: What is the difference between :focus and :active?
  • :root: What's the difference between CSS3's :root pseudo class and html?

Attribute selectors

  • [att|=val], [att^=val]: What is the difference between pipe (|) and caret (^) attribute selectors?

Namespaces

  • Namespace separator |: What does *|* this mean in CSS?
  • @namespace rule: What is the use of @namespace in CSS?

Shadow DOM

  • /deep/ combinator, ::shadow pseudo-element: What do /deep/ and ::shadow mean in a CSS selector?

Important declarations

  • !important: What are the implications of using "!important" in CSS?

Hacks

  • *: What does a star-preceded property mean in CSS?
  • :): What does the smiley face ":)" mean in CSS?


Related Topics



Leave a reply



Submit