Skip to content

Instantly share code, notes, and snippets.

@timmo001
Created November 13, 2025 12:30
Show Gist options
  • Select an option

  • Save timmo001/f9bc8330a266b2adb3ae8e84fdf6ea67 to your computer and use it in GitHub Desktop.

Select an option

Save timmo001/f9bc8330a266b2adb3ae8e84fdf6ea67 to your computer and use it in GitHub Desktop.
View Transitions and Shadow DOM
<h1>Just DOM πŸ‘</h1>
<section>
<button id="none">Toggle</button>
<hr>
<div class="test"></div>
</section>
<h1>Externally styled ::part()s πŸ‘</h1>
<with-part class="section">
<template shadowrootmode="open">
<button id="none">Toggle</button>
<hr>
<div part="test-0" class="test"></div>
</template>
</with-part>
<h1>External "view-transition-name", internal styles πŸ‘</h1>
<with-split class="section">
<template shadowrootmode="open">
<style>
.test, ::part(test) {
width: 100px;
height: 100px;
background: black;
clear: both;
float: left;
}
.test {
view-transition-name: test;
}
::part(test) {
view-transition-name: part;
}
.active, ::part(active) {
float: right !important;
}
</style>
<button id="none">Toggle</button>
<hr>
<div part="test-1" class="test"></div>
</template>
</with-split>
<h1>Shadow DOM with internally styled elements πŸ‘Ž</h1>
<with-internal class="section">
<template shadowrootmode="open">
<style>
.test, ::part(test) {
width: 100px;
height: 100px;
background: black;
clear: both;
float: left;
}
.test {
view-transition-name: test;
}
.active, ::part(active) {
float: right;
}
</style>
<button id="none">Toggle</button>
<hr>
<div class="test"></div>
</template>
</with-internal>
function toggleClass() {
const target = this.nextElementSibling.nextElementSibling;
if (document?.startViewTransition) {
document.startViewTransition(() => {
target.classList.toggle('active');
});
} else {
target.classList.toggle('active');
}
}
function togglePart() {
const target = this.nextElementSibling.nextElementSibling;
if (document?.startViewTransition) {
document.startViewTransition(() => {
target.part.toggle('active');
});
} else {
target.part.toggle('active');
}
}
none.addEventListener('click', toggleClass);
customElements.define('with-part', class extends HTMLElement {
connectedCallback() {
this.shadowRoot.querySelector('button').addEventListener('click', togglePart)
}
});
customElements.define('with-split', class extends HTMLElement {
connectedCallback() {
this.shadowRoot.querySelector('button').addEventListener('click', toggleClass)
}
});
customElements.define('with-internal', class extends HTMLElement {
connectedCallback() {
this.shadowRoot.querySelector('button').addEventListener('click', toggleClass)
}
});
body:after {
content: '';
width: 100%;
height: 200px;
display: block;
}
.test, ::part(test-0), ::part(test) {
width: 100px;
height: 100px;
background: black;
clear: both;
float: left;
}
.test {
view-transition-name: test;
}
::part(test-0) {
view-transition-name: part-0;
}
::part(test-1) {
view-transition-name: part-1;
}
.active, ::part(active) {
float: right;
}
section,
.section {
width: 100%;
float: left;
}
html {
view-transition-name: none;
}
::view-transition-group(*) {
animation-duration: 2.5s;
}
h1 {
font-size: 1.5rem;
margin: 1rem 0 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment