diff --git a/doc/api_assets/style.css b/doc/api_assets/style.css
index 7f471a8c08a499..e7ecfd264ad542 100644
--- a/doc/api_assets/style.css
+++ b/doc/api_assets/style.css
@@ -472,8 +472,8 @@ hr {
   margin: 0 0 1rem;
 }
 
-#toc h2 {
-  margin: 1.5rem 0;
+#toc > ul {
+  margin-top: 1.5rem;
 }
 
 #toc p {
diff --git a/doc/template.html b/doc/template.html
index d7cc96062eaf6a..675a761bd80f88 100644
--- a/doc/template.html
+++ b/doc/template.html
@@ -55,10 +55,10 @@ <h1>Node.js __VERSION__ Documentation</h1>
         <hr>
       </header>
 
-      <div id="toc">
-        <h2>Table of Contents</h2>
+      <details id="toc" open>
+        <summary>Table of Contents</summary>
         __TOC__
-      </div>
+      </details>
 
       <div id="apicontent">
         __CONTENT__
diff --git a/tools/doc/allhtml.js b/tools/doc/allhtml.js
index c038b1f57a9bb8..5a24cee4292656 100644
--- a/tools/doc/allhtml.js
+++ b/tools/doc/allhtml.js
@@ -31,10 +31,10 @@ for (const link of toc.match(/<a.*?>/g)) {
   const data = fs.readFileSync(source + '/' + href, 'utf8');
 
   // Split the doc.
-  const match = /(<\/ul>\s*)?<\/div>\s*<div id="apicontent">/.exec(data);
+  const match = /(<\/ul>\s*)?<\/\w+>\s*<\w+ id="apicontent">/.exec(data);
 
   contents += data.slice(0, match.index)
-    .replace(/[\s\S]*?<div id="toc">\s*<h2>.*?<\/h2>\s*(<ul>\s*)?/, '');
+    .replace(/[\s\S]*?id="toc"[^>]*>\s*<\w+>.*?<\/\w+>\s*(<ul>\s*)?/, '');
 
   apicontent += data.slice(match.index + match[0].length)
     .replace(/<!-- API END -->[\s\S]*/, '')
@@ -59,13 +59,13 @@ let all = toc.replace(/index\.html/g, 'all.html')
 all = all.replace(/<title>.*?\| /, '<title>');
 
 // Insert the combined table of contents.
-const tocStart = /<div id="toc">\s*<h2>.*?<\/h2>\s*/.exec(all);
+const tocStart = /<\w+ id="toc"[^>]*>\s*<\w+>.*?<\/\w+>\s*/.exec(all);
 all = all.slice(0, tocStart.index + tocStart[0].length) +
   '<ul>\n' + contents + '</ul>\n' +
   all.slice(tocStart.index + tocStart[0].length);
 
 // Replace apicontent with the concatenated set of apicontents from each source.
-const apiStart = /<div id="apicontent">\s*/.exec(all);
+const apiStart = /<\w+ id="apicontent">\s*/.exec(all);
 const apiEnd = all.lastIndexOf('<!-- API END -->');
 all = all.slice(0, apiStart.index + apiStart[0].length) +
   apicontent +