Close Menu
    DevStackTipsDevStackTips
    • Home
    • News & Updates
      1. Tech & Work
      2. View All

      Sunshine And March Vibes (2025 Wallpapers Edition)

      June 1, 2025

      The Case For Minimal WordPress Setups: A Contrarian View On Theme Frameworks

      June 1, 2025

      How To Fix Largest Contentful Paint Issues With Subpart Analysis

      June 1, 2025

      How To Prevent WordPress SQL Injection Attacks

      June 1, 2025

      My top 5 must-play PC games for the second half of 2025 — Will they live up to the hype?

      June 1, 2025

      A week of hell with my Windows 11 PC really makes me appreciate the simplicity of Google’s Chromebook laptops

      June 1, 2025

      Elden Ring Nightreign Night Aspect: How to beat Heolstor the Nightlord, the final boss

      June 1, 2025

      New Xbox games launching this week, from June 2 through June 8 — Zenless Zone Zero finally comes to Xbox

      June 1, 2025
    • Development
      1. Algorithms & Data Structures
      2. Artificial Intelligence
      3. Back-End Development
      4. Databases
      5. Front-End Development
      6. Libraries & Frameworks
      7. Machine Learning
      8. Security
      9. Software Engineering
      10. Tools & IDEs
      11. Web Design
      12. Web Development
      13. Web Security
      14. Programming Languages
        • PHP
        • JavaScript
      Featured

      Student Record Android App using SQLite

      June 1, 2025
      Recent

      Student Record Android App using SQLite

      June 1, 2025

      When Array uses less memory than Uint8Array (in V8)

      June 1, 2025

      Laravel 12 Starter Kits: Definite Guide Which to Choose

      June 1, 2025
    • Operating Systems
      1. Windows
      2. Linux
      3. macOS
      Featured

      My top 5 must-play PC games for the second half of 2025 — Will they live up to the hype?

      June 1, 2025
      Recent

      My top 5 must-play PC games for the second half of 2025 — Will they live up to the hype?

      June 1, 2025

      A week of hell with my Windows 11 PC really makes me appreciate the simplicity of Google’s Chromebook laptops

      June 1, 2025

      Elden Ring Nightreign Night Aspect: How to beat Heolstor the Nightlord, the final boss

      June 1, 2025
    • Learning Resources
      • Books
      • Cheatsheets
      • Tutorials & Guides
    Home»News & Updates»Using & Styling the Details Element

    Using & Styling the Details Element

    February 26, 2025

    You can find the <details> element all over the web these days. We were excited about it when it first dropped and toyed with using it as a menu back in 2019 (but probably don’t) among many other experiments. John Rhea made an entire game that combines <details> with the Popover API!

    Now that we’re 5+ years into <details>, we know more about it than ever before. I thought I’d round that information up so it’s in one place I can reference in the future without having to search the site — and other sites — to find it.

    The basic markup

    It’s a single element:

    <details>
      Open and close the element to toggle this content.
    </details>
    CodePen Embed Fallback

    That “details” label is a default. We can insert a <summary> element to come up with something custom:

    <details>
      <summary>Toggle content</summary>
      Open and close the element to toggle this content.
    </details>
    CodePen Embed Fallback

    From here, the world is sorta our oyster because we can stuff any HTML we want inside the element:

    <details>
      <summary>Toggle content</summary>
      <p>Open and close the element to toggle this content.</p>
      <img src="path/to/image.svg" alt="">
    </details>

    The content is (sorta) searchable

    The trouble with tucking content inside an element like this is that it’s hidden by default. Early on, this was considered an inaccessible practice because the content was undetected by in-page searching (like using CMD+F on the page), but that’s since changed, at least in Chrome, which will open the <details> element and reveal the content if it discovers a matched term.

    Searching for the word 'toggle' in Chrome. The term is highlighted in the open details element.

    That’s unfortunately not the case in Firefox and Safari, both of which skip the content stuffed inside a closed <details> element when doing in-page searches at the time I’m writing this. But it’s even more nuanced than that because Firefox (testing 134.0.1) matches searches when the <details> element is open, while Safari (testing 18.1) skips it altogether. That could very well change by the end of this year since searchability is one of the items being tackled in Interop 2025.

    So, as for now, it’s a good idea to keep important content out of a <details> element when possible. For example, <details> is often used as a pattern for Frequently Asked Questions, where each “question” is an expandable “answer” that reveals additional information. That might not be the best idea if that content should be searchable on the page, at least for now.

    CodePen Embed Fallback

    Open one at a time

    All we have to do is give each <details> a matching name attribute:

    <details name="notes">
      <summary>Open Note</summary>
      <p> ... </p>
    </details>
    <details name="notes"> <!-- etc. --> </details>
    <details name="notes"> <!-- etc. --> </details>
    <details name="notes"> <!-- etc. --> </details>

    This allows the elements to behave a lot more like true accordions, where one panel collapses when another expands.

    CodePen Embed Fallback

    Style the marker

    The marker is that little triangle that indicates whether the <details> element is open or closed. We can use the ::marker pseudo-element to style it, though it does come with constraints, namely that all we can do is change the color and font size, at least in Chrome and Firefox which both fully support ::marker. Safari partially supports it in the sense that it works for ordered and unordered list items (e.g., li::marker), but not for <details> (e.g., summary::marker).

    Let’s look at an example that styles the markers for both <details> and an unordered list. At the time I’m writing this, Chrome and Firefox support styling the ::marker in both places, but Safari only works with the unordered list.

    CodePen Embed Fallback

    Notice how the ::marker selector in that last example selects both the <details> element and the unordered list element. We need to scope the selector to the <details> element if we want to target just that marker, right?

    /* This doesn't work! */
    details::marker { 
      /* styles */
    }

    Nope! Instead, we need to scope it to the <summary> element. That’s what the marker is actually attached to.

    /* This does work */
    summary::marker { 
      /* styles */
    }

    You might think that we can style the marker even if we were to leave the summary out of the markup. After all, HTML automatically inserts one for us by default. But that’s not the case. The <summary> element has to be present in the markup for it to match styles. You’ll see in the following demo that I’m using a generic ::marker selector that should match both <details> elements, but only the second one matches because it contains a <summary> in the HTML. Again, only Chrome and Firefox support for the time being:

    CodePen Embed Fallback

    You might also think that we can swap out the triangle for something else since that’s something we can absolutely do with list items by way of the list-style-type property:

    /* Does not work! */
    summary::marker {
      list-style-type: square;
    }

    …but alas, that’s not the case. An article over at web.dev says that it does work, but I’ve been unsuccessful at getting a proper example to work in any browser.

    CodePen Embed Fallback

    That isn’t to say it shouldn’t work that way, but the specification isn’t explicit about it, so I have no expectations one way or another. Perhaps we’ll see an edit in a future specification that gets specific with <details> and to what extent CSS can modify the marker. Or maybe we won’t. It would be nice to have some way to chuck the triangle in favor of something else.

    And what about removing the marker altogether? All we need to do is set the content property on it with an empty string value and voilà!

    CodePen Embed Fallback

    Once the marker is gone, you could decide to craft your own custom marker with CSS by hooking into the <summary> element’s ::before pseudo-element.

    CodePen Embed Fallback

    Just take note that Safari displays both the default marker and the custom one since it does not support the ::marker pseudo-element at the time I’m writing this. You’re probably as tired reading that as I am typing it. 🤓

    Style the content

    Let’s say all you need to do is slap a background color on the content inside the <details> element. You could select the entire thing and set a background on it:

    details {
      background: oklch(95% 0.1812 38.35);
    }

    That’s cool, but it would be better if it only set the background color when the element is in an open state. We can use an attribute selector for that:

    Hostinger
    details[open] {
      background: oklch(95% 0.1812 38.35);
    }

    OK, but what about the <summary> element? What if you don’t want that included in the background? Well, you could wrap the content in a <div> and select that instead:

    details[open] div {
      background: oklch(95% 0.1812 38.35);
    }
    CodePen Embed Fallback

    What’s even better is using the ::details-content pseudo-element as a selector. This way, we can select everything inside the <details> element without reaching for more markup:

    ::details-content {
      background: oklch(95% 0.1812 38.35);
    }

    There’s no need to include details in the selector since ::details-content is only ever selectable in the context of a <details> element. So, it’s like we’re implicitly writing details::details-content.

    CodePen Embed Fallback

    The ::details-content pseudo is still gaining browser support when I’m writing this, so it’s worth keeping an eye on it and using it cautiously in the meantime.

    Animate the opening and closing

    Click a default <details> element and it immediately snaps open and closed. I’m not opposed to that, but there are times when it might look (and feel) nice to transition like a smooth operator between the open and closed states. It used to take some clever hackery to pull this off, as Louis Hoebregts demonstrated using the Web Animations API several years back. Robin Rendle shared another way that uses a CSS animation:

    details[open] p {
      animation: animateDown 0.2s linear forwards;
    }
    
    @keyframes animateDown {
      0% {
        opacity: 0;
        transform: translatey(-15px);
      }
      100% {
        opacity: 1;
        transform: translatey(0);
      }
    }

    He sprinkled in a little JavaScript to make his final example fully interactive, but you get the idea:

    CodePen Embed Fallback

    Notice what’s happening in there. Robin selects the paragraph element inside the <details> element when it is in an open state then triggers the animation. And that animation uses clever positioning to make it happen. That’s because there’s no way to know exactly how tall the paragraph — or the parent <details> element — is when expanded. We have to use explicit sizing, padding, and positioning to pull it all together.

    But guess what? Since then, we got a big gift from CSS that allows us to animate an element from zero height to its auto (i.e., intrinsic) height, even if we don’t know the exact value of that auto height in advance. We start with zero height and clip the overflow so nothing hangs out. And since we have the ::details-content pseudo, we can directly select that rather than introducing more markup to the HTML.

    ::details-content {
      transition: height 0.5s ease, content-visibility 0.5s ease allow-discrete;
      height: 0;
      overflow: clip;
    }

    Now we can opt into auto-height transitions using the interpolate-size property which was created just to enable transitions to keyword values, such as auto. We set it on the :root element so that it’s available everywhere, though you could scope it directly to a more specific instance if you’d like.

    :root {
      interpolate-size: allow-keywords;
    }

    Next up, we select the <details> element in its open state and set the ::details-content height to auto:

    [open]::details-content {
      height: auto;
    }

    We can make it so that this only applies if the browser supports auto-height transitions:

    @supports (interpolate-size: allow-keywords) {
      :root {
        interpolate-size: allow-keywords;
      }
    
      [open]::details-content {
        height: auto;
      }
    }

    And finally, we set the transition on the ::details-content pseudo to activate it:

    ::details-content {
      transition: height 0.5s ease;
      height: 0;
      overflow: clip;
    }
    
    /* Browser supports interpolate-size */
    @supports (interpolate-size: allow-keywords) {
      :root {
        interpolate-size: allow-keywords;
      }
    
      [open]::details-content {
        height: auto;
      }
    }
    CodePen Embed Fallback

    But wait! Notice how the animation works when opening <details>, but things snap back when closing it. Bramus notes that we need to include the content-visibility property in the transition because (1) it is implicitly set on the element and (2) it maps to a hidden state when the <details> element is closed. That’s what causes the content to snap to hidden when closing the <details>. So, let’s add content-visibility to our list of transitions:

    ::details-content {
      transition: height 0.5s ease, content-visibility 0.5s ease allow-discrete;
      height: 0;
      overflow: clip;
    }
    
    /* Browser supports interpolate-size */
    @supports (interpolate-size: allow-keywords) {
      :root {
        interpolate-size: allow-keywords;
      }
    
      [open]::details-content {
        height: auto;
      }
    }

    That’s much better:

    CodePen Embed Fallback

    Note the allow-discrete keyword which we need to set since content-visibility is a property that only supports discrete animations and transitions.

    Interesting tricks

    Chris has a demo that uses <details> as a system for floating footnotes in content. I forked it and added the name attribute to each footnote so that they close when another one is opened.

    CodePen Embed Fallback

    I mentioned John Rhea’s “Pop(over) The Balloons” game at the top of these notes:

    CodePen Embed Fallback

    Bramus with a slick-looking horizontal accordion forked from another example. Note how the <details> element is used as a flex container:

    CodePen Embed Fallback

    Chris with another clever trick that uses <details> to play and pause animated GIF image files. It’s doesn’t actually “pause” but the effect makes it seem like it does.

    CodePen Embed Fallback

    Ryan Trimble with styling <details> as a dropdown menu and then using anchor positioning to set where the content opens.

    CodePen Embed Fallback

    References

    • HTML Living Standard (Section 4.11.1) by WHATWG
    • “Quick Reminder that Details/Summary is the Easiest Way Ever to Make an Accordion” by Chris Coyier
    • “A (terrible?) way to do footnotes in HTML” by Chris Coyier
    • “Using <details> for Menus and Dialogs is an Interesting Idea” by Chris Coyier
    • “Pausing a GIF with details/summary” by Chris Coyier
    • “Exploring What the Details and Summary Elements Can Do” by Robin Rendle
    • “More Details on <details>“ by Geoff Graham
    • “::details-content“ by Geoff Graham
    • “More options for styling <details>“ by Bramus
    • “How to Animate the Details Element Using WAAPI” by Louis Hoebregts
    • “Details and summary” by web.dev

    Using & Styling the Details Element originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

    Source: Read More 

    Facebook Twitter Reddit Email Copy Link
    Previous ArticleChristoph Hellwig Si Dimette da Maintainer dei DMA Mapping Helpers nel Kernel Linux!
    Next Article Qccrypt – frontend for ccrypt

    Related Posts

    News & Updates

    My top 5 must-play PC games for the second half of 2025 — Will they live up to the hype?

    June 1, 2025
    News & Updates

    A week of hell with my Windows 11 PC really makes me appreciate the simplicity of Google’s Chromebook laptops

    June 1, 2025
    Leave A Reply Cancel Reply

    Continue Reading

    Microsoft is making it easier for you to change Windows 11’s time zone

    Operating Systems

    AI Desk offers 24/7 AI support to cut costs

    Development

    Adobe’s New AI Is So Good You Might Ditch Other Tools

    Artificial Intelligence

    Amazon SageMaker inference launches faster auto scaling for generative AI models

    Development

    Highlights

    CVE-2025-28367 – MojoPortal Directory Traversal Vulnerability

    April 21, 2025

    CVE ID : CVE-2025-28367

    Published : April 21, 2025, 4:15 p.m. | 2 hours, 47 minutes ago

    Description : mojoPortal
    Severity: 6.5 | MEDIUM

    Visit the link for more details, such as CVSS details, affected products, timeline, and more…

    The 30 best early Black Friday phone deals

    November 1, 2024

    Free GenAI 65-Hour Bootcamp

    May 9, 2025

    Understanding refs in Vue

    June 13, 2024
    © DevStackTips 2025. All rights reserved.
    • Contact
    • Privacy Policy

    Type above and press Enter to search. Press Esc to cancel.