Pure CSS Animated Accordion

Pure CSS Animated Accordion
Photo by Elimende Inagella / Unsplash

Modern Web Weekly #29

👋
Hello there! I'm Danny and this is Modern Web Weekly, your weekly update on what the modern web is capable of, Web Components, and Progressive Web Apps (PWA). I test modern web features and write about them in plain English to make sure you stay up to date.

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:

View Transitions in Safari Tech Preview

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:

View Transitions in Safari Tech Preview with scrolling issue

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.

Get Component Odyssey

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):

Pure CSS animated accordion by @yisi

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:

Pure CSS animated accordion 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):

Pure CSS animated accordion stripped down

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):

Pure CSS animated accordion with sliding down content

🔗
Got an interesting link for Modern Web Weekly? Send me a DM on Twitter to let me know!