What is the best way to target the shadow DOM host element specifically when it is the last child in the selection?

I want to style the shadow DOM host element as the last child.

In this particular situation, they are currently all green. I would like them to be all red, with the exception of the final one.

class MyCustomElement extends HTMLElement {
  constructor(){
    super();
    this.attachShadow({mode: 'open'});
    this.shadowRoot.innerHTML = `
      <h5>Element:</h5>
      <slot></slot>
      <style>
        :host {
          color: red;
        }
        :host-context(:last-child) {
          color: green;
        }
      </style>
     `;
  }
}
window.customElements.define('my-custom-element', MyCustomElement);
<div>
  <my-custom-element>first</my-cutom-element>
  <my-custom-element>... more elements</my-cutom-element>
  <my-custom-element>last</my-cutom-element>
</div>

Currently, they are all displaying as green. I desire for only the final one to appear in green.

I have experimented with :host:last-child, but it does not produce the desired result. Additionally, using

:host-context(my-custom-element:last-child)
causes all elements to turn green.

Answer №1

Refer to my previous answer for some helpful tips: Utilizing CSS selectors like :first-child within shadow DOM

Your elements will remain hidden in lightDOM!
Any global styles you apply will be reflected in the shadowDOM.

customElements.define('my-custom-element', class extends HTMLElement {
  constructor(){
    super()
      .attachShadow({mode: 'open'})
      .innerHTML = `<slot></slot><style>:host { color: red; }</style>`;
  }
});
<div>
  <my-custom-element>first</my-custom-element>
  <my-custom-element>... more elements</my-custom-element>
  <my-custom-element>last</my-custom-element>
</div>

<style>
   div my-custom-element:last-child {
        padding:    .5em;
        background: green;
   }
</style>

Additional Notes:

  • super() returns 'this' (the element itself), allowing you to chain methods on it

  • attachShadow returns this.shadowRoot, enabling you to chain methods on it

  • The :host-context selector may not be supported by FireFox and Safari
    see: :host-context not working as expected in Lit-Element web component



Regarding the comment:

This may be the correct solution, but it can be disappointing. The purpose of the shadow DOM was supposed to be self-contained, so having to use global styles to style elements within the shadow DOM doesn't seem ideal. It's no surprise people turn to frameworks like React and Vue when web standards are lacking.

Consider this perspective: if your my-custom-element were <p> elements, how would a <p> know it is inside the last-child... only by referencing its parent container.

No wonder people turn to frameworks like React and Vue when web standards are lacking.

All Frameworks operate similarly, wrapping content in containers (be it in regular DOM, shadowDOM, virtual DOM)

A more accurate statement: Frameworks frame your content in containers.. always

The Native W3C standard Custom Element API grants 100% control over utilizing a container or not.

Yes, this means you must do some scripting before enjoying the benefits.

You have complete freedom in crafting components as you wish.

React adds 48 KB (GZipped) to your download, along with build processes and compatibility issues with other frameworks. Additionally, it no longer conforms to the ES standard.

Crafting an additional Custom Element takes about 15 minutes and approximately 200 bytes

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

I'm noticing that my Tailwind styles don't take effect until I redefine them. What could be causing

My Tailwind classes are giving me trouble. I faced an issue when I created a new component in the directory and placed my Button component there. Whenever I restart the project in terminal, the styles do not apply to my button unless I manually define th ...

Photo displayed above the carousel using Bootstrap

I'm currently in the process of building a website using the template found at . However, I'm having trouble placing an image in the center of the carousel, above the slides. Here is the code snippet I have tried so far: <div style="positi ...

Unusual actions observed with that particular button

Currently, I am working on creating a pomodoro clock using Codepen. While I acknowledge that my code isn't flawless yet, I have encountered a peculiar behavior with the Start button. When I click on it once, the timer starts as expected. However, if I ...

The "Open in new tab" feature seems to be missing for links when using Safari on iOS

