Code Comparison Block — Before After Diff UI HTML CSS

Code Comparison Block · Layouts · Plain HTML, CSS & JS · Live preview

Share & Support

What's included

Features

CSS syntax token highlighting
.kw (purple), .fn (blue), .str (green), .bool (orange), .tag (pink) — VS Code Dark+ colours applied via span wrappers, no external library.
Full-width diff line markers
.bad-line and .good-line use display:block + negative margin to extend the background and border accent across the full panel width.
Copy with line number strip
replace(/^\d+\s*/gm, '') strips leading line numbers from innerText — pastes clean code without the number prefix.
Panel colour coding
.panel-before has a red border tint, .panel-after has a green border tint — at-a-glance bad/good visual identity for each panel.
Language badge
.lang-badge shows the language or framework per panel (JavaScript / React) — important when comparing cross-language rewrites.
Diff summary bar
Lines added/removed counts with a plain-English description — matches the GitHub pull request diff summary format.
Responsive stacking
Two-column grid on desktop, single column on mobile — code panels stack vertically on small screens for full readability.
Dark theme base
background: #0d1117 (GitHub dark) for code blocks, #1e293b (slate-800) for headers — the standard developer tool dark colour scheme.

About this UI Snippet

Code Comparison Block — CSS Syntax Highlight, Diff Line Markers & Copy-to-Clipboard

Screenshot of the Code Comparison Block snippet rendered live

Code comparison blocks are essential in developer tooling, technical documentation, tutorial sites, and code review interfaces — anywhere you need to show what changed and why. This snippet builds a production-quality before/after comparison layout with two dark-theme code panels, CSS-based syntax highlighting, red/green diff line markers with left border accents, copy-to-clipboard buttons, language badges, and a diff summary bar showing lines added and removed.

Technical blog posts, refactoring guides, changelog pages, and code review tools all need a clear visual diff format. The challenge is communicating change at a glance: readers must immediately see what was removed (red), what was added (green), and understand the structural difference — without reading every line. The left border accent on diff lines mirrors the GitHub and GitLab diff viewer pattern that developers already recognise.

CSS syntax highlighting without a library

