Skip to content

Commit

Permalink
fix(css): improve :defined pseudo-class example (#35371)
Browse files Browse the repository at this point in the history
* fix(css): improve :defined pseudo-class example

* Apply suggestions from code review

Co-authored-by: Chris Mills <[email protected]>

* address review comments

* small tweak

---------

Co-authored-by: Chris Mills <[email protected]>
  • Loading branch information
OnkarRuikar and chrisdavidmills authored Sep 17, 2024
1 parent 57cfc73 commit 415caa6
Showing 1 changed file with 69 additions and 39 deletions.
108 changes: 69 additions & 39 deletions files/en-us/web/css/_colon_defined/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ browser-compat: css.selectors.defined

{{CSSRef}}

The **`:defined`** [CSS](/en-US/docs/Web/CSS) [pseudo-class](/en-US/docs/Web/CSS/Pseudo-classes) represents any element that has been defined. This includes any standard element built in to the browser, and custom elements that have been successfully defined (i.e. with the {{domxref("CustomElementRegistry.define()")}} method).
The **`:defined`** [CSS](/en-US/docs/Web/CSS) [pseudo-class](/en-US/docs/Web/CSS/Pseudo-classes) represents any element that has been defined. This includes any standard element built into the browser and custom elements that have been successfully defined (i.e. with the {{domxref("CustomElementRegistry.define()")}} method).

```css
/* Selects any defined element */
Expand All @@ -33,65 +33,95 @@ simple-custom:defined {

### Hiding elements until they are defined

The following snippets are taken from our [defined-pseudo-class](https://github.com/mdn/web-components-examples/tree/main/defined-pseudo-class) demo ([see it live also](https://mdn.github.io/web-components-examples/defined-pseudo-class/)).
In this demo, we define a basic custom element named `<custom-element>` and use the `:not(:defined)` and `:defined` selectors to style the element before and after it is defined. This is useful if you have a complex custom element that takes a while to load into the page — you might want to hide instances of the element until the definition is complete so that you don't end up with flashes of ugly unstyled elements on the page.

In this demo we define a very simple trivial custom element:
#### HTML

```js
customElements.define(
"simple-custom",
class extends HTMLElement {
constructor() {
super();

let divElem = document.createElement("div");
divElem.textContent = this.getAttribute("text");

let shadowRoot = this.attachShadow({ mode: "open" }).appendChild(divElem);
}
},
);
```

Then insert a copy of this element into the document, along with a standard `<p>`:
The following HTML code uses the custom element but the element hasn't been defined yet. We also include a {{htmlelement("button")}} that will define the custom element when clicked, allowing you to see its state before and after definition.

```html
<simple-custom text="Custom element example text"></simple-custom>

<p>Standard paragraph example text</p>
<custom-element>
<p>
Loaded content: Lorem ipsum tel sed tellus eiusmod tellus. Aenean. Semper
dolor sit nisi. Elit porttitor nisi sit vivamus.
</p>
</custom-element>

<button id="btn">define the <code>&lt;custom-element&gt;</code></button>
```

In the CSS we first include the following rules:
#### CSS

```css
/* Give the two elements distinctive backgrounds */
p {
background: yellow;
```css hidden
custom-element {
display: block;
border: 5px dashed grey;
border-radius: 1rem;
height: 100px;
width: 400px;
padding: 1rem;
position: relative;
user-select: none;
}

simple-custom {
background: cyan;
code {
background: #ccc;
}

/* Both the custom and the built-in element are given italic text */
:defined {
font-style: italic;
#btn {
margin-top: 1rem;
cursor: pointer;
}
```

Then provide the following two rules to hide any instances of our custom element that are not defined, and display instances that are defined as block level elements:
In the following CSS, we use the `custom-element:not(:defined)` selector to select the element and color it grey while it is not defined and the `custom-element:defined` selector to select the element and color it black after it is defined.

```css
simple-custom:not(:defined) {
display: none;
custom-element:not(:defined) {
border-color: grey;
color: grey;
}

simple-custom:defined {
display: block;
custom-element:defined {
background-color: wheat;
border-color: black;
color: black;
}

/* show loading message */
custom-element:not(:defined)::before {
content: "Loading...";
position: absolute;
inset: 0 0 0 0;
align-content: center;
text-align: center;
font-size: 2rem;
background-color: white;
border-radius: 1rem;
}

/* remove the loading message */
custom-element:defined::before {
content: "";
}
```

We have also used the [`::before`](/en-US/docs/Web/CSS/::before) pseudo-element to show a "Loading..." overlay message until the element is defined. After definition, it is removed by setting the [`content`](/en-US/docs/Web/CSS/content) to an empty string.

The following JavaScript has been used to define the custom element. To allow you to see the state of the custom element before and after definition we run the {{domxref("CustomElementRegistry.define", "define()")}} method when the button is clicked.

```js
const btn = document.querySelector("#btn");

btn.addEventListener("click", () => {
customElements.define("custom-element", class extends HTMLElement {});
btn.remove();
});
```

This is useful if you have a complex custom element that takes a while to load into the page — you might want to hide instances of the element until definition is complete, so that you don't end up with flashes of ugly unstyled elements on the page
#### Result

{{EmbedLiveSample("Hiding elements until they are defined", "100%", "230")}}

## Specifications

Expand Down

0 comments on commit 415caa6

Please sign in to comment.