A friend showed me something of a design spec they were charged with pulling off:

The requirements:
… when I click on any of them it expands at the top to full width and the rest of the cards re-arrange themselves below it.
Like anything web design & development, there are a boatload of ways you could do this. Different layout strategies, different combinations of native technologies, different libraries to punt to, etc. I lean native first, so this was how my brain scripted the problem:
auto flow onto the grid.order: -1; (another 😬)grid-column: 1 / -1;And so:
Video here. Note that only Chrome supports View Transitions. This video shows them, but the rest of it should work regardless of browser.
:has() selector can go a long way in interactive fun!The Grid
Pretty easy these days, so I’ll make it complicated just for fun:
.grid { display: grid; grid-template-columns: repeat( auto-fit, /* fluid columns, but max out at 3 */ minmax(min(100%, max(10rem, 100%/4)), 1fr) ); gap: 2.5rem; }Code language: SCSS (scss)This incantation of grid-template-columns says:
A bit complex, but a useful bit of code there that can be expressed without media queries. I’m sure I’ll come back to this blog post for that over and over.
The Move
To make sure the clicked card becomes the first one, I’ll toggle a class:
.card { ... &.featured { order: -1; grid-column: 1 / -1; font-size: 133%; } }Code language: SCSS (scss)const cards = document.querySelectorAll(".card"); cards.forEach((card, i) => { card.addEventListener("click", () => { activateCard(card); }); }); function activateCard(card) { cards.forEach((card) => { card.classList.remove("featured"); }); card.classList.add("featured"); }Code language: JavaScript (javascript)Animate It
This is essentially a tweening (sometimes called FLIP) animation where you don’t really care about the starting or ending state per se you just say: animate between them please.
The trick there is the View Transitions API, which means you just wrap any DOM manipulation in there and it’ll automatically animate. Here I’ll ensure the DOM changes even if the browser doesn’t have that API yet.
if (!document.startViewTransition) { activateCard(card); } document.startViewTransition(() => { activateCard(card); });Code language: JavaScript (javascript)That’s ridiculously simple. I love it.
I popped a close button on each card also which just de-features all cards, and calls the same API.
The Accessibility Situation
I’ve attached a click handler to a damn <div> here. That’s not right. A user using a screen reader won’t be able to activate the animation because the <div> is not interactive itself.
But… maybe that’s OK?
This is what you might call a “fidget spinner animation”. It doesn’t do anything important. No information is revealed. It’s just something you can click on for poops and giggles.
The second we reveal some additional information… then we’re in trouble here. Then we need to attach the activation to an interactive element, probably a <button>. And as soon as we do that then the fact that we’re changing the tabbing order by messing with order becomes problematic. Tabbing order is no longer intuitive when the 4th item can appear at the top yet send focus to the 5th item just because that’s where it is in the DOM. Perhaps you could fight that by setting tabindex values ourselves, but that seems like a can of worms. Honestly, if this was revealing extra information, I’d probably just not take this approach at all and find some other more suitable way.
Text selection is a minor concern. It’s a little annoying how you can select text and un-clicking after dragging activates the click and the text goes flying away from you. I say minor because the text remains selected so it’s not a 100% blocker.
Another form of accessibility is not making people nauseous, so might as well honor the preference for reduced motion. Easy as CSS:
@media (prefers-reduced-motion: reduce) { ::view-transition-old(*), ::view-transition-new(*) { animation-duration: 0s; } }Code language: CSS (css)Another little View Transitions Thing
A hamburger interaction where the lines of the hamburger fly out to become the borders of the navigation drawer. This one not only uses View Transitions but native CSS nesting too just for fun.
Related
ncG1vNJzZmibmKe2tK%2FOsqCeql6jsrV7kWlpbGdgaXxyfY6er6mZnpm2r7OMoKminF2YrrOw0mauoqyYYsOqsdZmq6uZnqi2tbXOp6po