HTML <pre> and <code> reference
Jump to this section
Common attributes Jump to this section
Basic structures Jump to this section
<pre> preserves whitespace and line breaks exactly as written in HTML, rendering text in a monospace font. <code> marks up a fragment of computer code inline. They are most powerful when combined: <pre><code> is the standard pattern for displaying multi-line code blocks.
Key difference: Use <code> alone for inline code snippets within prose. Use <pre><code> together for freestanding multi-line code blocks.
Inline: use console.log() to debug.
function greet(name) {
return "Hello, " + name;
}
<!-- Inline code -->
<p>Use <code>console.log()</code> to debug.</p>
<!-- Block code -->
<pre><code>function greet(name) {
return "Hello, " + name;
}</code></pre>
Pre attributes Jump to this section
Whitespace preservation Jump to this section
<pre> renders text exactly as typed: spaces, tabs, and newlines are all preserved. This is its defining behavior and requires no attribute (it is built in).
Note: Content inside <pre> must have special HTML characters escaped (< for <, > for >, & for &). When inserting code via JavaScript, use textContent rather than innerHTML to handle this automatically.
indented
further
even more
<pre> indented
further
even more</pre>ASCII art and diagrams Jump to this section
<pre> is ideal for ASCII art, text diagrams, and any content where spatial positioning matters.
┌───────────┐
│ Client │
└─────┬─────┘
│ HTTP
┌─────▼─────┐
│ Server │
└───────────┘
<pre>
┌───────────┐
│ Client │
└─────┬─────┘
│ HTTP
┌─────▼─────┐
│ Server │
└───────────┘
</pre>width (deprecated) Jump to this section
The width attribute was used to set the maximum number of characters per line. It is deprecated, use CSS instead.
<!-- Deprecated, don't use -->
<pre width="40">...</pre>
<!-- Use CSS instead -->
<pre style="max-width: 40ch;">...</pre>
wrap (non-standard) Jump to this section
A non-standard attribute in some older browsers. Use CSS white-space instead for wrapping behavior.
<!-- Use CSS instead -->
<pre style="white-space: pre-wrap;">Long line that should wrap...</pre>
Code attributes Jump to this section
class (for language hints) Jump to this section
The most important attribute on <code> when inside a <pre> block. Syntax highlighting libraries like Prism.js and Highlight.js use a language-* class to identify the language and apply appropriate coloring.
Use language-* for Prism.js or just the language name for Highlight.js.
const x = 42;
<!-- Prism.js -->
<pre><code class="language-javascript">
const x = 42;
</code></pre>
<!-- Highlight.js -->
<pre><code class="javascript">
const x = 42;
</code></pre>
<!-- Other common values -->
<code class="language-html">
<code class="language-css">
<code class="language-python">
<code class="language-bash">
<code class="language-json">
<code class="language-sql">
Inline code Jump to this section
Inline <code> in prose
Jump to this section
Use <code> alone (without <pre>) for short inline references to variable names, function names, file paths, keyboard shortcuts, or any technical term.
Call Array.isArray() to check the type.
The config lives at /etc/nginx/nginx.conf.
Press Ctrl+S to save.
<p>Call <code>Array.isArray()</code>
to check the type.</p>
<p>The config lives at
<code>/etc/nginx/nginx.conf</code>.</p>
<p>Press <code>Ctrl+S</code> to save.</p>
Related elements Jump to this section
<kbd>
Jump to this section
Represents keyboard input. Use for documenting keyboard shortcuts and key combinations, distinct from <code> which represents program output or code.
Press Ctrl + C to copy.
<p>Press <kbd>Ctrl</kbd> + <kbd>C</kbd>
to copy.</p><samp>
Jump to this section
Represents sample output from a computer program. Use to display what a program prints or returns.
The program outputs: Hello, world!
<p>The program outputs:
<samp>Hello, world!</samp></p><var>
Jump to this section
Represents a variable in a mathematical expression or programming context.
The area equals width × height.
<p>The area equals
<var>width</var> × <var>height</var>.</p>Accessibility attributes Jump to this section
aria-label Jump to this section
Provides an accessible label for a code block when more context is useful for screen reader users.
<pre aria-label="JavaScript example showing array destructuring">
<code class="language-javascript">
const [a, b] = [1, 2];
</code>
</pre>
aria-describedby Jump to this section
References explanatory text by id to give screen reader users additional context about a code block.
<p id="snippet-desc">This function returns the sum of two numbers.</p>
<pre aria-describedby="snippet-desc"><code>
function add(a, b) {
return a + b;
}
</code></pre>
role="region" with aria-label Jump to this section
Wrap code blocks in a <figure> or <section> with a label to give them landmark semantics.
<figure aria-label="Code example">
<pre><code class="language-js">const x = 1;</code></pre>
<figcaption>Declaring a constant in JavaScript</figcaption>
</figure>
tabindex Jump to this section
Adding tabindex="0" to a <pre> makes it focusable with the keyboard, which is useful for long scrollable code blocks so keyboard users can scroll them.
<pre tabindex="0">
<code>...long code block...</code>
</pre>
Common attributes Jump to this section
id Jump to this section
Unique identifier. Useful for deep-linking to specific code examples and JavaScript targeting.
<pre id="installation-snippet">
<code class="language-bash">npm install my-package</code>
</pre>
<a href="#installation-snippet">See installation snippet</a>
class Jump to this section
Assigns CSS class names for styling or JavaScript selection. Also used by syntax highlighting libraries.
<pre class="code-block code-block--dark">
<code class="language-python">print("Hello")</code>
</pre>
data-* attributes Jump to this section
Custom attributes for storing metadata about a code block. Useful for copy buttons, language labels, and file names.
<pre data-language="javascript" data-filename="app.js" data-copyable="true">
<code class="language-javascript">const x = 1;</code>
</pre>
<script>
const block = document.querySelector('pre');
console.log(block.dataset.language); // "javascript"
console.log(block.dataset.filename); // "app.js"
</script>
translate Jump to this section
Set to "no" to prevent translation services from translating the code content (since code should stay in its original language).
<pre translate="no">
<code class="language-python">def greet():
print("Hello")</code>
</pre>
spellcheck Jump to this section
Set to "false" on editable code to prevent browser spell-check underlining in code editors.
<pre contenteditable="true" spellcheck="false">
<code>const myVariable = "hello";</code>
</pre>
Styling basics Jump to this section
<pre> and <code> carry minimal default browser styling, just a monospace font and whitespace preservation for <pre>. Most visual polish comes from CSS. The most common patterns are dark-theme code blocks, inline code pills, and copy-button wrappers.
Basic code block Jump to this section
function hello() {
console.log("Hello, world!");
}
pre {
background: #f3f4f6;
padding: 16px;
border-radius: 6px;
font-size: 14px;
overflow-x: auto;
}
pre code {
font-family: 'Monaco', 'Menlo',
'Consolas', monospace;
font-size: inherit;
background: none;
padding: 0;
}
Dark theme Jump to this section
function hello() {
console.log("Hello, world!");
}
pre {
background: #1e1e1e;
color: #d4d4d4;
padding: 16px;
border-radius: 8px;
font-size: 14px;
overflow-x: auto;
}With top bar / filename Jump to this section
HTML Structure:
<div class="code-wrapper">
<div class="code-header">app.js</div>
<pre><code>const express = require('express');
const app = express();</code></pre>
</div>
CSS:
.code-wrapper {
border-radius: 8px;
overflow: hidden;
border: 1px solid #e5e7eb;
}
.code-header {
background: #f3f4f6;
padding: 8px 16px;
font-size: 13px;
color: #6b7280;
border-bottom: 1px solid #e5e7eb;
font-family: monospace;
}
.code-wrapper pre {
margin: 0;
border-radius: 0;
}With language badge Jump to this section
const x = 42;
HTML Structure:
<div class="code-wrapper">
<span class="language-badge">JS</span>
<pre><code>const x = 42;</code></pre>
</div>
CSS:
.code-wrapper {
position: relative;
}
.language-badge {
position: absolute;
top: 10px;
right: 12px;
background: #3b82f6;
color: white;
font-size: 11px;
padding: 2px 8px;
border-radius: 4px;
font-family: monospace;
font-weight: 600;
letter-spacing: 0.5px;
}With line numbers Jump to this section
HTML Structure:
<div class="code-wrapper">
<div class="line-numbers">
1<br>2<br>3<br>4
</div>
<pre><code>function greet(name) {
const msg = "Hello, " + name;
return msg;
}</code></pre>
</div>
CSS:
.code-wrapper {
display: flex;
background: #1e1e1e;
border-radius: 8px;
overflow: hidden;
}
.line-numbers {
background: #252526;
color: #6b7280;
padding: 16px 12px;
text-align: right;
user-select: none;
line-height: 1.6;
}
.code-wrapper pre {
margin: 0;
color: #d4d4d4;
padding: 16px;
flex: 1;
}With copy button Jump to this section
const x = 42;
HTML Structure:
<div class="code-wrapper">
<button class="copy-btn">Copy</button>
<pre><code>const x = 42;</code></pre>
</div>
CSS:
.code-wrapper {
position: relative;
}
.copy-btn {
position: absolute;
top: 10px;
right: 10px;
padding: 4px 10px;
background: #374151;
color: #d1d5db;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 12px;
font-family: monospace;
transition: background 0.2s;
}
.copy-btn:hover {
background: #4b5563;
}Light theme with border Jump to this section
const x = 42;
console.log(x);
pre {
background: #fafafa;
border: 1px solid #e5e7eb;
border-left: 4px solid #3b82f6;
padding: 16px;
border-radius: 4px;
font-size: 13px;
overflow-x: auto;
}Scrollable with max height Jump to this section
line 1
line 2
line 3
line 4
line 5
line 6
line 7
line 8
pre {
max-height: 200px;
overflow-y: auto;
overflow-x: auto;
}
/* Custom scrollbar */
pre::-webkit-scrollbar {
height: 6px;
width: 6px;
}
pre::-webkit-scrollbar-track {
background: #2d2d2d;
}
pre::-webkit-scrollbar-thumb {
background: #555;
border-radius: 3px;
}
Inline code styles Jump to this section
Basic inline code Jump to this section
Call console.log() to debug.
code {
background: #f3f4f6;
padding: 2px 6px;
border-radius: 4px;
font-size: 0.875em;
font-family: 'Monaco', 'Menlo', monospace;
color: #374151;
}Colored inline code Jump to this section
Use fetch() to call APIs.
Run npm install to set up.
Avoid eval() in production.
.code-blue {
background: #dbeafe;
color: #1e40af;
}
.code-green {
background: #dcfce7;
color: #166534;
}
.code-red {
background: #fee2e2;
color: #991b1b;
}
Inline code with border Jump to this section
Check the package.json file.
code {
border: 1px solid #d1d5db;
background: #fafafa;
padding: 2px 6px;
border-radius: 4px;
font-size: 0.875em;
font-family: monospace;
}Keyboard key style Jump to this section
Press Ctrl + K to search.
kbd {
border: 1px solid #d1d5db;
border-bottom: 3px solid #9ca3af;
background: #f9fafb;
padding: 3px 8px;
border-radius: 4px;
font-family: monospace;
font-size: 0.875em;
color: #374151;
}Block code extras Jump to this section
Highlighted line Jump to this section
HTML Structure:
<pre><code>
<span class="line">function greet(name) {</span>
<span class="line highlighted-line"> return "Hello, " + name;</span>
<span class="line">}</span>
</code></pre>
CSS:
/* Mark specific lines */
.line {
display: block;
padding: 4px 16px;
}
.highlighted-line {
background: #264f78;
border-left: 3px solid #569cd6;
margin: 0 -16px;
padding: 4px 13px; /* Adjust for border */
}Diff style Jump to this section
HTML Structure:
<pre><code>
<span class="diff-add">+ const name = "Alice";</span>
<span class="diff-remove">- const name = "Bob";</span>
<span class="diff-unchanged"> console.log(name);</span>
</code></pre>
CSS:
.diff-add {
display: block;
background: #1a3322;
color: #4caf50;
padding: 4px 16px;
}
.diff-remove {
display: block;
background: #3b1212;
color: #f44336;
padding: 4px 16px;
}
.diff-unchanged {
display: block;
padding: 4px 16px;
}Responsive wrapping Jump to this section
/* Wrap long lines instead of horizontal scroll */
pre {
white-space: pre-wrap;
word-break: break-all;
}
/* Prefer scroll on wide screens, wrap on narrow */
@media (max-width: 640px) {
pre {
white-space: pre-wrap;
word-break: break-word;
}
}
JavaScript patterns Jump to this section
The most common JavaScript tasks for <pre> and <code> are copy-to-clipboard buttons, dynamic code insertion, syntax highlighting, and building interactive code editors.
Copy to clipboard Jump to this section
Add a copy button to every code block on the page.
const greeting = "Hello!";
console.log(greeting);
HTML Structure:
<div class="code-wrapper">
<button id="copy-btn" class="copy-btn">Copy</button>
<pre id="code-block"><code>const greeting = "Hello!";
console.log(greeting);</code></pre>
</div>
JavaScript:
// Single copy button
const btn = document.getElementById('copy-btn');
const block = document.getElementById('code-block');
btn.addEventListener('click', async () => {
const text = block.querySelector('code').textContent;
await navigator.clipboard.writeText(text);
btn.textContent = 'Copied!';
btn.style.background = '#10b981';
setTimeout(() => {
btn.textContent = 'Copy';
btn.style.background = '#374151';
}, 2000);
});
// Add copy buttons to every code block
document.querySelectorAll('pre').forEach(pre => {
const btn = document.createElement('button');
btn.textContent = 'Copy';
btn.className = 'copy-btn';
btn.addEventListener('click', async () => {
const text = pre.querySelector('code').textContent;
await navigator.clipboard.writeText(text);
btn.textContent = 'Copied!';
setTimeout(() => btn.textContent = 'Copy', 2000);
});
pre.style.position = 'relative';
pre.appendChild(btn);
});Insert code dynamically Jump to this section
Safely insert code content into a <pre><code> block.
// Click a button to insert code
HTML Structure:
<pre><code id="code">// Initial code</code></pre>
JavaScript:
const codeEl = document.getElementById('code');
// Safe insertion, textContent auto-escapes HTML entities
codeEl.textContent = `function add(a, b) {
return a + b;
}`;
// Unsafe, only use if the code is already escaped
// codeEl.innerHTML = escapedHtmlString;
// Helper to safely set code from a string
function setCode(elementId, code) {
document.getElementById(elementId).textContent = code;
}Read code content Jump to this section
Extract the text content of a code block.
const pi = 3.14159;
const area = pi * r * r;
const pre = document.getElementById('code-block');
// Get code text
const code = pre.querySelector('code').textContent;
// Get the language from the class
const codeEl = pre.querySelector('code');
const langClass = Array.from(codeEl.classList)
.find(c => c.startsWith('language-'));
const language = langClass?.replace('language-', '');
// e.g. "javascript"
// Count lines
const lineCount = code.split('\n').length;
console.log(${lineCount} lines of ${language});
Add line numbers dynamically Jump to this section
Inject line numbers into existing code blocks with JavaScript.
function add(a, b) {
return a + b;
}
const result = add(2, 3);
HTML Structure:
<pre id="code-block"><code>function add(a, b) {
return a + b;
}
const result = add(2, 3);</code></pre>
JavaScript:
function addLineNumbers(preId) {
const pre = document.getElementById(preId);
const code = pre.querySelector('code');
const lines = code.textContent.split('\n');
// Remove trailing empty line if present
if (lines[lines.length - 1] === '') lines.pop();
code.innerHTML = lines.map((line, i) => {
const num = String(i + 1).padStart(2, ' ');
const escaped = line
.replace(/&/g, '&')
.replace(//g, '>');
return `${num}${escaped}`;
}).join('\n');
}Highlight specific lines Jump to this section
Wrap specific lines in a highlight span after inserting code.
function greet(name) {
const msg = "Hello, " + name;
return msg;
}
HTML Structure:
<pre><code id="code">function greet(name) {
const msg = "Hello, " + name;
return msg;
}</code></pre>
JavaScript:
function highlightLines(codeId, linesToHighlight) {
const code = document.getElementById(codeId);
const lines = code.textContent.split('\n');
if (lines[lines.length - 1] === '') lines.pop();
code.innerHTML = lines.map((line, i) => {
const lineNum = i + 1;
const escaped = line
.replace(/&/g, '&')
.replace(//g, '>');
if (linesToHighlight.includes(lineNum)) {
return `${escaped}`;
}
return `${escaped}`;
}).join('');
}Simple editable code block Jump to this section
Make a code block editable using contenteditable.
// Edit me directly!
const x = 1 + 1;
HTML Structure:
<pre id="editable-pre" contenteditable="true" spellcheck="false">
<code>// Edit me directly!
const x = 1 + 1;</code>
</pre>
JavaScript:
const pre = document.getElementById('editable-pre');
// Make editable
pre.contentEditable = 'true';
pre.spellcheck = false;
// Focus styles
pre.addEventListener('focus', () => {
pre.style.outline = '2px solid #3b82f6';
});
pre.addEventListener('blur', () => {
pre.style.outline = '2px solid transparent';
});
// Read current content
pre.addEventListener('input', () => {
const currentCode = pre.textContent;
console.log('Code changed:', currentCode);
});Detect language from class Jump to this section
Read the language identifier from a code block's class name.
function getLanguage(codeElement) {
const classes = Array.from(codeElement.classList);
// Prism.js: "language-javascript"
const prismClass = classes.find(c => c.startsWith('language-'));
if (prismClass) return prismClass.replace('language-', '');
// Highlight.js: bare language name e.g. "javascript"
const known = ['javascript', 'python', 'html', 'css',
'bash', 'json', 'typescript', 'sql'];
return classes.find(c => known.includes(c)) ?? 'plaintext';
}
const code = document.querySelector('pre code');
console.log(getLanguage(code)); // "javascript"
Add copy buttons to all code blocks Jump to this section
Automatically wire up a copy button for every <pre> on the page.
function addCopyButtons() {
document.querySelectorAll('pre').forEach(pre => {
// Skip if already has a button
if (pre.querySelector('.copy-btn')) return;
const btn = document.createElement('button');
btn.textContent = 'Copy';
btn.className = 'copy-btn';
Object.assign(btn.style, {
position: 'absolute',
top: '10px',
right: '10px',
padding: '4px 10px',
background: '#374151',
color: '#d1d5db',
border: 'none',
borderRadius: '4px',
cursor: 'pointer',
fontSize: '12px',
fontFamily: 'monospace',
});
btn.addEventListener('click', async () => {
const code = pre.querySelector('code');
const text = (code ?? pre).textContent;
try {
await navigator.clipboard.writeText(text);
btn.textContent = '✓ Copied!';
btn.style.background = '#10b981';
} catch {
btn.textContent = 'Failed';
btn.style.background = '#ef4444';
}
setTimeout(() => {
btn.textContent = 'Copy';
btn.style.background = '#374151';
}, 2000);
});
pre.style.position = 'relative';
pre.appendChild(btn);
});
}
// Run on load and after dynamic content changes
document.addEventListener('DOMContentLoaded', addCopyButtons);
Count and list all code blocks Jump to this section
Inspect and enumerate code blocks on the page.
// Get all code blocks and their languages
const blocks = Array.from(document.querySelectorAll('pre code'));
const summary = blocks.map((code, index) => {
const langClass = Array.from(code.classList)
.find(c => c.startsWith('language-'));
const language = langClass?.replace('language-', '') ?? 'unknown';
const lines = code.textContent.trim().split('\n').length;
return { index, language, lines };
});
console.table(summary);
// ┌───────┬─────────────┬───────┐
// │ index │ language │ lines │
// ├───────┼─────────────┼───────┤
// │ 0 │ javascript │ 5 │
// │ 1 │ css │ 8 │
// └───────┴─────────────┴───────┘
// Count by language
const byLanguage = summary.reduce((acc, { language }) => {
acc[language] = (acc[language] ?? 0) + 1;
return acc;
}, {});
console.log(byLanguage); // { javascript: 4, css: 2, html: 3 }
Wrap code blocks automatically Jump to this section
Find bare <pre> elements and wrap them with a styled container.
function wrapCodeBlocks() {
document.querySelectorAll('pre:not(.wrapped)').forEach(pre => {
const code = pre.querySelector('code');
const langClass = code
? Array.from(code.classList)
.find(c => c.startsWith('language-'))
: null;
const language = langClass?.replace('language-', '');
// Create wrapper
const wrapper = document.createElement('div');
wrapper.className = 'code-wrapper';
// Create header if language is known
if (language) {
const header = document.createElement('div');
header.className = 'code-header';
header.textContent = language.toUpperCase();
wrapper.appendChild(header);
}
// Insert wrapper in DOM
pre.parentNode.insertBefore(wrapper, pre);
wrapper.appendChild(pre);
pre.classList.add('wrapped');
});
}
