Skip to content

pre 预格式文本

<pre> 标签用于定义预格式化文本(Preformatted Text)。被 <pre> 包裹的内容会保留源代码中的空格、换行符和制表符等空白字符,按照原始格式进行显示。<pre> 最常见的用途是与 <code> 标签配合,展示代码片段。

前置知识

阅读本节前,建议先了解:blockquote 引用块

基础概念

<pre> 是 "preformatted" 的缩写。在普通的 HTML 文本中,浏览器会将连续的空白字符压缩为单个空格。而 <pre> 元素打破了这一规则——它会忠实地保留文本中的所有空白字符(包括空格、换行和制表符),使文本按照源代码中书写的方式显示。

这使得 <pre> 成为展示需要保持格式的内容的理想选择,例如:

  • 计算机代码
  • ASCII 艺术
  • 纯文本文件内容
  • 诗歌(需要保持特定排版)

语法

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>pre 预格式文本示例</title>
</head>
<body>
  <h1>pre 标签示例</h1>

  <!-- 普通 p 标签:空白被压缩 -->
  <p>普通段落中    多个空格会被压缩。</p>

  <!-- pre 标签:保留空白字符 -->
  <pre>pre 标签中    多个空格会被保留。
第二行
    缩进的第三行</pre>
</body>
</html>

详细说明

pre 的默认样式

浏览器为 <pre> 提供了以下默认样式:

属性默认值(Chrome)说明
displayblock块级元素
font-familymonospace等宽字体
margin1em 0上下外边距
white-spacepre保留空白字符
overflowvisible默认不裁剪溢出内容

monospace 字体

<pre> 默认使用等宽字体(monospace),即每个字符占用相同的宽度。这确保了代码的对齐效果。常见的等宽字体有:Courier New、Consolas、Monaco、Menlo。

pre 与 code 配合使用

<pre> 本身只负责保留格式,不表达"这是代码"的语义。因此,在展示代码片段时,推荐将 <code> 放在 <pre> 内部,形成语义+格式的组合:

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>pre 与 code 配合</title>
  <style>
    pre {
      background: #f5f5f5;
      padding: 1rem;
      border-radius: 4px;
      overflow-x: auto;
    }
    code {
      font-family: "Consolas", "Monaco", monospace;
      font-size: 0.9rem;
    }
  </style>
</head>
<body>
  <h1>代码展示</h1>

  <!-- 推荐:pre 包裹 code,语义和格式都有 -->
  <pre><code>function greet(name) {
  console.log("你好, " + name + "!");
}

greet("世界");</code></pre>

  <!-- 注意:<pre> 内的 <code> 不应有换行 -->
  <pre><code>
    function greet(name) {
      return "Hello, " + name;
    }
  </code></pre>
</body>
</html>

pre 与 code 的换行问题

<pre> 标签内紧邻标签的换行符会被保留。为避免代码块前面出现多余的空行,<pre><code> 之间不应有换行:

html
<!-- 不推荐:<pre> 和 <code> 之间有换行,会导致代码块顶部有空行 -->
<pre>
<code>let x = 10;</code>
</pre>

<!-- 推荐:<pre> 和 <code> 紧邻,没有多余换行 -->
<pre><code>let x = 10;</code></pre>

pre 中可以包含的内容

