Bulma Table

Bulma provides beautifully styled tables with minimal CSS. The table component includes modifiers for different styles, responsive containers, and easy customization.

Basic Table

Simple table with default styling:

<table class="table">
  <thead>
    <tr>
      <th>ID</th>
      <th>Name</th>
      <th>Email</th>
      <th>Role</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1</td>
      <td>John Doe</td>
      <td>john@example.com</td>
      <td>Admin</td>
    </tr>
    <tr>
      <td>2</td>
      <td>Jane Smith</td>
      <td>jane@example.com</td>
      <td>User</td>
    </tr>
  </tbody>
</table>
IDNameEmailRole
1John Doejohn@example.comAdmin
2Jane Smithjane@example.comUser

Table Modifiers

Apply different styles to tables:

<!-- Bordered table -->
<table class="table is-bordered">

<!-- Striped table -->
<table class="table is-striped">

<!-- Narrow table -->
<table class="table is-narrow">

<!-- Hoverable rows -->
<table class="table is-hoverable">

<!-- Full width table -->
<table class="table is-fullwidth">

<!-- Combine modifiers -->
<table class="table is-striped is-hoverable is-fullwidth">
ModifierDescription
is-borderedAdds borders to all cells
is-stripedAdds zebra striping
is-narrowMakes cells more compact
is-hoverableHighlights row on hover
is-fullwidthTable takes full container width

Table with Container

Use table-container for responsive scrolling:

<div class="table-container">
  <table class="table is-bordered is-striped is-narrow is-hoverable is-fullwidth">
    <!-- Table content -->
  </table>
</div>

Table Header Colors

<!-- Dark header -->
<thead>
  <tr class="has-background-dark has-text-white">
    <th>Column 1</th>
    <th>Column 2</th>
  </tr>
</thead>

<!-- Primary header -->
<thead>
  <tr class="has-background-primary has-text-white">
    <th>Column 1</th>
    <th>Column 2</th>
  </tr>
</thead>

<!-- Gradient header -->
<thead>
  <tr style="background: linear-gradient(to right, #667eea, #764ba2); color: white;">
    <th>Column 1</th>
    <th>Column 2</th>
  </tr>
</thead>

Table Cell Alignment

<table class="table">
  <thead>
    <tr>
      <th class="has-text-left">Left Aligned</th>
      <th class="has-text-centered">Centered</th>
      <th class="has-text-right">Right Aligned</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td class="has-text-left">Left</td>
      <td class="has-text-centered">Center</td>
      <td class="has-text-right">Right</td>
    </tr>
  </tbody>
</table>

Table with Icons and Badges

<table class="table">
  <thead>
    <tr>
      <th>Status</th>
      <th>Task</th>
      <th>Priority</th>
      <th>Actions</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>
        <span class="icon has-text-success">
          <i class="fas fa-check-circle"></i>
        </span>
        <span>Completed</span>
      </td>
      <td>Design homepage</td>
      <td>
        <span class="tag is-primary">High</span>
      </td>
      <td>
        <button class="button is-small is-info">
          <span class="icon"><i class="fas fa-edit"></i></span>
        </button>
      </td>
    </tr>
    <tr>
      <td>
        <span class="icon has-text-warning">
          <i class="fas fa-exclamation-circle"></i>
        </span>
        <span>Pending</span>
      </td>
      <td>Write documentation</td>
      <td>
        <span class="tag is-warning">Medium</span>
      </td>
      <td>
        <button class="button is-small is-success">
          <span class="icon"><i class="fas fa-check"></i></span>
        </button>
      </td>
    </tr>
  </tbody>
</table>

Sortable Table Headers

<table class="table is-hoverable">
  <thead>
    <tr>
      <th>
        <a href="#" class="is-flex is-align-items-center">
          Name
          <span class="icon ml-1">
            <i class="fas fa-sort"></i>
          </span>
        </a>
      </th>
      <th>
        <a href="#" class="is-flex is-align-items-center">
          Date
          <span class="icon ml-1">
            <i class="fas fa-sort"></i>
          </span>
        </a>
      </th>
      <th>
        <a href="#" class="is-flex is-align-items-center">
          Amount
          <span class="icon ml-1">
            <i class="fas fa-sort"></i>
          </span>
        </a>
      </th>
    </tr>
  </thead>
  <tbody>
    <!-- Table data -->
  </tbody>
</table>

