Source Code

<div class="container py-5 d-flex justify-content-center">
  <div class="card bscsv-card">
    <div class="card-body p-3">
      <label class="form-label small fw-semibold">Paste CSV data</label>
      <textarea class="form-control mb-2" id="bscsvInput" rows="4">name,email,role
Dana Reyes,dana@acme.co,Admin
Marcus Lee,marcus@acme,Editor
,priya@acme.co,Viewer</textarea>
      <button type="button" class="btn btn-dark btn-sm fw-bold mb-3" id="bscsvParse">Preview import</button>

      <div class="d-none" id="bscsvResult">
        <p class="small mb-2">
          <span class="text-success fw-semibold" id="bscsvValid">0 valid</span> &middot;
          <span class="text-danger fw-semibold" id="bscsvInvalid">0 with errors</span>
        </p>
        <div class="table-responsive">
          <table class="table table-sm mb-0" id="bscsvTable"></table>
        </div>
      </div>
    </div>
  </div>
</div>

Bootstrap CSV Import Preview — Free HTML CSS JS Snippet

Bootstrap CSV Import Preview · Forms · Plain HTML, CSS & JS · Live preview

What's included

Features

A real character-by-character CSV line parser that correctly handles quoted fields containing commas
Per-row validation returns specific, readable error reasons rather than a single pass/fail flag
Column headers are read from the pasted data itself, not hardcoded to a fixed schema
Invalid rows are visually flagged with their exact error reasons shown inline, right below the row
A live valid-vs-error count summarizes the whole import before anything is actually committed

About this UI Snippet

Bootstrap CSV Import Preview — HTML, CSS & JavaScript

Screenshot of the Bootstrap CSV Import Preview snippet rendered live

Splitting a CSV line on a plain comma breaks the instant a field itself contains a comma inside quotes (a common case in a real spreadsheet export, like an address field) — parseLine() instead walks the line character by character, tracking an inQuotes flag that a " character flips, and only treats a comma as a field separator while that flag is false. That's a small but genuinely necessary piece of correctness a naive line.split(',') implementation gets wrong.

Every parsed row is validated independently through validateRow(), which returns an array of specific, human-readable error strings rather than a single "invalid" boolean — a row is flagged for a missing name and a badly formatted email separately, so the errors shown per row ("missing name, invalid email") tell the user exactly what to fix, not just that something's wrong.

The headers themselves come from the first parsed line rather than being hardcoded, so row[h] for each header h builds every row as a plain object keyed by whatever columns the pasted data actually has — pasting CSV data with different column names or a different column count renders correctly without any code changes, since nothing downstream assumes a fixed schema.

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 add a real file input (in addition to the paste textarea) that reads an uploaded .csv file via FileReader before parsing, or to add a "download only invalid rows" button so a user can fix and re-upload just the rows that failed validation.

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 5.3 CSV import preview tool, using the real Bootstrap CDN framework (bootstrap.min.css and bootstrap.bundle.min.js), not custom CSS made to resemble it.

Requirements:
- A textarea where a user can paste CSV text (header row plus data rows), and a "Preview import" button.
- Implement a character-by-character CSV line parser that correctly handles quoted fields containing embedded commas, rather than naively splitting each line on a plain comma.
- Read column headers from the first parsed line dynamically — don't hardcode a fixed set of expected columns.
- Validate each data row (e.g. requiring a non-empty name field and a plausibly formatted email field) and collect specific, readable error messages per row rather than a single pass/fail flag.
- Render every row in a table, visually flagging rows with validation errors and showing their specific error reasons inline, alongside a live summary count of valid rows versus rows with errors.

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
    Load the snippetA textarea holds sample CSV text: a header row plus three data rows, one with a malformed email and one with a missing name.
  2. 2
    Click "Preview import"A table renders every row, with a live count of valid rows vs. rows with errors above it.
  3. 3
    Look at the row with "marcus@acme" (missing a domain suffix)It's highlighted red with an inline "invalid email" message beneath it.
  4. 4
    Look at the row with an empty name fieldIt shows "empty" in italics for that cell and lists "missing name" as its specific error.
  5. 5
    Edit the textarea to fix an error, then click "Preview import" againThe corrected row moves from the error count into the valid count.

Real-world uses

Common Use Cases

DEV
Bulk user, contact, or product import tools
Let an admin catch and fix data problems before an import runs, rather than discovering failures after the fact.
Internal data migration and onboarding tools
A safety check before committing a bulk operation against real records.
Spreadsheet-to-database import flows
Pairs naturally with any backend import endpoint as the client-side preview step before submission.

Got questions?

Frequently Asked Questions

Yes — parseLine() tracks whether it's currently inside a quoted field and only treats a comma as a field separator when it isn't, correctly handling a value like "Reyes, Dana" as one field rather than splitting it into two.

No — it handles the common real-world cases (quoted fields, embedded commas) but not every edge case of the full CSV specification, like escaped quotes within a quoted field. For fully compliant parsing of arbitrary real-world CSV files, a dedicated library like PapaParse is the safer choice.

This demo checks for a non-empty name and a plausibly formatted email address as an illustrative example — validateRow() is the single place to add or change rules for whatever fields your real import actually requires.

Yes. Keep parseLine() and validateRow() as plain, framework-agnostic functions, store the parsed rows in component state, and map them to your framework's table-rendering approach instead of building an HTML string directly.