How to add sortable columns and pagination to Bootstrap tables in 2025

How to Add Sortable Columns and Pagination to Bootstrap Tables in 2025

Building data tables that users can actually interact with—sorting columns, filtering rows, paginating through hundreds of records—is a common requirement in web applications. While Bootstrap provides excellent CSS styling for tables, the markup alone doesn't give you these interactive features. That's where bootstrap-table comes in: a lightweight jQuery plugin that extends standard Bootstrap tables with sorting, pagination, checkboxes, and AJAX data loading.

In this guide, you'll learn how to set up bootstrap-table, configure sortable columns, enable pagination, and handle row selection with checkboxes.

Why Use bootstrap-table?

You could build table interactivity from scratch, but bootstrap-table saves significant development time by providing:

  • Instant sorting with click-to-sort column headers
  • Built-in pagination with customizable page sizes
  • Row selection via checkboxes or radio buttons
  • AJAX data loading for server-side pagination
  • Responsive design that adapts to mobile screens
  • Multiple CSS framework support (Bootstrap, Semantic UI, Bulma, Material Design)
  • Card view and detail views for better mobile UX
  • Column visibility toggling without reloading data

Unlike heavyweight data grid libraries, bootstrap-table is lightweight (~50KB) and integrates seamlessly with existing Bootstrap projects.

Step 1: Install bootstrap-table

You have three installation options:

Via npm (Recommended)

npm install bootstrap-table

Via Yarn

yarn add bootstrap-table

Via CDN

If you prefer not to use a build tool:

<!-- Bootstrap CSS (required) -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/css/bootstrap.min.css">

<!-- bootstrap-table CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.22.1/bootstrap-table.min.css">

<!-- jQuery (required) -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>

<!-- Bootstrap JS -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/js/bootstrap.bundle.min.js"></script>

<!-- bootstrap-table JS -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.22.1/bootstrap-table.min.js"></script>

Step 2: Create a Basic Table with Sorting

Here's a minimal HTML table that bootstrap-table will enhance:

<table id="table" 
       class="table table-striped"
       data-toggle="table"
       data-sortable="true"
       data-sort-name="name"
       data-sort-order="asc">
  <thead>
    <tr>
      <th data-field="id" data-sortable="true">ID</th>
      <th data-field="name" data-sortable="true">Name</th>
      <th data-field="email" data-sortable="true">Email</th>
      <th data-field="status">Status</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1</td>
      <td>John Doe</td>
      <td>john@example.com</td>
      <td>Active</td>
    </tr>
    <tr>
      <td>2</td>
      <td>Jane Smith</td>
      <td>jane@example.com</td>
      <td>Active</td>
    </tr>
    <tr>
      <td>3</td>
      <td>Bob Johnson</td>
      <td>bob@example.com</td>
      <td>Inactive</td>
    </tr>
  </tbody>
</table>

<script>
$('#table').bootstrapTable()
</script>

Key attributes:

  • data-toggle="table" — Tells bootstrap-table to initialize this element
  • data-sortable="true" — Enables column sorting
  • data-field — Maps column to data property
  • data-sort-name and data-sort-order — Set default sort column and direction

Step 3: Add Pagination

To enable pagination, add these attributes to the <table> element:

<table id="table" 
       class="table table-striped"
       data-toggle="table"
       data-sortable="true"
       data-pagination="true"
       data-page-size="10"
       data-page-list="[5, 10, 25, 50]">
  <!-- thead and tbody remain the same -->
</table>

Pagination attributes:

  • data-pagination="true" — Enables pagination controls
  • data-page-size="10" — Sets initial rows per page
  • data-page-list="[5, 10, 25, 50]" — Options for rows-per-page dropdown

Step 4: Enable Row Selection with Checkboxes

Add a checkbox column to allow users to select multiple rows:

<table id="table" 
       class="table table-striped"
       data-toggle="table"
       data-sortable="true"
       data-pagination="true"
       data-page-size="10"
       data-show-select="true">
  <thead>
    <tr>
      <th data-field="state" data-checkbox="true"></th>
      <th data-field="id" data-sortable="true">ID</th>
      <th data-field="name" data-sortable="true">Name</th>
      <th data-field="email" data-sortable="true">Email</th>
    </tr>
  </thead>
  <tbody>
    <!-- rows -->
  </tbody>
