Summary (TL;DR): How to put code on a website so people can read and reuse it: the markup underneath, syntax highlighting, choosing a theme that works in light and dark, line numbers, the copy button, accessibility, and the mistakes that make code unusable on a phone.

Showing code on a website looks trivial until you do it, at which point you discover that the quotes got converted, the block scrolls the whole page sideways on a phone, the copy button copies the line numbers, and the theme you picked is invisible in dark mode.
None of these are hard problems. They are just details that nobody tells you about until a reader emails to say your example does not run, because a straight quote became a curly one somewhere between your editor and their clipboard.
This guide covers the whole job: the markup underneath, whether you need a highlighting library, choosing a theme, the settings worth turning on, and the accessibility and mobile details that decide whether the code is usable at all.
The Markup Underneath
Every approach ends up producing the same two elements, so it is worth knowing what they do.
A <pre> element preserves whitespace and line breaks exactly as written. Without it, a browser collapses your indentation into single spaces and your carefully formatted code becomes one paragraph. A <code> element says the content is code, which is what screen readers and other tools use to announce it as such.
They are used together, the <code> inside the <pre>, and the reference documentation for the pre element is short and worth a skim once.
Two practical consequences follow. Anything you paste needs escaping if it contains angle brackets or ampersands, otherwise the browser tries to render your example rather than display it. And whatever tool you use, the copy behaviour depends on what ended up inside those elements, which is why line numbers implemented as text get copied and line numbers implemented in the styling do not.
Do You Need Highlighting at All
Syntax highlighting colours keywords, strings and comments so the structure of the code is visible at a glance. It genuinely helps reading, and it is not free.
Skip it if you show code occasionally: a command to run, a line to add to a config file, one example in a blog post. Monospaced text in the right markup is entirely readable, loads instantly, and never gets a colour wrong.
Use it if code is a regular part of your content: documentation, tutorials, a developer blog, an API reference. There, consistent colouring is part of how readers navigate, and doing it by hand is not an option.
The cost is a script and a stylesheet, and how much that matters depends on when they run. Highlighting done when the page is built costs the reader nothing at all. Highlighting done in the browser costs a download and a moment of unstyled code before it takes effect, which is the flash people notice on slow connections.
If you are curious about how the colouring actually works, we built one from scratch in building a code syntax highlighter in React, which is a good way to understand what the libraries are doing for you.
Choosing a Theme
The theme decision causes more debate than it deserves, and there are only three things that matter.
- Contrast has to be real. Many popular themes were designed for editors on large screens, and their comment colours are close to unreadable on a phone in daylight. Check the dimmest colour in the theme against its background before adopting it.
- It has to work in both page modes. If your site has a dark mode, your code block needs a variant for each, or it will either glow or vanish. Choosing a theme family that ships both is the easy answer.
- It should be one theme, everywhere. Different colouring on different pages makes a site feel assembled from parts. Pick one and apply it site wide.
On the dark against light question specifically: a dark block on a light page is a deliberate and common choice, because it marks code as a distinct kind of content without needing a border or a label. It is a good default, provided you have a light variant for readers using a dark page.
The Settings Worth Having
Most snippet tools offer the same handful of options. These are the ones that change the reader's experience.
| Setting | Turn it on when | Watch out for |
|---|---|---|
| Copy button | Always | It must copy the code only, with no numbers and no prompt characters |
| Line numbers | You refer to lines in the text | Whether they end up in the clipboard |
| Line wrapping | Prose-like content, long URLs | It changes how indentation reads |
| Horizontal scroll | Real code with long lines | The block must scroll, not the page |
| Language label | You show several languages | Keep it small and consistent |
| Filename header | The snippet belongs in a specific file | More useful than most people expect |
| Line highlighting | Drawing attention to a change | Only meaningful if the text says why |
The copy button is the one that matters most, and it is the one most often broken. Test it by copying and pasting into a plain text editor, not by looking at it.
The Copy Button, and How It Goes Wrong
Readers copy code. That is what it is there for, and there are four ways to make it fail.
- Line numbers in the clipboard. The classic. Every pasted line arrives with a digit in front of it, and the reader has to strip them by hand.
- The shell prompt copied too. If your terminal examples start with a dollar sign, that character should not come along. Either leave it out or make it unselectable.
- Trailing whitespace and a missing newline. Trivial and irritating, and it produces a mangled first line when pasted into a terminal.
- Nothing at all on the phone. Copy behaviour varies on mobile browsers, so test it on a real phone.
The second failure mode deserves emphasis because it causes real support tickets. Someone copies your install line, pastes it with the prompt character, and gets an error message about a command that does not exist. They then conclude your instructions are wrong.
Getting the Snippet Onto the Page
How you add a code block depends entirely on what your site is built with, and the differences are where most of the mangled quotes come from.
- A static site or anything markdown based. The easy case. Fenced code blocks with a language name, highlighted at build time, nothing to load in the browser.
- WordPress. The editor has a code block, and using it rather than a paragraph is the whole trick. Pasting code into a normal paragraph is what converts your quotes.
- Squarespace and similar builders. There is usually a code or markdown block available. What varies is whether the plan allows custom code at all, which is worth checking before planning around it.
- Webflow and Wix. Both have an embed element that accepts HTML, which is enough for a properly marked up block or a widget snippet.
- Notion and documentation tools. Code blocks are built in and generally good, and the constraint is that you get their theme rather than yours.
- Anywhere with no code block at all. This is where an embedded widget earns its place, since it needs one embed field rather than control over the page markup.
Whichever it is, publish one snippet and check three things on the live page: that a quotation mark is still straight, that indentation survived, and that copying gives you exactly what you wrote. Those three catch nearly every platform specific problem.
Terminal Commands Are a Special Case
Commands to run in a terminal cause more support requests than any other kind of snippet, and the reasons are all avoidable.
Decide about the prompt character. A leading dollar sign shows that this is a shell command, and it breaks copying unless it is excluded from the clipboard. If you are unsure, leave it out: a command without a prompt is unambiguous and always safe to paste.
Show the output separately. Mixing a command and its output in one block means anyone copying the whole thing pastes the output too. Two blocks, or a clear label, solves it.
Handle operating system differences honestly. If the command differs between systems, show both rather than picking one and hoping. Tabs are nice; two labelled blocks are fine.
Be careful with elevated commands. Anything asking a reader to run something with administrator rights deserves a sentence explaining what it does. People paste these without reading, which is precisely why you should say.
Watch multiline commands. Continuation characters at line ends are easy to break when a page wraps them. Test the copy on a narrow window, where the wrapping actually happens.
Code on a Phone
A good share of technical reading happens on a phone, usually to check something rather than to type it, and code blocks handle that badly by default.
Keep the block scrolling, not the page. A single long line should scroll inside its own box. If it stretches the container, the entire page scrolls sideways and every other element goes with it.
Do not shrink the font below readable. Fitting more characters per line by making the text tiny helps nobody. Scrolling a readable block beats squinting at a complete one.
Break long lines in the source where you can. A command with six flags can usually be written across several lines, which reads better everywhere, not just on a phone.
Keep examples short. Thirty lines on a small screen is a lot of scrolling. Show the part that matters and link to the full file.
The test takes a minute: open the page on your own phone and try to read the longest snippet on it. Almost everyone who does this changes something.
Speed, and Where the Cost Sits
Code blocks look static and can be surprisingly expensive, depending on where the work happens.
Highlighting at build time costs the reader nothing. The colours arrive as part of the HTML, and there is no script involved at all. If your site is generated, this is the option to take, and it is usually one setting away.
Highlighting in the browser means downloading a library and running it after the page loads. On a fast connection it is imperceptible. On a slow one the reader sees plain code, then a flash as the colours arrive, which is the effect people describe as the page jumping.
Language packs matter more than the library. Most highlighting libraries let you load only the languages you use. Loading everything, when your site shows two languages, is the common and invisible waste here.
Fonts are the other half. A monospaced web font is another download for a small part of the page. The fonts already on the reader's device are good enough for code and cost nothing.
The general rule: do the work once, when the page is built, and let the reader receive the result. Anything that has to happen in their browser should be there because it genuinely could not happen earlier.
Accessibility
Code blocks are read by more kinds of software than most content, so a few details go a long way.
Use the proper elements. The pre and code pair is what tells assistive technology that this is code rather than a paragraph with strange spacing.
Make a scrollable block reachable by keyboard. A block that scrolls sideways must be focusable, otherwise a keyboard user cannot see the right hand side of it at all.
Never rely on colour alone to make a point. If a highlighted line is important, say so in the surrounding text as well.
Check the contrast of the theme, not just the page. Comment colours in popular themes are frequently the lowest contrast text on a whole site.
Give the copy button a real label. An icon with no accessible name is a button that announces itself as nothing.
Writing Snippets People Can Use
The editorial side matters more than any setting, and it is the part most technical pages skip.
- Say what it does before showing it. One line above the block. Readers scanning for the right example find it by the sentence, not by the code.
- Show the smallest thing that works. Strip logging, error handling and unrelated configuration unless the example is about them.
- Make placeholders obvious. Something clearly not real, in a consistent style, so nobody ships your example key.
- Say where it goes. A filename header answers the question people ask most often about a snippet.
- Keep it runnable. If someone can paste it and see it work, they trust everything else on the page more.
- Version it if it will age. A note about which version of the tool an example is for costs a few words and saves a lot of confusion later.
Where Snippets Belong Beyond Documentation
Code blocks are not only for developer docs, and a few uses are easy to miss.
- Install and embed instructions. Any product that gives customers a snippet to paste should present it as code with a copy button, not as a paragraph.
- Support articles. A configuration line in a help centre is code, and treating it as such removes an entire class of typing errors.
- Portfolios. A short, well presented snippet says more about how someone works than a screenshot of an editor. We covered the wider version of this in web developer portfolio tips.
- Marketing pages for technical products. A three line example above the fold is the fastest way to show a developer audience what your product actually does.
- Internal wikis and runbooks. Where a copy button that works is worth more than any styling.
Keeping Snippets Correct
Code on a website rots faster than prose, because the thing it describes keeps changing while the page does not.
- Keep one canonical copy where you can. The same install snippet is usually on a marketing page, in the docs and in a help article. Three copies means two wrong ones eventually.
- Note the version an example applies to. A short line under the block. It is the difference between a reader knowing the example is old and concluding your product is broken.
- Actually run them, occasionally. A yearly pass where someone pastes each snippet and checks it works finds more than any review.
- Give people a way to report a broken example. A line at the end of the page. Readers are usually willing and rarely have anywhere to say it.
- Fix the source, not the page. If the snippet is wrong on the page and right in the repository, the page will be wrong again next time.
None of this is elaborate, and the payoff is disproportionate: a technical page with examples that run is trusted for everything else it says, and one with a single broken example is quietly doubted throughout.
Problems and Their Fixes
- Quotes and dashes changed. A rich text editor applied typographic substitutions. Use a code block or a raw HTML block, and check a quotation mark in the published page.
- The example renders instead of showing. Angle brackets were not escaped, so the browser is treating your HTML example as HTML.
- The page scrolls sideways on a phone. The block is stretching its container. Give it its own horizontal scroll.
- Copying includes the line numbers. They are text rather than styling. Either turn them off or switch to an implementation that keeps them out of the clipboard.
- The code flashes unstyled then colours in. Highlighting is running in the browser. Doing it at build time removes the flash entirely.
- Indentation collapsed. The pre element is missing, or a platform stripped it.
- The theme is unreadable in dark mode. A fixed theme on a page that switches. Use a theme with both variants.
- The wrong language is highlighted. Either the language was not declared or it was guessed. Declare it explicitly on every block, since automatic detection is reliable right up until it is not.
When something looks wrong, check the published page rather than the editor. Almost every problem on this list is introduced between the two, and the editor will keep showing you the version you typed.
Getting Started
The short path. Put your code in a pre and code pair, escape anything with angle brackets, and give the block its own horizontal scroll. Add a copy button and test it by pasting into a plain editor. Pick one theme with a light and a dark variant and use it everywhere. Turn line numbers on only if your text refers to them, and check what ends up in the clipboard when you do.
If your site is not somewhere you can add a highlighting library, or you would rather not maintain one, a code snippets widget gives you the highlighting, the theme, the line numbers and the copy button as settings, on any platform that takes an embed.