My webapp contains links structured like this: <a href="/articles/">Articles</a> I am using JavaScript to control these links within my app: $(document).on("click", 'a', function(ev) { ev.preventDefault(); ev.stopPropagat ...

Leveraging split and map functions within JSX code

const array = ['name', 'contact number'] const Application = () => ( <div style={styles}> Unable to display Add name & contact, encountering issues with splitting the array). </div> ); I'm facing difficul ...

Is it possible to share data from one controller in a JS file to another JS file? (using AngularJS)

I need to create a table in JavaScript. In one of my JS files, I have a controller with JSON data containing properties like width, height, color, etc. In another JS file, I am building the actual table structure. Here is an example of my AngularJS file: ...

Verifying Angular (2+?) Compatibility: Opening and Closing Material mat-menu on Hover [GUIDE]

After extensive research, I tried various methods to hover a material menu to display its options. However, the solutions I came across were either too complicated or ineffective. Therefore, I decided to develop my own solution by combining elements of e ...

The JQuery function .load() is not functioning correctly

How can I dynamically load a webpage's content into a div using JavaScript and jQuery? Here's what I have tried: <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script> When a s ...

Utilizing Angular Filter to compare the date in a JSON file with the current system date

<p id="appt_time" ng-if="x.dateTime | date: MM/dd/yyyy == {{todaysDate}}">DISPLAY IF TRUE{{todaysDate}} </p> Plunkr:https://plnkr.co/edit/r2qtcU3vaYIq04c5TVKG?p=preview x.dateTime | date: MM/dd/yyyy retrieves a date and time which results in ...

Yet again faced with an annoying gap between table rows and cells, for the 532nd instance

Once again, tables have defeated me. I am struggling with a simple table: <table style="width: 200px; margin: 20px auto; border-collapse: collapse; border-spacing: 0; border: none;"> <tr style="margin: 0; padding: 0; border: none; border-colla ...

Align elements on the left side with some space between them

Having trouble displaying a list of images inline within a div. When I float them left, they leave a lot of space and do not display properly. Can anyone help me with this issue? See screenshot below: Here is my html code: <div class="col75"> & ...

Exploring the use of Shadow DOM in ContentEditable for securing text segments

I have recently been working on creating a basic text editor using ContentEditable. The main requirement for the application is to allow users to insert blocks of text that are protected from typical editing actions. These protected text blocks should not ...

CSS - Ignoring Padding Causes Unexpected White Space to Appear

I am encountering a simple error, and the following address will direct you to where the issue can be seen. Why is certain parts of the header appearing white instead of the light shade of green it is set to be? It should be positioned right at the top un ...

Tips for accessing a variable value within a JavaScript function

I am currently facing an issue where I am unable to retrieve a variable from a JavaScript function and use it outside of the function. While I can successfully output the variable value inside the function, I am struggling to access it elsewhere in my sc ...

Unpacking and reassigning variables in Vue.js 3 using TypeScript

I am working with a component that has input parameters, and I am experimenting with using destructuring assignment on the properties object to reassign variables with different names: <script setup lang="ts"> const { modelValue: isSelected ...

What steps can be taken to ensure your bot successfully sends the second argument?

Who just handed out an L to user#0000? Looks like JohnGameRage#0000 did! ...

Setting up a Webpack configuration for packaging a Vue component as an npm module

Below is the primary JavaScript code for my component: import './sass/main.scss' import Vlider from './Vlider.vue' function install(Vue) { if (install.installed) return; install.installed = true; Vue.component('vlider ...

Classic design of the shadow element

I have main.js and index.html below class CustomTagA extends HTMLElement { constructor() { super(); const shadow = this.attachShadow({mode: 'open'}); const wrapper = document.createElement('h1'); ...

Associative TypeScript Arrays

I'm attempting to organize reservations based on business ID in order to achieve a specific end result. Here is the desired output: [ [businessID1] => [Object1,Object2, Object3], [businessID2] => [Object1,Object2], [businessID3] => [Object1,Objec ...

Simple HTML and CSS exercise for beginners to grasp the concept

I'm looking to modify the layout of a specific webpage at based on the following instructions: First, insert this link within the <head> <link rel="stylesheet" href="https://trafficbalance.io/static/css/sdk/sdk.css"> -next, add th ...