Code Block — Free HTML CSS JS Snippet

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

Share & Support

What's included

Features

CSS syntax highlighting: .kw .fn .str .cm .num .op span classes — no library
Colour scheme matches VSCode Dark+ — familiar to all developers
Line numbers: separate div with matched font/line-height, user-select:none
Copy button: Clipboard API + .copied class green feedback + 2s reset
Language tabs: data-lang attribute, setLang() swaps SNIPPETS object entry
macOS-style dots: red/yellow/green circles in header bar
Dark terminal frame: #0f172a background, overflow-x: auto for long lines
Monospace font stack: Fira Code → Consolas → monospace fallback

About this UI Snippet

Code Block — Syntax Highlighting, Copy Button, Language Tabs & Line Numbers

Screenshot of the Code Block snippet rendered live

Every developer blog, documentation site, tutorial, and technical landing page needs a well-styled code block. Syntax highlighting makes code dramatically more readable — keywords, strings, function names, and comments in distinct colours allow the reader to parse structure visually before reading text. This snippet provides a complete styled code block: a dark terminal frame with macOS-style dots, CSS-based syntax highlighting using span classes, line numbers, a copy-to-clipboard button with success feedback, and language tab switching.

CSS-based syntax highlighting without a library

The syntax highlighting uses CSS classes applied via span elements inline in the HTML: .kw (keywords, purple), .fn (function names, blue), .str (strings, green), .cm (comments, muted grey italic), .num (numbers, orange), .op (operators, light grey). These map to the classic VSCode Dark+ colour scheme that developers recognise immediately. No Prism.js, no Highlight.js — just CSS classes on span elements.

Line numbers with CSS

The line numbers column uses a separate div with textContent set to numbers joined by newlines: lines.map((_,i) => i+1).join('\n'). It uses the same font-family, font-size, and line-height as the code block to ensure perfect vertical alignment. user-select: none prevents accidental line number selection when users copy code.

The copy button feedback pattern

navigator.clipboard.writeText() returns a Promise. On resolve, the button label changes to "Copied!" and a .copied class applies a green colour scheme. A setTimeout resets both after 2 seconds. The Clipboard API is available in all modern browsers over HTTPS. The code text is extracted via code element textContent, which strips HTML tags from the span elements.

Language tab switching

Three SNIPPETS objects hold pre-highlighted HTML for each language. setLang(lang) updates the active tab, re-renders the code and line numbers, and updates the language label. The pre-highlighted HTML approach avoids runtime parsing — the highlighting is applied at author time.

Adapting for your content

Replace the SNIPPETS objects with your own code. Apply the .kw, .fn, .str, .cm, .num span classes to your code tokens. For automatic syntax highlighting at scale, use Prism.js or Shiki server-side to generate the highlighted HTML that replaces the span-based approach in this snippet.

Extending with a filename tab

Add a filename display between the browser dots and the language label: <span class="cb-filename">api/users.js</span>. This is standard in documentation sites where the same code block appears across multiple files. Update via JavaScript when the language tab changes: setLang() updates both the lang-label and filename spans simultaneously.

Build with AI

Build, Understand, Optimize, and Extend It With AI

Rather than assuming the pre-baked HTML strings in SNIPPETS are just decoration, paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to explain exactly why the code is stored as HTML strings with span tags already embedded rather than tokenized at render time, and why copyCode() reads textContent instead of innerHTML to get the clipboard value. The same assistant can help you assess the tradeoffs — ask whether hand-authoring highlighted HTML like this scales past three small snippets, and at what point switching to a build-time highlighter like Shiki becomes worth the added tooling. It's also a good partner for extending the block: ask it to add line-highlighting for specific lines via a data attribute, add a fourth language tab, or wire the copy button to a click-tracking event so you can measure which snippet gets copied most. 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 terminal-style "code block" with language tabs in plain HTML, CSS, and JavaScript — no syntax-highlighting library required, but written so a real one could later replace the markup approach.

Requirements:
- Store each language's example as pre-authored HTML source (a template string containing span elements with semantic class names like keyword, function, string, comment, number, operator) rather than plain unstyled text, so switching languages swaps in a complete pre-highlighted block via innerHTML.
- A header bar styled like a terminal window: three colored circular dots (red, yellow, green) on the left, a centered language label showing the currently active language's display name, and on the right a copy button plus a small set of language-tab buttons.
- Clicking a language tab must update that tab's active visual state, swap the displayed code and line numbers to match the newly selected language's stored snippet, and update the centered language label text.
- A separate line-numbers column, generated by splitting the current snippet's raw text on newlines and rendering sequential numbers, using the exact same font family, font size, and line height as the code area so the numbers stay vertically aligned with their corresponding code lines, and marked non-selectable.
- The copy button must extract the code element's textContent (not innerHTML) so the highlighting span tags are stripped and only the plain, pasteable source text is copied, using the Clipboard API with a hidden-textarea execCommand fallback, and must show a temporary green "Copied!" state that reverts to "Copy" after about two seconds.
- Apply a consistent, VSCode-like color palette across the span classes (keywords, function names, strings, comments, numbers, operators) so all three language examples look visually cohesive despite being independently authored.

