CSS Styling for Custom Elements

css
Published on February 19, 2021

Custom elements can be styled using CSS defined in its Shadow DOM, or through CSS defined in the main page.

Styling Custom Element with Its Own CSS (via Shadow DOM)

Custom element can define its own CSS rules using Shadow DOM.

CSS rules defined in the Shadow DOM will be kept isolated to the custom element itself. They won't be applied to any outside element in the page.

<!-- main page -->
<input-plus-minus></input-plus-minus>
<!-- custom element's Shadow DOM -->
<style>
	#add {
		width: 50%;
	}

	#count {
		width: 50%;
	}
</style>
<div id="container">
	<input type="text" id="count" />
	<button id="add">+</button>
</div>

Styling Custom Element with User-Defined CSS

Custom elements can also be styled through user-defined CSS in the main page.

Note that user-defined CSS rules will always override custom element's CSS defined in its Shadow DOM..

  1. Users can apply their custom CSS rules in the main page so as to style the element from the "outside", using the tag name selector.

    <!-- main page -->
    <input-plus-minus></input-plus-minus>
    <style>
    	input-plus-minus {
    		width: 500px;
    		background-color: red;
    	}
    
    	input-plus-minus:hover {
    		background-color: blue;
    	}
    </style>
    

    However such CSS rules in the main page cannot be used to select any inner elements inside the Shadow DOM.

  2. Inheritable CSS rules such as background, font etc however pass through the Shadow DOM, and get inherited by the custom element.

    <!-- main page -->
    <input-plus-minus></input-plus-minus>
    <style>
    	/* background-color & font-size will get inherited inside the Shadow DOM also */
    	input-plus-minus {
    		background-color: red;
    		font-size: 18px;
    	}
    </style>
    

    To prevent this CSS inheritance in the element's Shadow DOM, all: initial can be used to reset inheritable styles to their initial values.

    <!-- custom element's Shadow DOM -->
    <style>
    	/* reset all inheritable styles */
    	#container {
    		all: initial;
    	}
    </style>
    <div id="container">
    	<input type="text" id="count" />
    	<button id="add">+</button>
    </div>
    
  3. User-defined CSS custom properties also pass through the Shadow DOM. This can be used to style inner elements inside the custom element's Shadow DOM.

    <!-- main page -->
    <input-plus-minus></input-plus-minus>
    <style>
    	input-plus-minus {
    		--main-color: green;
    	}
    </style>
    
    <!-- custom element's Shadow DOM -->
    <style>
    	#add {
    		border: 1px solid var(--main-color);
    	}
    </style>
    <div id="container">
    	<input type="text" id="count" />
    	<button id="add">+</button>
    </div>
    

Styling Unregistered Custom Element

Before the custom element is registered using the Javascript customElements.define() method, it can be styled using the :defined & :not CSS pseudo-classes.

:defined CSS pseudo-class selects elements that have been defined.

:not CSS pseudo-class selects elements that is NOT the specified selector.

<!-- main page -->
<input-plus-minus></input-plus-minus>
<style>
	/* CSS styles until custom element is unregistered */
	input-plus-minus:not(:defined) {
		display: none;
	}

	/* CSS styles when custom element gets registered */
	input-plus-minus:defined {
		display: block;
	}
</style>
In this Tutorial