<script>
// Simple sorting functionality
document.querySelectorAll('th a').forEach(header => {
  header.addEventListener('click', function(e) {
    e.preventDefault();
    const table = this.closest('table');
    const headerIndex = Array.from(this.parentNode.parentNode.children).indexOf(this.parentNode);
    const tbody = table.querySelector('tbody');
    const rows = Array.from(tbody.querySelectorAll('tr'));
    
    rows.sort((a, b) => {
      const aText = a.children[headerIndex].textContent.trim();
      const bText = b.children[headerIndex].textContent.trim();
      
      // Try to parse as number first
      const aNum = parseFloat(aText.replace(/[^0-9.-]+/g, ''));
      const bNum = parseFloat(bText.replace(/[^0-9.-]+/g, ''));
      
      if (!isNaN(aNum) && !isNaN(bNum)) {
        return aNum - bNum;
      }
      
      // Otherwise sort as string
      return aText.localeCompare(bText);
    });
    
    // Clear and re-append sorted rows
    tbody.innerHTML = '';
    rows.forEach(row => tbody.appendChild(row));
  });
});
</script>

Responsive Tables

Make tables scrollable on mobile:

<div class="table-container is-scrollable">
  <table class="table is-bordered is-striped">
    <!-- Wide table that will scroll on mobile -->
  </table>
</div>