Step by step

How to Use

  1. 1
    Click the language tabs to switch code examplesClick JS, Python, or TS to switch between language examples. The code, line numbers, and language label update immediately. Each language shows the same fetch-and-render logic in different syntax.
  2. 2
    Click Copy to copy the code to clipboardClick the Copy button to copy the current code to clipboard. The button turns green and shows "Copied!" for 2 seconds, then resets. The textContent is copied without HTML tags.
  3. 3
    Replace the code contentUpdate the code strings in the SNIPPETS object. Apply .kw, .fn, .str, .cm, .num CSS classes via span elements to add syntax highlighting to your own code. Or paste plain code without spans for an unstyled code block.
  4. 4
    Add or remove language tabsAdd a new entry to SNIPPETS and a matching .lang-tab button with data-lang and onclick="setLang('newlang')". Remove unused language objects and their tab buttons.
  5. 5
    Use Shiki or Prism.js for automatic highlightingFor production documentation sites, replace the manual span approach with server-side highlighting. In Next.js, use Shiki createHighlighter() to generate highlighted HTML from raw code strings at build time. This snippet's CSS colour variables stay compatible with both approaches.
  6. 6
    Export in your formatClick "HTML" for a standalone file, "JSX" for a React component accepting code and language props, or "Tailwind" for a React + Tailwind CSS version.

Real-world uses

Common Use Cases

Developer blog and tutorial code examples
Every technical blog post needs syntax-highlighted code blocks. This snippet provides the complete visual treatment — dark background, line numbers, copy button, language label — that readers expect from professional technical writing platforms.
Documentation site and API reference pages
API documentation requires code blocks for request/response examples, integration snippets, and configuration samples. The language tab switcher lets documentation show the same concept in multiple languages side by side.
Landing pages showing integration snippets
SaaS product landing pages frequently show a code snippet as the primary hero element ("Add this to your project in 3 lines"). The terminal frame communicates developer credibility and positions the product as technical and well-engineered.
Interactive coding tutorials and learning platforms
Coding education platforms show code blocks at every step. Wire the copy button to a tracking event to measure which snippets users copy most. Add a "Run" button that passes the code to a sandboxed evaluation environment.
Portfolio projects and case study technical sections
Developer portfolios showcase technical depth with code samples. The styled code block signals attention to detail and design quality — it communicates that you care about presenting your code well, not just writing it.
Onboarding flows showing setup and installation commands
SaaS and developer tool onboarding frequently shows installation commands (npm install, pip install, curl commands). The copy button is essential here — users expect one-click copy for any command they need to run in their terminal.

Got questions?

Frequently Asked Questions

The copy function reads code element textContent (not innerHTML): const text = document.getElementById("cb-code").textContent. textContent returns only the visible characters without any HTML markup — the span tags used for syntax highlighting are stripped automatically. This gives the user clean, pasteable code without any markup artifacts.

For production use, use a server-side highlighting library. In Next.js: import { createHighlighter } from "shiki"; const hl = await createHighlighter({ themes: ["github-dark"], langs: ["javascript"] }); const html = hl.codeToHtml(code, { lang: "javascript", theme: "github-dark" }). Set the returned HTML as innerHTML of your code element. The Shiki output is compatible with this code block's CSS structure — just remove the manual span classes and use Shiki's classes instead.

Add a data-highlight attribute listing which lines to highlight: <pre data-highlight="3,7,8">. In JavaScript, after render(), read the attribute: const highlighted = pre.dataset.highlight?.split(",").map(Number) || []. Then wrap those line numbers in the code HTML: split the code by newline, wrap lines at highlighted indexes in <span class="hl-line">...</span>, rejoin. Add .hl-line { background: rgba(99,102,241,0.1); display: block; margin: 0 -16px; padding: 0 16px; } to the CSS.

Click "JSX" to download. Accept code (string), lang (string), and language (display label string) as props. Use dangerouslySetInnerHTML={{ __html: highlightedCode }} for the code element to render the pre-highlighted HTML. In Next.js, use Shiki in getStaticProps or a Server Component to generate the highlighted HTML at build time, passing it as a prop. For React without SSR, use Prism.js or highlight.js in a useEffect to highlight after mount.