I am using the popular TOC+ plugin by Michael Tran to generate a Table of Contents on my blog posts.
The plugin offers an option that allows us to enable a Show/Hide feature, with another option to hide the table of contents initially.
Now, it uses Javascript to achieve this. The problem is that the table is shown before the browser catches and renders the Javascript. This ultimately leads to Content Layout Shift (CLS) issues in Core Web Vitals.
I went ahead and disabled the Show/Hide option and that solved the CLS completely. However, now I am left with obnoxiously big TOCs in my posts (I use a full-width layout, so they are inserted within the content itself).
Anyways, moving ahead I had an idea of using HTML <details>
and <summary>
elements to get the Show/Hide behavior without having to rely on Javascript.
I have successfully edited the plugin's PHP code to change the markup and changed this:
<div id="toc_container">
<p class="toc_title">Table of Contents</p>
<ul class="toc_list>
<li><a href="#first-heading"></a></li>
<li><a href="#second-heading"></a></li>
<li><a href="#third-heading"></a></li>
<li><a href="#fourth-heading"></a></li>
</ul>
</div>
To this:
<details id="toc_container">
<summary class="toc_title">Table of Contents</summary>
<ul class="toc_list>
<li><a href="#first-heading"></a></li>
<li><a href="#second-heading"></a></li>
<li><a href="#third-heading"></a></li>
<li><a href="#fourth-heading"></a></li>
</ul>
</details>
It works. But I am not sure if it's right to do it? Or is it semantically incorrect?
It would be great if someone here could share their opinion and correct me if I am wrong.
EDIT: Before posting I did some digging and found a discussion thread over at SitePoint. Moreover, I also saw HTML5 Doctor mentioning "Table of Contents" as a possible use-case.
Both <summary>
and <details>
are valid html5 elements, and therefore can be used without restriction.
The
<summary>
tag defines a visible heading for the<details>
element. The heading can be clicked to view/hide the details.
The
<details>
tag specifies additional details that the user can open and close on demand. The<details>
tag is often used to create an interactive widget that the user can open and close. By default, the widget is closed. When open, it expands, and displays the content within. Any sort of content can be put inside the<details>
tag.
Regarding:
The problem is that the table is shown before the browser catches and renders the Javascript.
Properly enqueuing scripts should easily fix that issue you can learn more about Wordpress and scripts enqueuing here @ https://stackoverflow.com/a/65396220/3645650.
You could also look into implementing some kind of page loader which would let users know that your page is still loading, it would also prevent any problem related to content display.