Bootstrap Code Block With Copy + Line Numbers — Free HTML CSS JS Snippet

Bootstrap Code Block With Copy + Line Numbers · Misc · Plain HTML, CSS & JS · Live preview

What's included

Features

Line numbers and code lines are generated from the same array, so they can never fall out of sync
Lightweight line-based highlighting for comments and quoted strings, no external syntax highlighter required
Copy grabs the original plain-text source array, never the rendered, HTML-tagged markup
The gutter and code pane scroll independently, so long lines don't push line numbers out of view
A file-name header bar gives the block real context, like a familiar code editor tab

About this UI Snippet

Bootstrap Code Block With Copy + Line Numbers — HTML, CSS & JavaScript

Screenshot of the Bootstrap Code Block With Copy + Line Numbers snippet rendered live

Keeping the line-number gutter and the code perfectly aligned is the entire design challenge here, and this snippet solves it by generating both from the exact same CODE array — gutter.innerHTML maps over CODE.length to produce sequential numbers, and pre.innerHTML maps over the same array to render each line, so a gutter number and its code line can never drift apart even if lines are added or removed, since both are derived from one array's length and index rather than counted separately by hand.

Highlighting is deliberately minimal and line-based: highlight() checks whether a trimmed line starts with # to color it as a comment, and separately wraps any double-quoted text in a string-colored span — good enough for a shell script or a config snippet without pulling in a full tokenizing syntax highlighter for a handful of lines.

The important correctness detail is what "Copy" actually copies: CODE.join('\n') — the original, plain-text array — not the DOM's rendered innerHTML. Copying rendered HTML would paste literal <span class="bscode-comment"> tags into whatever the user pastes into; copying from the source array guarantees the clipboard always holds exactly the real code, with no highlighting markup ever leaking into it.

Build with AI

Build, Understand, Optimize, and Extend It With AI

Hand this snippet to an AI coding assistant like Claude and ask it to swap in highlight.js (loaded from a CDN) for genuine multi-language syntax highlighting while keeping the same gutter-from-array line-numbering approach, or to add a "Download as file" button using a Blob the same way bootstrap-two-factor-backup-codes downloads its codes.

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 Bootstrap-styled code block with line numbers and a copy button, using the real Bootstrap CDN framework (bootstrap.min.css and bootstrap.bundle.min.js) for the surrounding card/header only — the code block itself should use plain dark-theme CSS.

Requirements:
- Store the code as an array of individual lines, one string per line.
- Render a line-number gutter and the code pane from that same array, so the numbers and lines always stay in sync regardless of how many lines exist.
- Apply simple line-based highlighting: lines starting with a comment character get one color, and double-quoted substrings within any line get a different color — no external syntax highlighting library required.
- A "Copy" button must copy the original plain-text lines joined with newlines, never the rendered HTML with highlighting markup included, and show a temporary "Copied!" confirmation that reverts automatically.
- The gutter and the code pane should scroll independently so a long line doesn't push the line numbers out of view.

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.

Source Code

<div class="container py-5 d-flex justify-content-center">
  <div class="card bscode-card">
    <div class="bscode-header">
      <span class="small fw-semibold">install.sh</span>
      <button type="button" class="btn btn-sm btn-outline-light" id="bscodeCopy">Copy</button>
    </div>
    <div class="bscode-body">
      <div class="bscode-gutter" id="bscodeGutter"></div>
      <pre class="bscode-pre" id="bscodePre"></pre>
    </div>
  </div>
</div>

Step by step

How to Use

  1. 1
    Load the snippetA dark code block appears with line numbers 1 through 9 in the gutter, comments and quoted strings colored differently from plain code.
  2. 2
    Scroll the code horizontally if a line is longThe gutter stays fixed in place while only the code pane scrolls, since they're two separate flex children.
  3. 3
    Click "Copy"The button briefly reads "Copied!" before reverting, and the clipboard holds the plain script text with no HTML markup in it.
  4. 4
    Paste it anywhereIt pastes as clean, runnable shell script text, line numbers and coloring both correctly excluded.

Real-world uses

Common Use Cases

DEV
Documentation, README pages, and setup guides
Pairs with bootstrap-copy-to-clipboard-feedback for the same core copy interaction applied to a single value instead of a whole script.
API documentation showing example requests
Show a curl command or SDK usage example exactly as a developer would want to copy and run it.
Learning to keep derived UI in sync from one source
The gutter-from-array technique here generalizes to any UI where two visual elements must always describe the same underlying list.

Got questions?

Frequently Asked Questions

For a short, illustrative code block, a full tokenizer is often more weight than the content warrants — the line-based comment/string check here covers the common visual cases with zero dependencies, though swapping in highlight.js is a reasonable upgrade for genuinely complex multi-language code.

Nothing else needs to change — both the gutter and the code pane re-derive their length and numbering from CODE.length automatically the next time the page loads.

No — CODE.join('\n') copies only the actual script content; the numbers exist purely in the separate gutter element and were never part of the copied text to begin with.

Yes. Keep CODE as a plain array, map it to both the gutter numbers and the highlighted lines in the render function, and keep the Copy handler joining the original array rather than reading back from the rendered DOM.