Source Code

<div class="container py-5 d-flex justify-content-center">
  <div class="card bscolvis-card">
    <div class="card-body p-3">
      <div class="d-flex justify-content-between align-items-center mb-2">
        <h6 class="fw-bold mb-0">Customers</h6>
        <div class="dropdown">
          <button class="btn btn-sm btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" data-bs-auto-close="outside">Columns</button>
          <ul class="dropdown-menu p-2" id="bscolvisMenu"></ul>
        </div>
      </div>
      <div class="table-responsive">
        <table class="table table-sm mb-0" id="bscolvisTable"></table>
      </div>
    </div>
  </div>
</div>

Bootstrap Table Column Visibility Toggle — Free HTML CSS JS Snippet

Bootstrap Table Column Visibility Toggle · Tables · Plain HTML, CSS & JS · Live preview

What's included

Features

Visible columns are tracked in a single Set, filtered once to drive both the header and every row
The header and body columns are always structurally guaranteed to match, since both render from the same filtered list
One column is genuinely locked always-visible, disabled at the checkbox level, not just discouraged
The dropdown stays open across multiple checkbox clicks via Bootstrap's real auto-close="outside" option
Adding a new toggleable column is a one-line addition to the COLUMNS array

About this UI Snippet

Bootstrap Table Column Visibility Toggle — HTML, CSS & JavaScript

Screenshot of the Bootstrap Table Column Visibility Toggle snippet rendered live

Visible columns are tracked as a Set of column keys rather than a boolean flag per column scattered across variables, which is what makes renderTable() a one-line filter — COLUMNS.filter(c => visible.has(c.key)) — instead of a chain of individual if-checks per column. Both the header row and every body row map over that exact same filtered cols array, so a header and its corresponding data cells can never fall out of sync about which columns actually exist.

The Name column is marked locked: true and its checkbox renders disabled — table content with no visible identifying column at all is close to meaningless, so removing the one column every row needs to make sense isn't offered as an option in the first place, rather than being technically possible and just discouraged.

The dropdown uses Bootstrap's real data-bs-auto-close="outside" option, the same technique this collection uses in bootstrap-multi-select-dropdown and bootstrap-notification-center-dropdown — without it, Bootstrap's default dropdown behavior closes the menu the instant the first checkbox is clicked, which would make toggling more than one column at a time frustratingly slow.

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 persist the user's column visibility choices to localStorage so they're remembered on their next visit, or to add drag handles in the dropdown checklist letting the user also reorder the visible columns, not just show/hide them.

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 table with a column visibility toggle dropdown, using the real Bootstrap CDN framework (bootstrap.min.css and bootstrap.bundle.min.js), not custom CSS made to resemble it.

Requirements:
- A table with at least 5 columns and a few sample rows, plus a dropdown button labeled "Columns" (using Bootstrap's real dropdown component with data-bs-auto-close="outside" so it stays open across multiple checkbox clicks).
- The dropdown contains one checkbox per column, all checked by default. Track visible columns in a single Set of column keys, and render both the table header and every row's cells by filtering the full column list against that Set — never by independently toggling individual header or cell elements.
- Unchecking a column's checkbox must immediately hide that column from the table (both header and every row); rechecking must restore it.
- Exactly one column (e.g. the primary identifying column, like a name) must be structurally locked always-visible — its checkbox should be disabled and unclickable, not just pre-checked.

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 five-column customer table shows in full, with a "Columns" dropdown button above it.
  2. 2
    Click "Columns"A checklist opens showing all five columns checked, with Name greyed out and unclickable.
  3. 3
    Uncheck "MRR"The MRR column disappears from the table immediately, and the dropdown stays open.
  4. 4
    Uncheck "Signed up" too, without closing the dropdown firstBoth columns can be toggled off in one open dropdown session, since it doesn't auto-close on the first click.
  5. 5
    Try to uncheck "Name"Its checkbox is disabled — it can never be hidden.

Real-world uses

Common Use Cases

Admin data tables with more columns than fit comfortably
Pairs with bootstrap-sortable-data-table or bootstrap-sticky-table-header-scroll for a fuller-featured data grid.
DEV
Internal reporting and analytics dashboards
Let a user focus on only the columns relevant to their current task, hiding the rest.
CRM and customer-management tools
A standard feature in most real CRM table views, letting users customize which fields they see.

Got questions?

Frequently Asked Questions

A row with every identifying column hidden would be meaningless — locking the one column every row needs to actually be readable prevents a user from accidentally hiding every useful piece of context at once.

Bootstrap's dropdown closes itself by default on any click inside it, including a checkbox click — without this option, toggling a second or third column would require reopening the dropdown after every single click.

Yes — add an entry to the COLUMNS array with a key, label, and locked flag, and add matching data to each row in ROWS keyed the same way; renderMenu() and renderTable() both iterate the array generically.

Yes. Keep the visible column keys in a Set (or equivalent) in component state, and derive both the checklist and the filtered table columns from it in your render function — the locked-column logic carries over directly.