Pure CSS Animated Accordion
Modern Web Weekly #29
View Transitions now work (almost) perfectly in Safari Tech Preview
In Modern Web Weekly #26, I wrote that View Transitions were enabled in Safari Tech Preview and now they have been improved to work almost perfectly.
In the video below, you see a mobile view of What PWA Can Do Today to simulate what it will look like on iOS when support lands there. Notice that the flip animation is not yet correct as the page is flipped in the wrong direction when navigating back:
Although not fully correct, it's good to see the animation now has the 3D effect that was previously missing.
Another issue is that the scroll positions are not correct when navigating back and forth:
In Chrome, this is taken care of by the scroll
option of the Navigation API which is not yet fully supported in Safari Tech Preview.
The next example shows an event handler for the navigate
event that is fired in supporting browsers when the user navigates to another URL. The navigation is intercepted using the intercept
method of the NavigateEvent
that takes an options object as an argument. Its handler
property takes a function that takes care of rendering the new page and inside this function, the view transition is executed:
navigation.addEventListener('navigate', e => {
e.intercept({
// makes sure home page opens scrolled to top on back navigation
scroll: 'manual',
async handler() {
const matchedRoute = getMatchedRoute(url);
if(matchedRoute) {
const transition = document.startViewTransition(async () => {
// makes sure new page is scrolled to top
// on forward navigation
if(!backNavigation) {
window.scrollTo(0, 0);
}
...
});
...
}
}
});
});
By setting its scroll
property to manual
, the browser will not reset the pages to their last scroll position so when using a sliding page transition (like in the previous video) the sliding pages are always shown fully scrolled to the top which eliminates the scrolling issue shown in the same video.
I also added the window.scrollTo(0, 0)
part in Safari but the issue remains as you can see in the above video.
When support for the Navigation API lands in Safari, these issues will likely be solved. I will continue to test and report here.
[disabled] vs :disabled in CSS
I was recently reminded of a small but very important detail regarding disabled form elements.
I usually use the [disabled]
attribute selector to target disabled form elements because when a form element is disabled by setting its disabled
property to true
this is always reflected to the disabled
attribute.
But when a form element is inside a <fieldset>
element that is disabled, that form element will also be disabled but this state will then not be reflected to the disabled
attribute. So in that case, the form element is disabled but it won't have the disabled
attribute.
The :disabled
pseudo-class will however apply to both cases so you may want to consider using :disabled
instead of [disabled]
since the first will always work.
Learn to build and publish a component library that works in any web framework
The interactive Component Odyssey course will teach you everything you need to build a modern web component library. In over 60 lessons, learn how to build, style, and publish components that are interoperable with React, Vue, Svelte, and any other web framework.
Save yourself and your company weeks of development time by betting on the web and browser-native tools.
Start building components your users will love. Web Weekly readers get 10% off with the discount code MODERNWEB01.
A pure CSS animation accordion
You probably already know you can now create an exclusive accordion by using multiple details
elements with the same name
attribute like this:
<details name="accordion">
<summary>Foo</summary>
Foo content...
</details>
<details name="accordion">
<summary>Bar</summary>
Bar content...
</details>
<details name="accordion">
<summary>Baz</summary>
Baz content...
</details>
but soon you'll also be able to animate the opening and closing of the accordion with only CSS!
As a matter of fact, here's a Codepen that does just that in Chrome Canary with experimental web platform features enabled (you may need to view this in the browser version of this email):
This demo uses the ::details-content
pseudo element that represents the content inside the <details>
element. This element is in proposal stage and therefore still experimental but as you can see in the demo, it works quite well!
The trick to animating the opening and closing of the accordion is the calc-size
CSS function that enables developers to animate height: auto
.
Initially, `details::details-content will have height: 0
and when it's opened it will transition to height: calc-size(auto)
:
/* details is closed */
details::details-content {
height: 0;
opacity: 0;
overflow: hidden;
transition: height .3s, opacity 0.5s,
content-visibility .3s;
transition-behavior: allow-discrete;
}
/* details is opened */
details[open]::details-content {
height: calc-size(auto);
opacity: 1;
}
For this to work, content-visibility
needs to transition as well and since this is a so-called discrete property, setting transition-behavior
to allow-discrete
is required.
Again, this is all still experimental but it gives you a nice glimpse of what the future may look like for pure CSS animated accordions. Here's a video of the Codepen by @yisi:
Here's a fork of this Codepen stripped down to its bare essentials for you to experiment with (you may need to view this in the browser version of this email):
For fun, I also adapted the original demo to let the content slide down instead of being revealed (you may need to view this in the browser version of this email):