0

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.

1 Answers1

0

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.

amarinediary
  • 4,930
  • 4
  • 27
  • 45
  • 1
    That's fantastic! And thank you so much for directing me to that resource. It will surely be very useful since I am dealing with some more scripts, like that for the responsive menus. I personally wanted to follow the non-JS approach as much as possible for better page speed. And having the ability to use native HTML5 elements such as '
    ' and '' makes sense in the case of Table of Contents.
    – Dhananjay Bhardwaj Feb 15 '21 at 20:07
  • You can never go wrong developping the old school way, withonly html5 and CC3. HTML5 brings a lot of new native behaviour to the table. People usually don't know about it or just relly on JS library like Jquery. Thing is, too much dependencies are always a bad thing. (same thing apply to Wordpress and plugins). The best thing you can do is reducing dependencies as much as possible. Comming back to our `` and `
    ` elements, you could also add an effect to it without relying on js, using purelly css3. See https://stackoverflow.com/a/38215801/3645650
    – amarinediary Feb 16 '21 at 15:56
  • Couldn't agree more. HTML5 is such a drastic improvement overall, and it's really great that browsers are getting good at adapting it. I usually stray away from Javascript as it's render-blocking and try to find an HTML/CSS-only solution first. The JS for responsive menus in the Genesis Framework I use is obnoxiously heavy. I have thought of ditching it and using a horizontal scrolling menu instead. But I couldn't find a solid HTML/CSS way to output the search form in the header. Do you have any ideas? Thanks for sharing the link, I have marked it. Pretty cool technique, I will try it. – Dhananjay Bhardwaj Feb 17 '21 at 11:52
  • Don't know about Genesis Framework. I'm a big fan of full page navigation coupled with a simple grid and using a show/hide js system. – amarinediary Feb 17 '21 at 17:19
  • Seems like a good option to me. Could you share an example or possible code? If the JS isn't as heavy as that of my responsive-menus js, then I would love to implement it (with some help, of course :D ). – Dhananjay Bhardwaj Feb 17 '21 at 18:57