Syntax highlighting is achieved with HTML <span> elements wrapping token groups, each with a colour class: .kw (keywords, purple #c084fc), .fn (function names, blue #60a5fa), .str (strings, green #86efac), .bool (booleans, orange #f97316), .tag (JSX tags, pink #f472b6). This manual approach is intentional for a snippet — no external library dependency. For a production code editor, use a library like Prism.js or highlight.js. The colour palette is derived from the VS Code Dark+ theme, the most widely-used editor colour scheme.

Diff line markers

Lines marked with .bad-line or .good-line use a display: block override to make the span fill the full line width, combined with negative margin (margin: 0 -16px; padding: 0 16px) to extend the background colour into the panel padding — matching GitHub's diff viewer behaviour. The left border (border-left: 2px solid) provides a secondary "this line changed" indicator for colour-blind accessibility. Line numbers also shift colour: red-tinted for removed lines, green-tinted for added lines.

Copy-to-clipboard with line number stripping

The copy function uses pre.innerText to get the rendered text, then strips line numbers with replace(/^\d+\s*/gm, '') — a multiline regex that removes the leading number + whitespace from each line. The result is clean, pasteable code. The Clipboard API (navigator.clipboard.writeText) is modern and requires HTTPS in production. The button transitions to a green "Copied!" state for 2 seconds, then reverts — the same pattern used in code block and copy button snippets.

Build with AI

Build, Understand, Optimize, and Extend It With AI

Rather than assuming the copy button just grabs the visible text, paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to explain exactly how copyCode() strips the leading line-number span from each .cl line using the regex replace, and why the diff line classes (bl and gl) use a negative-margin-plus-padding trick to extend their background color into the panel's own padding area. The same assistant can help you verify correctness — ask it to trace what would happen to the copied text if a code line legitimately started with a digit (like a line of actual code beginning with a number), and whether the current regex could strip real content by mistake. It's also a good partner for extending the block: ask it to add a unified single-panel diff mode with plus/minus prefixes instead of two side-by-side panels, wire real syntax highlighting via Shiki instead of hand-placed spans, or make the diff summary counts compute automatically by counting .bl and .gl lines instead of being hardcoded text. Treat the code less like a finished artifact and more like a starting point for a conversation.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build a side-by-side "before/after code comparison" block in plain HTML, CSS, and JavaScript — no diffing library, no syntax-highlighting library.

Requirements:
- Two code panels in a responsive grid (side-by-side on desktop, stacked on narrow viewports), each with its own header showing a Before/After label, a language badge, and an independent copy button — styled with a distinct border tint per panel (e.g. reddish for before, greenish for after).
- Render each line of code as its own block-level element containing a non-selectable line-number span followed by the actual code content, with inline span elements applying syntax-highlight colors to keywords, function names, strings, booleans, and JSX-style tags.
- Mark specific lines as "removed" or "added" by giving their line element a distinct class that applies a tinted background color extending across the full width of the panel (including into the panel's padding, via a negative-margin technique) plus a colored left border accent, with the line-number's own color also tinting to match.
- Each panel's copy button must extract only the actual code text (not the line-number prefixes) by reading each line element's text and stripping the leading number and whitespace before joining lines back together, then copy that clean text via the Clipboard API with an execCommand-based fallback, and show a temporary checkmark-icon "Copied!" state that reverts after about two seconds.
- Below both panels, render a summary bar showing a count of lines removed, a count of lines added, and a short plain-English note describing the nature of the change.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Step by step

How to Use

  1. 1
    Paste HTML, CSS, and JSTwo side-by-side dark code panels appear: "Before" (red border) showing imperative DOM code, and "After" (green border) showing the React state equivalent.
  2. 2
    Read the diff highlightsRed-background lines with a left red border show removed/bad code. Green-background lines with a left green border show the new/good code.
  3. 3
    Click Copy on either panelThe button copies the code to clipboard with line numbers stripped. It turns green and shows "Copied!" for 2 seconds, then resets.
  4. 4
    Read the diff summary barBelow the panels: −8 lines removed (red), +11 lines added (green), and a plain-English description of the change.
  5. 5
    Update code contentReplace the <code> content inside each <pre>. Wrap tokens in <span class="kw">, <span class="fn">, <span class="str"> etc. for highlighting.
  6. 6
    Mark diff linesWrap any line in <span class="bad-line">...</span> for red highlighting or <span class="good-line">...</span> for green highlighting.

Real-world uses

Common Use Cases

Technical blog posts and tutorials
Show before/after code in refactoring articles, migration guides, and "from X to Y" tutorials. The diff highlights make the change immediately scannable.
Changelog and release notes pages
Breaking change documentation benefits from a side-by-side diff showing the old API pattern next to the new one.
Code review UI in developer tools
Internal tooling, PR preview tools, and code quality dashboards use diff blocks to highlight the specific changes in a pull request.
Design system migration guides
Component library upgrade guides (v1 → v2) show the old usage pattern next to the new one — helps developers migrate without reading the full docs.
Interview prep and algorithm explanations
Technical interview prep sites compare inefficient and optimised solutions side-by-side with time/space complexity notes in the diff summary.
AI code review tools
AI-generated code improvement suggestions shown as before/after diffs — the format is familiar and immediately actionable for developers.

Got questions?

Frequently Asked Questions

Replace the manual span markup with Prism.js: add <script src="prism.js"> and use <code class="language-javascript">. Prism tokenises the code automatically. For a build-time solution, use Shiki (used by VitePress and Astro) which renders highlighted HTML at build time — zero client-side JS.

The <pre> already has overflow-x: auto. For very long lines, ensure the .code-block has white-space: pre (not pre-wrap) so lines don't wrap. Add min-width: 0 to the .code-panel in the grid to prevent flex/grid overflow.

Remove the grid and use a single <pre> with both .bad-line (red, − prefix) and .good-line (green, + prefix) lines interleaved. Add a + or character before each changed line's content, matching the git diff output format.

Create a CodePanel component accepting {title, language, code, variant} where code is a pre-highlighted HTML string (from Shiki/Prism) set via dangerouslySetInnerHTML. The parent CodeComparison takes {before, after, summary} props and renders two CodePanel instances side-by-side.