<style>
.is-scrollable {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

/* Alternatively, use Bulma's responsive table */
@media screen and (max-width: 768px) {
  .table.is-responsive {
    display: block;
    overflow-x: auto;
    white-space: nowrap;
  }
}
</style>

JavaScript Integration

Add interactivity to tables:

// Row selection
document.querySelectorAll('.table tbody tr').forEach(row => {
  row.addEventListener('click', function() {
    this.classList.toggle('has-background-light');
  });
});

// Filter table rows
function filterTable(inputId, tableId) {
  const filter = document.getElementById(inputId).value.toLowerCase();
  const table = document.getElementById(tableId);
  const rows = table.querySelectorAll('tbody tr');
  
  rows.forEach(row => {
    const text = row.textContent.toLowerCase();
    if (text.includes(filter)) {
      row.style.display = '';
    } else {
      row.style.display = 'none';
    }
  });
}

// Paginate table
function paginateTable(tableId, pageSize) {
  const table = document.getElementById(tableId);
  const rows = table.querySelectorAll('tbody tr');
  const totalPages = Math.ceil(rows.length / pageSize);
  
  function showPage(page) {
    const start = (page - 1) * pageSize;
    const end = start + pageSize;
    
    rows.forEach((row, index) => {
      if (index >= start && index < end) {
        row.style.display = '';
      } else {
        row.style.display = 'none';
      }
    });
  }
  
  return { showPage, totalPages };
}

// Initialize pagination
const tablePaginator = paginateTable('my-table', 10);
tablePaginator.showPage(1);

Practical Examples

User Management Table

<div class="box">
  <div class="level">
    <div class="level-left">
      <div class="level-item">
        <h2 class="title is-4">Users</h2>
      </div>
      <div class="level-item">
        <div class="field has-addons">
          <div class="control">
            <input class="input" type="text" placeholder="Search users..." id="user-search">
          </div>
          <div class="control">
            <button class="button is-primary">
              <span class="icon"><i class="fas fa-search"></i></span>
            </button>
          </div>
        </div>
      </div>
    </div>
    <div class="level-right">
      <div class="level-item">
        <button class="button is-success">
          <span class="icon"><i class="fas fa-plus"></i></span>
          <span>Add User</span>
        </button>
      </div>
    </div>
  </div>
  
  <div class="table-container">
    <table class="table is-fullwidth is-striped is-hoverable" id="users-table">
      <thead>
        <tr class="has-background-light">
          <th>ID</th>
          <th>Name</th>
          <th>Email</th>
          <th>Role</th>
          <th>Status</th>
          <th>Joined</th>
          <th>Actions</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>1</td>
          <td>
            <div class="media">
              <div class="media-left">
                <figure class="image is-32x32">
                  <img class="is-rounded" src="avatar1.jpg" alt="Avatar">
                </figure>
              </div>
              <div class="media-content">
                <p class="has-text-weight-semibold">John Doe</p>
              </div>
            </div>
          </td>
          <td>john@example.com</td>
          <td>
            <span class="tag is-primary">Admin</span>
          </td>
          <td>
            <span class="tag is-success">Active</span>
          </td>
          <td>2024-01-15</td>
          <td>
            <div class="buttons are-small">
              <button class="button is-info">
                <span class="icon"><i class="fas fa-edit"></i></span>
              </button>
              <button class="button is-danger">
                <span class="icon"><i class="fas fa-trash"></i></span>
              </button>
            </div>
          </td>
        </tr>
        <!-- More rows -->
      </tbody>
    </table>
  </div>
  
  <!-- Pagination -->
  <nav class="pagination is-centered mt-4">
    <!-- Pagination controls -->
  </nav>
</div>

Product Inventory Table

<div class="card">
  <div class="card-content">
    <h3 class="title is-4">Inventory</h3>
    
    <table class="table is-fullwidth is-striped">
      <thead>
        <tr>
          <th>Product</th>
          <th>SKU</th>
          <th>Category</th>
          <th>Price</th>
          <th>Stock</th>
          <th>Status</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>
            <div class="media">
              <div class="media-left">
                <figure class="image is-48x48">
                  <img src="product1.jpg" alt="Product">
                </figure>
              </div>
              <div class="media-content">
                <p class="has-text-weight-semibold">Wireless Headphones</p>
                <p class="is-size-7 has-text-grey">Premium sound quality</p>
              </div>
            </div>
          </td>
          <td>WH-2024</td>
          <td>Electronics</td>
          <td>
            <span class="has-text-weight-bold">$99.99</span>
          </td>
          <td>
            <div class="level is-mobile">
              <div class="level-left">
                <div class="level-item">45 units</div>
              </div>
              <div class="level-right">
                <div class="level-item">
                  <progress class="progress is-small is-success" value="45" max="100">45%</progress>
                </div>
              </div>
            </div>
          </td>
          <td>
            <span class="tag is-success">In Stock</span>
          </td>
        </tr>
        <tr>
          <td>Laptop Stand</td>
          <td>LS-101</td>
          <td>Accessories</td>
          <td>$29.99</td>
          <td>
            <div class="level is-mobile">
              <div class="level-left">
                <div class="level-item">3 units</div>
              </div>
              <div class="level-right">
                <div class="level-item">
                  <progress class="progress is-small is-warning" value="15" max="100">15%</progress>
                </div>
              </div>
            </div>
          </td>
          <td>
            <span class="tag is-warning">Low Stock</span>
          </td>
        </tr>
        <tr>
          <td>Gaming Mouse</td>
          <td>GM-305</td>
          <td>Gaming</td>
          <td>$49.99</td>
          <td>
            <div class="level is-mobile">
              <div class="level-left">
                <div class="level-item">0 units</div>
              </div>
            </div>
          </td>
          <td>
            <span class="tag is-danger">Out of Stock</span>
          </td>
        </tr>
      </tbody>
      <tfoot>
        <tr>
          <td colspan="6" class="has-text-right">
            <strong>Total Products:</strong> 3
          </td>
        </tr>
      </tfoot>
    </table>
  </div>
</div>

Financial Transactions Table

<table class="table is-fullwidth is-hoverable">
  <thead>
    <tr class="has-background-dark has-text-white">
      <th>Date</th>
      <th>Description</th>
      <th>Category</th>
      <th class="has-text-right">Amount</th>
      <th>Status</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>2024-01-15</td>
      <td>Website Hosting</td>
      <td>
        <span class="tag is-info">Business</span>
      </td>
      <td class="has-text-right has-text-danger">-$29.99</td>
      <td>
        <span class="icon has-text-success">
          <i class="fas fa-check-circle"></i>
        </span>
        <span>Completed</span>
      </td>
    </tr>
    <tr>
      <td>2024-01-14</td>
      <td>Freelance Payment</td>
      <td>
        <span class="tag is-success">Income</span>
      </td>
      <td class="has-text-right has-text-success">+$1,250.00</td>
      <td>
        <span class="icon has-text-success">
          <i class="fas fa-check-circle"></i>
        </span>
        <span>Completed</span>
      </td>
    </tr>
    <tr>
      <td>2024-01-13</td>
      <td>Software Subscription</td>
      <td>
        <span class="tag is-warning">Software</span>
      </td>
      <td class="has-text-right has-text-danger">-$99.00</td>
      <td>
        <span class="icon has-text-warning">
          <i class="fas fa-clock"></i>
        </span>
        <span>Pending</span>
      </td>
    </tr>
  </tbody>
  <tfoot>
    <tr class="has-background-light">
      <td colspan="3" class="has-text-weight-bold">Total</td>
      <td class="has-text-right has-text-weight-bold has-text-success">+$1,121.01</td>
      <td></td>
    </tr>
  </tfoot>
</table>

Best Practices

  • Always wrap tables in .table-container for proper overflow handling
  • Use is-striped and is-hoverable for better readability
  • Make tables responsive with horizontal scrolling on mobile
  • Use appropriate header colors to distinguish from data rows
  • Align numerical data to the right for easier comparison
  • Use tags and icons to represent status and categories visually
  • Implement sorting and filtering for large datasets
  • Consider pagination for tables with many rows
Accessibility: Always include proper table headers with <th>elements, use scope="col" for column headers and scope="row" for row headers when applicable, and provide captions for complex tables.

Next: Bulma Tabs Component