How to change details label when open/closed without JavaScript
John P. Rouillard

John P. Rouillard @rouilj

About: Former system admin, current open source dev and EMT.

Location:
Near Boston, MA USA
Joined:
Aug 13, 2020

How to change details label when open/closed without JavaScript

Publish Date: Jul 12 '21
5 4

I wish the details element would support different labels (provided by the summary tag) for its open and closed states.

Consider a label of "Closed, click to open" when the details element is closed and "Open, click to close" when open:

Open details element with label changed to indicate state.

Sadly only one summary tag is supported by the details element. However you can use an empty summary with a ::before pseudo-element to implement this.

Save the following to a file:



<html>
  <body>
  <style>
    #widget1 div { padding-inline-start: 1em; max-width: 20em;}
    #widget1 summary::before { content: "Closed, click to open";}
    #widget1[open] summary::before { content: "Open, click to close";}
    #widget1[open] summary { height: 2em;}
  </style>

  <p> Text before details.</p>
  <details id="widget1">
    <summary></summary>
    <div>
    A widget can be in one of two states. The default closed
    state displays only the triangle and the label inside summary
    (or a user agent-defined default string if no summary).
    </div>
  </details>
  <p>Text after details.</p>
  <body>
</html>


Enter fullscreen mode Exit fullscreen mode

to experiment.
The second and third style lines are where the magic happens.

Note that it might not be accessible. I didn't try to see if adding a live region aria label to the summary would cause the label change to be announced. I suspect it will not, but refining this is left as an exercise for the reader. Add your experimental findings to the comments below.

Comments 4 total

  • Elena
    ElenaJul 14, 2021

    Well, content in css is not that great especially when your dealing with translations. I guess a simple way to do it is to have 2 <span>s and toggle them depending on the open attribute, but I do agree it's not ideal.

    • John P. Rouillard
      John P. RouillardJul 18, 2021

      Ah interesting interesting idea. So:

       <details>
         <summary>
          <span class="open">open text</span>
          <span class="closed">closed text</span>
        </summary>
        ...
      </details>
      
      Enter fullscreen mode Exit fullscreen mode

      with:

      details summary span.open {display:none;}
      details[open] summary span.open {display:inline}
      details[open] summary span.closed {display:none}
      
      Enter fullscreen mode Exit fullscreen mode

      Nice idea.

      • Elena
        ElenaJul 18, 2021

        Nice. For some reason I was thinking on a js solution, but this css solution most definitely works too.

        • John P. Rouillard
          John P. RouillardJul 18, 2021

          Hi Elena:

          Yeah, I try to stay away from JS whenever possible. Using CSS and HTML provides better performance.

          Removing JS whenever possible makes the web less fragile.

          Hence the original reason for the post. Plus this is probably more accessible as well.

          -- rouilj

Add comment