要实现可折叠代码块,须组合并转义HTML字符;须为首个子元素,须紧随其后;动态展开时需监听toggle事件重触发语法高亮。

<details></details> 标签本身不支持语法高亮或代码块渲染,它只是语义化折叠容器;要实现“可折叠的代码块”,必须手动组合 <details></details>、<summary></summary> 和 <pre class="brush:php;toolbar:false;"><code></code>,并确保 <code><code></code> 的内容被正确转义或由编辑器预处理。</p>
<H3>为什么直接写 <pre class="brush:php;toolbar:false;"><details><summary>Code</summary><pre class="brush:php;toolbar:false;"><code>console.log(1)</code></pre>
<p>常见错误是未对 HTML 特殊字符做转义,导致浏览器把 <code><code> 内的尖括号解析为标签而非文本。例如:<code>for (let i = 0; i 中的 <code> 会被截断解析,后续内容消失或报错。
- 编辑器若为富文本(如 TinyMCE、CKEditor),默认会过滤或破坏
<pre class="brush:php;toolbar:false;"><code></code> 结构,需开启 <code>allowedContent</code> 或禁用 HTML 清洗</li> <li>若为 Markdown 编辑器(如 Toast UI Editor、Obsidian),需确认是否支持原生 HTML 嵌入 —— 多数默认关闭,需设 <code>html: true</code> 或等效配置</li> <li>服务端渲染时(如 Jekyll、Hugo),模板引擎可能自动转义,需用 <code>{{ raw }}...{{ endraw }}</code> 或 <code>{{ .RawHTML | safeHTML }}</code> 绕过</li> </ul> <H3>正确嵌套结构与转义方式</H3> <p>核心是保证 <code><pre class="brush:php;toolbar:false;"><code></code> 内容作为纯文本存在。最稳妥的做法是:在 HTML 源码中手动将 <code><</code> 替换为 <code><</code>,<code>></code> 替换为 <code>></code>,<code>&</code> 替换为 <code>&</code>。</p><div class="aritcle_card flexRow"> <div class="artcardd flexRow"> <a class="aritcle_card_img" href="/xiazai/skill11244" title="Convert Markdown To HTML And PDF - Markdown和HTML、PDF互转"><img src="https://img.php.cn/upload/skill/001/246/273/6adaf20d79f23518.jpg" alt="Convert Markdown To HTML And PDF - Markdown和HTML、PDF互转" ></a> <div class="aritcle_card_info flexColumn"> <a href="/xiazai/skill11244" title="Convert Markdown To HTML And PDF - Markdown和HTML、PDF互转">Convert Markdown To HTML And PDF - Markdown和HTML、PDF互转</a> <p>实现 Markdown↔ HTML 互转,支持导出 PDF,用于用户请求的文档格式转换。</p> </div> <a href="/xiazai/skill11244" title="Convert Markdown To HTML And PDF - Markdown和HTML、PDF互转" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div> <pre class="brush:php;toolbar:false;"><details> <summary>点击展开 JS 示例</summary> <pre class="brush:php;toolbar:false;"><code class="js">function hello() { console.log("world"); return true && false; }</code></pre> <ul> <li> <code><summary></summary>必须是<details></details>的第一个子元素,否则折叠逻辑失效 <pre class="brush:php;toolbar:false;"></code> 应紧贴 <code><summary></code> 后,中间不能有空格或换行文本节点(某些旧版 Safari 会因此不渲染)</li> <li>如果依赖 Prism.js 或 Highlight.js,<code>class="js"</code> 是必需的触发标识,且需在 <code><details></code> 展开后再调用 <code>Prism.highlightAll()</code></li> </ul> <H3>动态展开后语法高亮不生效?</H3> <p>因为 <code><details></code> 默认折叠时,部分高亮库(尤其是早期 Prism 版本)会跳过隐藏 DOM 的处理。解决方案不是改 CSS 显示,而是监听 <code>toggle</code> 事件重触发:</p><p><span>立即学习</span>“<a href="https://pan.quark.cn/s/cb6835dc7db1" style="text-decoration: underline !important; color: blue; font-weight: bolder;" rel="nofollow" target="_blank">前端免费学习笔记(深入)</a>”;</p> <pre class="brush:php;toolbar:false;">document.addEventListener('DOMContentLoaded', () => { document.querySelectorAll('details').forEach(details => { details.addEventListener('toggle', () => { if (details.open && details.querySelector('code')) { Prism.highlightElement(details.querySelector('code')); } }); }); });</pre> <ul> <li>不要用 <code>details.addEventListener('click', ...)—— 点击<summary></summary>不一定触发该事件,toggle才是标准行为- 检查
Prism.highlightElement()是否已加载;若用模块化引入,需确保prism-core和对应语言插件都已 import - 若用 Highlight.js,替换为
hljs.highlightElement(codeEl),逻辑一致
真正容易被忽略的是:编辑器保存时是否保留原始 HTML 结构。很多所见即所得编辑器会在切换源码/可视化模式时自动“修复”嵌套,把 <pre class="brush:php;toolbar:false;"><code></code> 提到外面,或删掉 <code><details></details></code>。上线前务必查看浏览器实际渲染的 DOM,而不是编辑器里写的源码。</pre>


















