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 am attempting to integrate a datetimepicker onto my website, but I keep encountering an error. Can

Once upon a time, my website had a perfectly functioning datetimepicker. However, one day it suddenly stopped working. After some investigation, I realized that the JavaScript file I was referencing had been taken down. Determined to fix the issue, I visit ...

Guide to centering a list on a webpage using Bootstrap 3

Looking to create a centered list using the latest version of Bootstrap 3. Any tips? The desired list should be positioned in the middle of the page. ___________________________________________ | | | ...

The concept of recursion in AngularJS directives

I developed a unique custom directive. angular.module('menu',[]) .directive('MenuDirective',function(){ return{ restrict:'E', replace:'true', scope:{ m ...

adjust the dimensions of the clickable icon's background

Is there a way to expand the pressable area of a close icon without altering its size? For example, if the icon is 19X19 pixels, can the pressable area be increased to 39X39 pixels? The concern lies with the div element containing the close button and the ...

What is the best way to input data into nedb across various lines?

There is a requirement to store each element of an array into separate lines while saving it in the NEDB database. The idea is to add "\r\n" after every element, like this: Currently, I am doing the following: usernames = ["name1","name2","name3 ...

How to Refresh EJS Template in an Express Node.js Application

Currently, I am integrating discord.js with express and facing a challenge. I want my webpage to automatically update whenever the client.on("message") event is triggered. According to my knowledge and research, it seems that rendering an ejs template is o ...

JavaScript CompleteLink message

Hey there, I've come across a JavaScript code for a countdown timer but need some assistance with it. The issue I'm facing is that within the code, there's a line that displays a message to the user when the timer reaches zero. I want to kn ...

Using Jquery for a Second Timer

I have a jQuery function that looks like the one below. The result is displayed in a span, but when the page is reloaded, this span briefly disappears and then reappears. Is there a way to prevent this from happening? I need it to stay visible at all tim ...

Is it possible to utilize a computed property for dynamically styling a table row based on certain conditions?

I have a table of users that I am currently rendering, and my goal is to highlight the entire row only for the current user. My initial thought was to use a computed property to achieve this, but I seem to be facing some difficulties in making it work. I ...

Issues with rendering AngularJS onto an HTML page are currently being experienced

I was attempting to learn AngularJs in order to improve my front-end development skills, but unfortunately I ran into some issues. Despite following the video tutorials on their site step by step, I couldn't get it to render correctly. Here's the ...

JQuery Ajax request produces the message "Insufficient storage to fulfill this operation."

Encountering an error while attempting to pass the result.target of an OnLoad event in FileReader.readAsArrayBuffer call using a jQuery Ajax POST. The POST is not being executed, and this issue seems to be specific to IE, as it functions correctly in Chrom ...

"Retrieve real-time information from the server directly on the client side

Within my express router, I validate the data submitted on a form and then render another page if the data is valid, passing along the form data. My goal is to be able to access this passed data on the client-side. In the chat.ejs view, I have a chatroom.j ...

Alter the style of a div by clicking on a button

Can the background image of a div be changed by selecting a button outside of the div? For example: HTML <div id="change"></div> <div id="buttons"> <button class="button1">this</button> <button class="button2"> ...

Why do style assignments lose their motion when executed right after being made?

If you take a look at this specific fiddle in Webkit, you will see exactly what I am referring to. Is there a way to define the style of an element when it is first specified, and then its final state? I would like to be able to fully define a single-ste ...

The AJAX request encountered an error due to an Unexpected End of JSON Input

My AJAX code is encountering an error message. parsererror (index):75 SyntaxError: Unexpected end of JSON input at parse (<anonymous>) at Nb (jquery.min.js:4) at A (jquery.min.js:4) at XMLHttpRequest.<anonymous> (jquery.min.js: ...

Issue with Alignment of Border in PDF [Example Included]

I am currently developing a straightforward react application with very minimal content. index.js: <div className="App"> <div id="printable-div"> <h1>Generate PDF</h1> <p>Capture a screenshot of ...

What is the reason behind the length property belonging to an array object?

While there are other instances, let's focus on the length property for now. Why does it appear as if we're copying it here: [].hasOwnProperty("length") //==> true It is common knowledge that an array's length property belongs ...

What is the best way to design an angular directive or service specifically for straightforward pagination featuring only next and previous options?

Within a block of div tags, an ng-repeat directive is being used to display sets of 3 divs at a time. By clicking on the next button, the next set of 3 divs should be displayed, and the same goes for the previous button. Check out the HTML code below: &l ...

How can I access an InputStream from a local XML file in a PhoneGap application?

Looking for advice on how to fetch an inputstream from a local XML file using JavaScript in my PhoneGap application. I'm new to JavaScript, so any guidance would be appreciated! ...

Please retain only the clean <p> elements using Jsoup and remove all other content

I'm struggling to figure out a simple solution for this problem. My elements consist of a mix of <p>, p class="example">, and <p><strong>...</strong></p>. All I want to do is preserve everything within the clean < ...