<pre> 内部可以包含文本和行内元素,如 <code><em><strong><a><span> 等,但不能包含块级元素:

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>pre 内的行内元素</title>
  <style>
    pre { background: #f5f5f5; padding: 1rem; }
  </style>
</head>
<body>
  <!-- pre 中可以使用行内元素做语法高亮 -->
  <pre><code><span style="color: blue;">function</span> <span style="color: #d73a49;">add</span>(a, b) {
  <span style="color: #6f42c1;">return</span> a + b;
}</code></pre>

  <!-- pre 中也可以包含链接 -->
  <pre>更多文档请访问:<a href="https://developer.mozilla.org">MDN Web Docs</a></pre>
</body>
</html>
html
<!-- 错误:pre 中不能包含块级元素 -->
<pre>
  <p>这是一段文字</p>  <!-- 浏览器会提前关闭 pre -->
</pre>

overflow 处理

<pre> 中的长文本或代码行可能会超出容器宽度,导致页面出现水平滚动条或内容被截断。这是使用 <pre> 时最常见的问题。

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>pre overflow 处理</title>
  <style>
    body { max-width: 680px; margin: 0 auto; padding: 2rem 1rem; }

    /* 方案一:水平滚动(推荐,不截断代码) */
    .scroll-pre {
      background: #f5f5f5;
      padding: 1rem;
      border-radius: 4px;
      overflow-x: auto;  /* 允许水平滚动 */
      white-space: pre;  /* 保持原始格式 */
    }

    /* 方案二:自动换行(代码可读性可能降低) */
    .wrap-pre {
      background: #f5f5f5;
      padding: 1rem;
      border-radius: 4px;
      overflow-x: hidden;
      white-space: pre-wrap;  /* 在必要时换行 */
      word-break: break-all;
    }

    /* 方案三:保留空白但允许换行 */
    .pre-wrap {
      background: #f5f5f5;
      padding: 1rem;
      border-radius: 4px;
      white-space: pre-wrap;  /* 保留空白,但允许自然换行 */
      overflow-x: hidden;
    }
  </style>
</head>
<body>
  <h1>处理 pre 中的长文本</h1>

  <h2>方案一:水平滚动</h2>
  <pre class="scroll-pre"><code>const result = someVeryLongFunctionName(someVeryLongArgumentName1, someVeryLongArgumentName2, someVeryLongArgumentName3);</code></pre>

  <h2>方案二:自动换行</h2>
  <pre class="wrap-pre"><code>const result = someVeryLongFunctionName(someVeryLongArgumentName1, someVeryLongArgumentName2, someVeryLongArgumentName3);</code></pre>

  <h2>方案三:保留空白但允许换行</h2>
  <pre class="pre-wrap"><code>const result = someVeryLongFunctionName(
  someVeryLongArgumentName1,
  someVeryLongArgumentName2,
  someVeryLongArgumentName3
);</code></pre>
</body>
</html>

white-space 属性对比

空格换行符自动换行适用场景
pre保留保留代码展示(默认值)
pre-wrap保留保留长文本 + 保持缩进
pre-line压缩保留保留换行的普通文本
normal压缩压缩普通文本(非 pre)
nowrap压缩压缩单行显示

实战示例

代码展示页面

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>代码展示</title>
  <style>
    body {
      font-family: -apple-system, BlinkMacSystemFont, sans-serif;
      max-width: 760px;
      margin: 0 auto;
      padding: 2rem 1rem;
      line-height: 1.6;
    }
    pre {
      background: #282c34;
      color: #abb2bf;
      padding: 1.25rem;
      border-radius: 8px;
      overflow-x: auto;
      font-size: 0.875rem;
      line-height: 1.5;
    }
    pre code {
      font-family: "Fira Code", "Consolas", "Monaco", monospace;
    }
    /* 语法高亮类 */
    .keyword { color: #c678dd; }
    .string { color: #98c379; }
    .comment { color: #5c6370; font-style: italic; }
    .function { color: #61afef; }
    .number { color: #d19a66; }
  </style>
</head>
<body>
  <h1>JavaScript 示例代码</h1>

  <p>以下是一个使用 <code>Array.reduce()</code> 方法计算数组总和的示例:</p>

  <pre><code><span class="keyword">const</span> numbers = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>];

<span class="comment">// 使用 reduce 计算总和</span>
<span class="keyword">const</span> sum = numbers.<span class="function">reduce</span>((acc, cur) =&gt; {
  <span class="keyword">return</span> acc + cur;
}, <span class="number">0</span>);

console.<span class="function">log</span>(<span class="string">`总和为:${sum}`</span>); <span class="comment">// 总和为:15</span></code></pre>

  <p>这段代码首先定义了一个包含五个数字的数组,然后使用 <code>reduce()</code> 方法对数组进行累加,初始值为 0。</p>
</body>
</html>

ASCII 艺术展示

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>ASCII 艺术</title>
  <style>
    body { max-width: 680px; margin: 0 auto; padding: 2rem 1rem; }
    pre.ascii-art {
      background: #1a1a2e;
      color: #00ff88;
      padding: 1.5rem;
      border-radius: 8px;
      font-size: 0.75rem;
      line-height: 1.2;
      overflow-x: auto;
    }
  </style>
</head>
<body>
  <h1>ASCII 艺术展示</h1>

  <pre class="ascii-art">
  ___                        _  _
 / _ \ _ __ ___  _ __ __ _ __| || |
| |_| | '_ ` _ \| '__/ _` / _` || |_
|  _  | | | | | | | | (_| | (_| |  _|
|_| |_|_| |_| |_|_|  \__,_|\__, |_||
                            |___/
  </pre>

  <pre class="ascii-art">
    /\_/\
   ( o.o )
    &gt; ^ &lt;
   /|   |\
  (_|   |_)
  </pre>
</body>
</html>

诗歌排版

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>诗歌排版</title>
  <style>
    body { max-width: 680px; margin: 0 auto; padding: 2rem 1rem; font-family: serif; }
    pre.poem {
      text-align: center;
      font-size: 1.25rem;
      line-height: 2;
      background: #fafafa;
      padding: 2rem;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <h1>静夜思</h1>
  <p>作者:李白</p>

  <pre class="poem">    床前明月光,
    疑是地上霜。
    举头望明月,
    低头思故乡。</pre>
</body>
</html>

注意事项

HTML 实体转义

<pre> 中展示 HTML 标签时,需要对 <> 进行转义,否则浏览器会将它们解析为真正的 HTML 标签:

html
<!-- 错误:<div> 会被解析为 HTML 元素 -->
<pre><code><div class="box">Hello</div></code></pre>

<!-- 正确:使用 HTML 实体转义 -->
<pre><code>&lt;div class="box"&gt;Hello&lt;/div&gt;</code></pre>
字符HTML 实体说明
<&lt;小于号
>&gt;大于号
&&amp;和号

pre 与 tab 的处理

<pre> 会保留制表符(Tab),但不同编辑器对 Tab 宽度的设置不同,可能导致显示不一致。建议使用空格替代制表符,或通过 CSS 设置 Tab 的显示宽度:

css
pre {
  tab-size: 4;      /* 设置 Tab 宽度为 4 个空格 */
  tab-width: 4;     /* Firefox 兼容 */
  -moz-tab-size: 4; /* Firefox 旧版 */
}

最佳实践

  1. 与 code 配合使用:展示代码时,使用 <pre><code>...</code></pre> 的组合
  2. 注意标签换行<pre><code> 之间不要有换行,避免顶部出现空行
  3. 处理溢出:使用 overflow-x: auto 允许水平滚动,避免截断代码
  4. 转义 HTML 实体:在 <pre> 中展示 HTML 代码时,记得转义 <>&
  5. 选择合适的 white-space:根据内容类型选择 prepre-wrappre-line
  6. 设置等宽字体:使用可靠的等宽字体栈,确保代码对齐

下一节

继续学习:strong 与 b

参考链接