Jan's Development Microblog
Go back to blog overview

How to reverse the order of the details summary HTML element

Learn how to create a "Read More/Read Less" toggle using the HTML element, reversing its default order, and enhancing it with dynamic labels.

For one of my latest projects, I needed a way to include a read more / read less toggle. I had a few options for this. As it should only show text when the element is open, I opted to use the details element. By default, the title is always above the content, and there is no built-in way to flip the order of the element.

My first attempt to reverse the order of the detail summary HTML element

In my case, I wanted to display the summary label at the bottom. My first thought was to change the order of the HTML so I could reverse the order of the detail summary HTML elements.

<details>
<div class="content"></div>
<summary></summary>
</details>    

However, this didn't do anything at all, as the summary label was still rendered at the top. Somehow this makes sense if you think in web components, but code-wise this doesn't seem logical. Back to the drawing board. After a bit of searching on the web, I couldn't really find a working solution. Meanwhile, I tried using flex-box to change the order of the element within the detail-element. But no luck, as the summary label was still on top.

Working solution to reverse the order of the detail summary HTML element

During the search earlier, I got a few small hints for a possible solution. I had the feeling that using position: absolute might do the trick to reverse the order of the detail summary HTML element. So, time to write the code.

​<div class="block">
<h2>Whispers of the Untamed Horizon</h2>
<details open>
<div>
Breezy afternoons whisper through tall pines, scattering
golden sunlight.
</div>
<summary>
<div class="open">Read less</div>
<div class="closed">Read more</div>
</summary>
</details>
</div>

<style>
details {
position: relative;
summary {
position: absolute;
bottom: -1.5em;
display: block;
}
> div {
padding-bottom: 1em;
}
&[open] .closed{
display: none;
}
&:not([open]) .open{
display: none;
}
}
</style>

I ended up with the code above, which was working. The summary label was shown at the bottom and the content above. I have added some extra code to show a different summary label depending on the state of the details element. When the container is open, the content is shown and the summary label shows the text "Read less." When the element is closed, the text "Read more" shows.

Summary

I'm aware that this solution is far from perfect. When showing more or less text, you normally want to cut down the text to three or four lines instead of hiding it completely. If this is the case, the solution using details cannot be used. However, I still believe there are multiple use cases for this solution. For myself, I will convert this into a web component that I'll add to my library for future use. Why write the same code twice when you can just reuse it?