Skip to content

Latest commit

 

History

History

details-animation

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 

Animating the <details> element

npm version Workflow status

Features

  • Animation effect on the opening and closing of HTML <details> element.
  • Animation speed (duration) and easing effects (easing) can be customized.
  • In prefers-reduced-motion: reduce environments, no animation is performed. (Version 4.2.0 or later)

Demo

Examples

<script type="importmap">
  {
    "imports": {
      "@w0s/details-animation": "...",
      "@w0s/shadow-append-css": "...",
      "@w0s/writing-mode": "..."
    }
  }
</script>
<script type="module">
  import DetailsAnimation from '@w0s/details-animation';

  for (const targetElement of document.querySelectorAll('.js-details-animation')) {
    new DetailsAnimation(targetElement);
  }
</script>

<details class="js-details-animation"
  open=""
  data-duration="1000"
  data-easing="linear"
>
  <summary>Caption Text</summary>
  <p>Contents text</p>
</details>

Attributes

open [optional]
Whether the details are visible. (open attribute of <details> Element)
data-duration [optional]
The iteration duration which is a real number greater than or equal to zero (including positive infinity) representing the time taken to complete a single iteration of the animation effect (See OptionalEffectTiming for details). If omitted, the default value is 500(ms).
data-easing [optional]
The timing function used to scale the time to produce easing effects (See OptionalEffectTiming for details). If omitted, the default value is ease.

Sample CSS

In order to achieve animation, the timing of setting the open attribute of the <details> element is delayed. Therefore, the viewlet icon of the <summary> element should be determined by the data-pre-open attribute.

details {
  --summary-icon-rotate: 0deg;

  &:is(:not([open]), [data-pre-open='false']) {
    --summary-icon-rotate: -90deg;
  }

  & > summary {
    list-style: none;

    &::-webkit-details-marker {
      display: none;
    }

    &::before {
      display: inline flow-root;
      margin-inline-end: 0.5em;
      content: '▼';
      rotate: var(--summary-icon-rotate);
    }
  }
}

* By including both :not([open]) and [data-pre-open='false'] in the selector's condition, we can handle both cases when JavaScript works correctly and when it does not (e.g. script disabled environment).

* Safari(17) does not support list-style for the <summary> element, so use the ::-webkit-details-marker pseudo-element. (Can I use...)