缩进错位源于制表符渲染差异、中文字体非等宽、语义缺失、HTML注入错误及CSS样式覆盖四层问题,需统一用pre-wrap、textContent、pre+code嵌套并确保等宽字体栈。

pre 里缩进错位,八成是制表符和字体惹的祸
直接把代码复制进 <pre> 却发现缩进塌了、中文挤在一起、Tab 看起来比空格宽三倍——这不是你代码写得不对,而是浏览器对 \t 默认按 8 字符渲染,而编辑器(如 VS Code)通常设为 4;更关键的是,中文字体 fallback 到 SimSun 这类非等宽字体后,一个汉字 ≈ 2 个空格宽,视觉直接“塌陷”。
- 用 DevTools 检查
<pre>元素 computed 的font-family,确认是否真落到'Microsoft YaHei Mono'或monospace栈上 - 检查内容是否含原始
\t:后端返回的 YAML/INI 常带未处理的 Tab,JS 里要先做str.replace(/\t/g, ' ') - 别信编辑器里的缩进显示——它和浏览器渲染逻辑根本不同
必须用 <pre><code> 嵌套,单用 <pre> 是语义残缺
<code> 是行内元素,不保留换行;<pre> 是块级容器,但缺语言语义。只套一层,屏幕阅读器读不出“这是 Python 代码”,Prism.js 也找不到入口点,SEO 更无法识别语言类型。
- 正确结构必须是:
<pre><code class="python">...</code></pre>(注意 class 值是language-python,不是python) - 样式要作用在
pre code上,而非仅pre:比如pre code { font-family: monospace; } - 别写
<pre lang="python">——HTML5 规范不支持该属性用于语法高亮,工具链不认
动态注入时,textContent 是唯一安全且保形的方式
后端返回一段带 &、<、> 的配置内容,如果用 innerHTML 直接塞进 <pre>,& 会被解析成实体,<url> 可能被当成标签闭合,甚至触发 XSS;更糟的是,\n 在 innerHTML 中会被忽略,缩进全丢。
- 永远用
preEl.textContent = configStr:它把整个字符串当纯文本,\n和空格原样保留 - 模板引擎里避免写
<pre>{{ configStr }}</pre>——默认转义会把\n变成,缩进消失;需显式用v-pre或{{{ }}}(依框架而定) - 若必须高亮,别手写正则替换 + innerHTML,改用
highlight.js或Prism.js,它们内部已处理好 whitespace 边界
样式层:white-space: pre-wrap 比 pre 更实用
pre 默认 white-space: pre,保留所有空白但禁止折行,一行 300 字符的 URL 直接撑破容器;pre-line 会裁掉所有行首缩进,不能用;pre-wrap 是真实项目中最稳的选择。
立即学习“前端免费学习笔记(深入)”;
- 加
white-space: pre-wrap:保留缩进、换行、空格,同时允许长行在边界处自然折行 - 配
overflow-x: auto:防无空格长串(如 base64)横向溢出 - 禁用
text-align: center:会让整块代码居中,破坏相对缩进关系 - 别被 reset.css 覆盖:检查是否有
pre { white-space: normal; }这类规则,显式重置更可靠
\t、字体栈没落到等宽中文字体、JS 用了 innerHTML、或者全局样式悄悄覆盖了 white-space,都会让缩进当场失效。



















