Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(css): improve :defined pseudo-class example #35371

Merged
merged 4 commits into from
Sep 17, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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")}}
OnkarRuikar marked this conversation as resolved.
Show resolved Hide resolved

## Specifications

Expand Down