</table>

<script>
var $table = $('#table');

$table.bootstrapTable();

// Get selected rows
document.getElementById('getSelected').addEventListener('click', function() {
  var rows = $table.bootstrapTable('getSelections');
  console.log('Selected rows:', rows);
});
</script>

Selection attributes:

  • data-show-select="true" — Displays select-all header checkbox
  • data-field="state" data-checkbox="true" — Creates checkbox column

Step 5: Load Data via AJAX

For larger datasets, fetch data from a server endpoint:

<table id="table" 
       class="table table-striped"
       data-toggle="table"
       data-url="/api/users"
       data-pagination="true"
       data-page-size="10"
       data-side-pagination="server"
       data-show-select="true">
  <thead>
    <tr>
      <th data-field="state" data-checkbox="true"></th>
      <th data-field="id" data-sortable="true">ID</th>
      <th data-field="name" data-sortable="true">Name</th>
      <th data-field="email" data-sortable="true">Email</th>
    </tr>
  </thead>
</table>

<script>
$('#table').bootstrapTable({
  url: '/api/users',
  method: 'GET',
  sidePagination: 'server',
  queryParams: function (params) {
    return {
      limit: params.limit,
      offset: params.offset,
      sort: params.sort,
      order: params.order
    };
  }
});
</script>

Your API endpoint should return JSON with this structure:

{
  "total": 100,
  "totalNotFiltered": 100,
  "rows": [
    {"id": 1, "name": "John Doe", "email": "john@example.com"},
    {"id": 2, "name": "Jane Smith", "email": "jane@example.com"}
  ]
}

Configuration Comparison: Data Attributes vs JavaScript

| Feature | Data Attribute | JavaScript Option | Best For | |---------|----------------|--------------------|----------| | Sorting | data-sortable="true" | sortable: true | Simple tables | | Pagination | data-pagination="true" | pagination: true | Pre-rendered data | | Server-side pagination | data-side-pagination="server" | sidePagination: 'server' | Large datasets | | Row selection | data-show-select="true" | showSelect: true | Admin dashboards | | Custom formatting | — | formatter function | Conditionally styled cells |

Common Use Cases

Format Cell Values

Display custom content (badges, buttons, formatted dates) in cells:

$('#table').bootstrapTable({
  columns: [{
    field: 'status',
    formatter: function(value) {
      var badgeClass = value === 'Active' ? 'success' : 'danger';
      return '<span class="badge bg-' + badgeClass + '">' + value + '</span>';
    }
  }]
});

Handle Row Click Events

Execute actions when users click a row:

$('#table').on('click-row.bs.table', function(e, row) {
  console.log('Clicked row:', row);
  // Navigate to detail page, open modal, etc.
});

Programmatically Add/Remove Rows

var $table = $('#table');

// Add new row
$table.bootstrapTable('insertRow', {
  index: 0,
  row: {id: 999, name: 'New User', email: 'new@example.com'}
});

// Remove row by ID
$table.bootstrapTable('remove', {field: 'id', values: [999]});

Troubleshooting

Sorting not working: Ensure data-sortable="true" is on both the table AND the <th> elements.

Checkboxes missing: Verify you have a <th> with data-field="state" data-checkbox="true" and data-show-select="true" on the table.

AJAX data not loading: Check browser console for network errors. Verify your endpoint returns the correct JSON structure with total and rows properties.

Next Steps

Once you've mastered basic sorting and pagination, explore:

  • Column filtering (data-filter-control="true")
  • Export to Excel/CSV (via extensions)
  • Keyboard navigation (accessibility)
  • Custom toolbar buttons for bulk actions
  • Mobile card view (data-card-view="true")

bootstrap-table handles the tedious DOM manipulation so you can focus on business logic. For production dashboards with hundreds of rows, server-side pagination keeps load times minimal while maintaining a responsive UX.

Recommended Tools

  • GitHubWhere the world builds software
  • DigitalOceanCloud hosting built for developers — $200 free credit for new users