Snippets Responsive

Bootstrap 5 Responsive Table with Search and Sorting

A clean orders table with status badges, tabular numbers, a live search box and sortable columns. On phones each row collapses into a labelled card.

Bootstrap 5 No jQuery Jun 2019 2.6K views

<section class="wdw-stage">
  <div class="container" style="max-width:1040px">
    <div class="wdw-card overflow-hidden">
      <div class="d-flex flex-wrap align-items-center justify-content-between gap-3 p-4 pb-3">
        <div>
          <span class="wdw-eyebrow">Orders</span>
          <h1 class="wdw-heading h4 mt-1 mb-0">Recent orders</h1>
        </div>
        <div class="position-relative order-search w-100 w-md-auto">
          <label for="orderSearch" class="visually-hidden">Search orders</label>
          <svg class="search-ico" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/></svg>
          <input id="orderSearch" type="search" class="form-control ps-5" placeholder="Search orders">
        </div>
      </div>
      <div class="d-flex flex-wrap align-items-center gap-2 px-4 pb-3">
        <div class="d-flex flex-wrap gap-2" role="group" aria-label="Filter by status" id="orderFilters">
          <button type="button" class="btn btn-sm rounded-pill filter-chip active" data-filter="All" aria-pressed="true">All</button>
          <button type="button" class="btn btn-sm rounded-pill filter-chip" data-filter="Delivered" aria-pressed="false">Delivered</button>
          <button type="button" class="btn btn-sm rounded-pill filter-chip" data-filter="Shipped" aria-pressed="false">Shipped</button>
          <button type="button" class="btn btn-sm rounded-pill filter-chip" data-filter="Pending" aria-pressed="false">Pending</button>
        </div>
        <div class="d-md-none w-100">
          <label for="orderSort" class="visually-hidden">Sort by</label>
          <select id="orderSort" class="form-select">
            <option value="">Sort by…</option>
            <option value="0:descending">Newest first</option>
            <option value="0:ascending">Oldest first</option>
            <option value="6:descending">Total: high to low</option>
            <option value="6:ascending">Total: low to high</option>
            <option value="2:ascending">Product A–Z</option>
          </select>
        </div>
      </div>
      <div class="table-responsive">
        <table class="table orders-table align-middle mb-0">
          <caption class="visually-hidden">Recent orders, sortable by column</caption>
          <thead>
            <tr>
              <th scope="col"><button type="button" class="sort-btn">Date</button></th>
              <th scope="col"><button type="button" class="sort-btn">Order</button></th>
              <th scope="col"><button type="button" class="sort-btn">Product</button></th>
              <th scope="col">Status</th>
              <th scope="col" class="text-end"><button type="button" class="sort-btn">Price</button></th>
              <th scope="col" class="text-end"><button type="button" class="sort-btn">Qty</button></th>
              <th scope="col" class="text-end"><button type="button" class="sort-btn">Total</button></th>
            </tr>
          </thead>
          <tbody>
          <tr data-status="Delivered">
            <td data-label="Date" class="c-date" data-sort="2026-10-24"><time datetime="2026-10-24">Oct 24, 2026</time></td>
            <td data-label="Order" class="c-order fw-semibold" data-sort="200418">#200418</td>
            <td data-label="Product" class="c-product"><span class="d-flex align-items-center gap-3"><span class="prod-tile" aria-hidden="true">i</span><span>iPhone 17 Pro 256GB<span class="prod-qty d-md-none"> × 1</span></span></span></td>
            <td data-label="Status" class="c-status"><span class="badge rounded-pill status-badge bg-success-subtle text-success-emphasis"><span class="status-dot bg-success" aria-hidden="true"></span>Delivered</span></td>
            <td data-label="Price" class="c-price text-end" data-sort="1199">$1,199.00</td>
            <td data-label="Qty" class="c-qty text-end" data-sort="1">1</td>
            <td data-label="Total" class="c-total text-end fw-semibold" data-sort="1199">$1,199.00</td>
          </tr>
          <tr data-status="Shipped">
            <td data-label="Date" class="c-date" data-sort="2026-10-22"><time datetime="2026-10-22">Oct 22, 2026</time></td>
            <td data-label="Order" class="c-order fw-semibold" data-sort="200417">#200417</td>
            <td data-label="Product" class="c-product"><span class="d-flex align-items-center gap-3"><span class="prod-tile" aria-hidden="true">P</span><span>Pixel 10 Pro Obsidian<span class="prod-qty d-md-none"> × 1</span></span></span></td>
            <td data-label="Status" class="c-status"><span class="badge rounded-pill status-badge bg-primary-subtle text-primary-emphasis"><span class="status-dot bg-primary" aria-hidden="true"></span>Shipped</span></td>
            <td data-label="Price" class="c-price text-end" data-sort="999">$999.00</td>
            <td data-label="Qty" class="c-qty text-end" data-sort="1">1</td>
            <td data-label="Total" class="c-total text-end fw-semibold" data-sort="999">$999.00</td>
          </tr>
          <tr data-status="Delivered">
            <td data-label="Date" class="c-date" data-sort="2026-10-20"><time datetime="2026-10-20">Oct 20, 2026</time></td>
            <td data-label="Order" class="c-order fw-semibold" data-sort="200416">#200416</td>
            <td data-label="Product" class="c-product"><span class="d-flex align-items-center gap-3"><span class="prod-tile" aria-hidden="true">D</span><span>DualSense Edge Controller<span class="prod-qty d-md-none"> × 2</span></span></span></td>
            <td data-label="Status" class="c-status"><span class="badge rounded-pill status-badge bg-success-subtle text-success-emphasis"><span class="status-dot bg-success" aria-hidden="true"></span>Delivered</span></td>
            <td data-label="Price" class="c-price text-end" data-sort="199">$199.00</td>
            <td data-label="Qty" class="c-qty text-end" data-sort="2">2</td>
            <td data-label="Total" class="c-total text-end fw-semibold" data-sort="398">$398.00</td>
          </tr>
          <tr data-status="Pending">
            <td data-label="Date" class="c-date" data-sort="2026-10-18"><time datetime="2026-10-18">Oct 18, 2026</time></td>
            <td data-label="Order" class="c-order fw-semibold" data-sort="200415">#200415</td>
            <td data-label="Product" class="c-product"><span class="d-flex align-items-center gap-3"><span class="prod-tile" aria-hidden="true">U</span><span>USB-C Charging Cable 2m<span class="prod-qty d-md-none"> × 3</span></span></span></td>
            <td data-label="Status" class="c-status"><span class="badge rounded-pill status-badge bg-warning-subtle text-warning-emphasis"><span class="status-dot bg-warning" aria-hidden="true"></span>Pending</span></td>
            <td data-label="Price" class="c-price text-end" data-sort="19">$19.00</td>
            <td data-label="Qty" class="c-qty text-end" data-sort="3">3</td>
            <td data-label="Total" class="c-total text-end fw-semibold" data-sort="57">$57.00</td>
          </tr>
          <tr data-status="Shipped">
            <td data-label="Date" class="c-date" data-sort="2026-10-15"><time datetime="2026-10-15">Oct 15, 2026</time></td>
            <td data-label="Order" class="c-order fw-semibold" data-sort="200414">#200414</td>
            <td data-label="Product" class="c-product"><span class="d-flex align-items-center gap-3"><span class="prod-tile" aria-hidden="true">G</span><span>Galaxy Watch 8 LTE<span class="prod-qty d-md-none"> × 2</span></span></span></td>
            <td data-label="Status" class="c-status"><span class="badge rounded-pill status-badge bg-primary-subtle text-primary-emphasis"><span class="status-dot bg-primary" aria-hidden="true"></span>Shipped</span></td>
            <td data-label="Price" class="c-price text-end" data-sort="349">$349.00</td>
            <td data-label="Qty" class="c-qty text-end" data-sort="2">2</td>
            <td data-label="Total" class="c-total text-end fw-semibold" data-sort="698">$698.00</td>
          </tr>
          <tr data-status="Cancelled">
            <td data-label="Date" class="c-date" data-sort="2026-10-12"><time datetime="2026-10-12">Oct 12, 2026</time></td>
            <td data-label="Order" class="c-order fw-semibold" data-sort="200413">#200413</td>
            <td data-label="Product" class="c-product"><span class="d-flex align-items-center gap-3"><span class="prod-tile" aria-hidden="true">S</span><span>Sony A7 IV Mirrorless<span class="prod-qty d-md-none"> × 1</span></span></span></td>
            <td data-label="Status" class="c-status"><span class="badge rounded-pill status-badge bg-danger-subtle text-danger-emphasis"><span class="status-dot bg-danger" aria-hidden="true"></span>Cancelled</span></td>
            <td data-label="Price" class="c-price text-end" data-sort="2499">$2,499.00</td>
            <td data-label="Qty" class="c-qty text-end" data-sort="1">1</td>
            <td data-label="Total" class="c-total text-end fw-semibold" data-sort="2499">$2,499.00</td>
          </tr>
          <tr data-status="Delivered">
            <td data-label="Date" class="c-date" data-sort="2026-10-09"><time datetime="2026-10-09">Oct 9, 2026</time></td>
            <td data-label="Order" class="c-order fw-semibold" data-sort="200412">#200412</td>
            <td data-label="Product" class="c-product"><span class="d-flex align-items-center gap-3"><span class="prod-tile" aria-hidden="true">M</span><span>MacBook Air 15" M4<span class="prod-qty d-md-none"> × 1</span></span></span></td>
            <td data-label="Status" class="c-status"><span class="badge rounded-pill status-badge bg-success-subtle text-success-emphasis"><span class="status-dot bg-success" aria-hidden="true"></span>Delivered</span></td>
            <td data-label="Price" class="c-price text-end" data-sort="1299">$1,299.00</td>
            <td data-label="Qty" class="c-qty text-end" data-sort="1">1</td>
            <td data-label="Total" class="c-total text-end fw-semibold" data-sort="1299">$1,299.00</td>
          </tr>
          <tr data-status="Pending">
            <td data-label="Date" class="c-date" data-sort="2026-10-06"><time datetime="2026-10-06">Oct 6, 2026</time></td>
            <td data-label="Order" class="c-order fw-semibold" data-sort="200411">#200411</td>
            <td data-label="Product" class="c-product"><span class="d-flex align-items-center gap-3"><span class="prod-tile" aria-hidden="true">A</span><span>AirPods Pro 3<span class="prod-qty d-md-none"> × 2</span></span></span></td>
            <td data-label="Status" class="c-status"><span class="badge rounded-pill status-badge bg-warning-subtle text-warning-emphasis"><span class="status-dot bg-warning" aria-hidden="true"></span>Pending</span></td>
            <td data-label="Price" class="c-price text-end" data-sort="249">$249.00</td>
            <td data-label="Qty" class="c-qty text-end" data-sort="2">2</td>
            <td data-label="Total" class="c-total text-end fw-semibold" data-sort="498">$498.00</td>
          </tr>
          </tbody>
        </table>
      </div>
      <p id="orderEmpty" class="text-center wdw-muted p-4 mb-0" role="status" aria-live="polite" hidden>No orders match your search.</p>
      <div class="d-flex flex-wrap align-items-center justify-content-between gap-2 px-4 py-3 border-top small wdw-muted">
        <span id="orderCount" aria-live="polite">Showing 8 of 8 orders</span>
        <nav aria-label="Orders pages"><ul class="pagination pagination-sm mb-0">
          <li class="page-item disabled"><span class="page-link">Previous</span></li>
          <li class="page-item active" aria-current="page"><span class="page-link">1</span></li>
          <li class="page-item disabled"><span class="page-link">Next</span></li>
        </ul></nav>
      </div>
    </div>
  </div>
</section>

Built on Bootstrap 5.3.8 with plain JavaScript — no jQuery. Supports light and dark mode via data-bs-theme.

Free to use in personal and commercial projects under the MIT license.