htmlcss

Last HTML element will not transition as expected


For context, I believe this code only currently works in Chrome as it is relatively new CSS.

I'm not sure if this is a bug or if I have a poor understanding of CSS/browsers/the document.

I have been using a combination of size interpolation and the <details> pseudo-element ::details-content to transition the opening of the details element.

I noticed that the last element does not transition at all unless there is something immediately after it. See below minimal example.

In the below example, all details transition as expected, however, if I remove the last div, the last details does not transition correctly.

With last div, working:

body {
    min-height: 100svh;
}
details {
    interpolate-size: allow-keywords;
}
details > div {
    overflow:hidden;
}
details::details-content {
    block-size: 0;
    transition: block-size 0.2s ease-in-out, content-visibility 0.2s;
    transition-behavior: allow-discrete;
}
details[open]::details-content {
    block-size: auto;
}
<html lang="en">
  <head>
    <meta charset="utf-8">
  </head>

  <body>
    
    <details>
        <summary>summary</summary>
        <div>content</div>
    </details>
    
    <details>
        <summary>summary</summary>
        <div>content</div>
    </details>
    
    <details>
        <summary>summary</summary>
        <div>content</div>
    </details>
    
    <div>end</div>
  </body>
</html>

Without last div, broken transition on last element:

body {
    min-height: 100svh;
}
details {
    interpolate-size: allow-keywords;
}
details > div {
    overflow:hidden;
}
details::details-content {
    block-size: 0;
    transition: block-size 0.2s ease-in-out, content-visibility 0.2s;
    transition-behavior: allow-discrete;
}
details[open]::details-content {
    block-size: auto;
}
<html lang="en">
  <head>
    <meta charset="utf-8">
  </head>

  <body>
    
    <details>
        <summary>summary</summary>
        <div>content</div>
    </details>
    
    <details>
        <summary>summary</summary>
        <div>content</div>
    </details>
    
    <details>
        <summary>summary</summary>
        <div>content</div>
    </details>
    
  </body>
</html>


Solution

  • if you look closely, all of them behave the same. there is no transition when the content appear. There is only a transition on the height. You have the illusion that the last one is broken because nothing is moving after it.

    The overflow: hidden needs to be on ::details-content not the div to make sure the content appear slowly.

    body {
      min-height: 100svh;
    }
    
    details {
      interpolate-size: allow-keywords;
    }
    
    details::details-content {
      block-size: 0;
      transition: block-size 0.2s ease-in-out, content-visibility 0.2s;
      transition-behavior: allow-discrete;
      overflow: hidden;
    }
    
    details[open]::details-content {
      block-size: auto;
    }
    <details>
      <summary>summary</summary>
      <div>content</div>
    </details>
    
    <details>
      <summary>summary</summary>
      <div>content</div>
    </details>
    
    <details>
      <summary>summary</summary>
      <div>content</div>
    </details>

    Use a big transition value with your example to notice the issue

    body {
      min-height: 100svh;
    }
    
    details {
      interpolate-size: allow-keywords;
    }
    
    details::details-content {
      block-size: 0;
      transition: block-size 2s ease-in-out, content-visibility 2s;
      transition-behavior: allow-discrete;
    }
    
    details[open]::details-content {
      block-size: auto;
    }
    <details>
      <summary>summary</summary>
      <div>content</div>
    </details>
    
    <details>
      <summary>summary</summary>
      <div>content</div>
    </details>
    
    <details>
      <summary>summary</summary>
      <div>content</div>
    </details>