What is a Shadow DOM (shadow tree) According to Mozilla Developer Network (MDN), a shadow tree is a tree of DOM nodes whose topmost node is a shadow root; that is, the topmost node within a shadow DOM. A shadow tree is a hidden set of standard DOM nodes which is attached to a standard DOM node that serves as a host. The hidden nodes are not directly visible using regular DOM functionality, but require the use of a special Shadow DOM API to access. Since the latest version of you can make special components called shadowed components. QCObjects What is a Shadowed Component A shadowed component is a QCObjects Component definition that you can extend to allow the content of your component to be shadowed in the browser. By the moment, QCObjects is only supporting the mode "open" for shadowed components. If you're not familiar yet with the concept of shadow root, shadow DOM or shadow tree, I highly recommend you to read this article of MDN about . Using the Shadow DOM Differences between a Shadowed Component and a Lightning Component A Lightning Component is no other thing that the same component that you're actually familiar with. On the image above, the component has a normal content, called a light DOM. This content is following the same CSS rules and scope that the rest of the document, and as a consequence, the rest of the web app. When you inject a style css rule into the content of this component, this rule will be added in runtime to the document, but it will also override any other rule that maches a conflict. This is useful most of the times, but a mess in particular others. For that particular times when you need to enclose the CSS and markup scope you got to use shadow DOM for content injection in a component. Shadow DOM is local to the component and defines its internal structure, scoped CSS, and encapsulates your implementation details. It can also define how to render markup that's authored by the consumer of your component. The above image is showing a card component that is filled up with shadowed content. To make it easy to handle when and where to put the shadow content, QCObjects has . Shadowed Components Creating Shadowed Component You have two ways to make a shadowed component in QCObjects. The first one, is to declare a component Class definition and use it in the component tag declaration. Class( ,Component,{ : , shadowed: , : , :{} }) // in your components package 'ShadowedCardComponent' name 'card' /* If shadowed is true, the DOM will be shadowed, default is false */ true cached false data In the above definition, you can use the hidden static property to let QCObjects to know it has to shadow the DOM of the component body. shadowed Then, you are able to use this definition into your html component tag, like this: <!-- in your html layout file --> < = > component componentClass "ShadowedCardComponent" </ > component If you don't want to spend a special Class definition for your component, the second option is to set an attribute straight in the component tag declaration. < = = > component name "card" shadowed "true" </ > component Both ways get the same result, the component is built with shadowed DOM, and the styles into it will not follow the global css rules, and the markup inside will have an independent structure. Make sure your shadowed components are only used when needed, and you are not needing to depend on any other lighting component content to make your shadowed components visible and available, as they are completely independent. Also, it is not recommended to use lighting subcomponents into shadowed components, as the purpose of lighting components is to be absolutely available to be injected everywhere and to be interfered by external behaviours, and it is not the same purpose for shadowed components, whose are meant to be restricting the global behaviour in some ways. Both, lighting components and shadowed components are accesible from the global components stack, the main difference is that in the instance of every shadowed component will be a new hidden property (readonly) called , that is replacing the behaviour of the body, now, if you have any elements to add to the component content, you need to use instead of shadowedRoot componentInstance.shadowRoot.appendChild(element) componentInstance.body.append(element) Composition and slots In simple and easy words, is when you dynamically place elements of an object instance into blocks defined on its inherited instance. The resulting composed object instance will be mutating its behaviour as a result of the dynamic blocks mixing. Composition The shadow DOM is a hidden tree, that is allocated in a private scope, and it is populating its content to the light DOM, that is visible and accesible from the global scope. You can place light DOM elements over the shadow DOM elements, mutating the behaviour of the final flattened tree. This is called shadow DOM composition. Light DOM vs Shadow DOM The flattened DOM tree is the content that you can view opening dev tools in your browser. The flattened DOM tree of a Light DOM inside a QCObjects component will be like this: Card Title Card Description < = > component name "card" <!-- this content is generated by templates/components/card.tpl.html file --> < = > div class "card" < = = = > img src "img/avatar.png" alt "Avatar" style "width:100%" < = > div class "container" < > h4 < > b </ > b </ > h4 < > p </ > p </ > div </ > div </ > component On the other hand, a flattened DOM tree of a shadowed component with the exact same template content will be like this: #shadow-root Card Title Card Description < = = > component name "card" shadowed "true" <!-- this content is generated by templates/components/card.tpl.html file --> < = > div class "shadowHost" < = > div class "card" < = = = > img src "img/avatar.png" alt "Avatar" style "width:100%" < = > div class "container" < > h4 < > b </ > b </ > h4 < > p </ > p </ > div </ > div </ > div </ > component In this case, a light component was added dynamically to enclose the shadow DOM, this is always done by QCObjects in order to asure there will be no restrictions by the HTML spec over the different browsers that support shadow DOM. <div> The <slot> element Following the rules of the shadow DOM composition, we can go further defining some slots (a good additional example of the use of slots is in the MDN ). here <!-- file: templates/components/card.tpl.html --> < = > div class "card" < = = = > img src "img/avatar.png" alt "Avatar" style "width:100%" < = > div class "container" < > h4 < = > slot name "card_title" </ > slot </ > h4 < = > slot name "card_description" </ > slot </ > div </ > div And Omg! this is becoming a bit more interesting... Card Title Card Description <!-- file: main-layout.html or wherever you want to place your component --> < = = > component name "card" shadowed "true" < = > b slot "card_title" </ > b < = > p slot "card_description" </ > p </ > component In a shadowed component, you can override the content of the elements using custom blocks. slot And the resulting flattened DOM tree will be like this: #shadow-root Card Title Card Description <!-- file: main-layout.html or wherever you want to place your component --> < = = > component name "card" shadowed "true" <!-- this content is generated by templates/components/card.tpl.html file --> < = > div class "shadowHost" < = > div class "card" < = = = > img src "img/avatar.png" alt "Avatar" style "width:100%" < = > div class "container" < > h4 < = > b slot "card_title" </ > b </ > h4 < = > p slot "card_description" </ > p </ > div </ > div </ > div </ > component And yes, you should be able to use data injectors too: {{title}} {{description}} <!-- file: main-layout.html or wherever you want to place your component --> < = = > component name "card" shadowed "true" < = > b slot "card_title" </ > b < = > p slot "card_description" </ > p </ > component Styling In-line context based styles for shadowed components For shadowed components, it is recommended to place your style rules into the dynamic template file, commonly named with the extension , so the styles will be enabled only for the scope of the shadowed component. You can reference the main element of the shadowed DOM by using element in your style declaration, like this: tpl.html :host <!-- file: templates/components/card.tpl.html --> < > style { : block; } @ url( ); :host display /* Also you can import styles from another css file */ import "./css/components/card.css" </ > style < = > div class "card" < = = = > img src "img/avatar.png" alt "Avatar" style "width:100%" < = > div class "container" < > h4 < = > slot name "card_title" </ > slot </ > h4 < = > slot name "card_description" </ > slot </ > div </ > div Enjoy coding! Previously published at https://devblog.qcobjects.org/shadowed-components-ck94xiira00e7s3s1os7bq7is