Bootstrap5 分页(实战指南)

什么是 Bootstrap5 分页?为什么它如此重要?

在网页开发中,当你需要展示大量数据时,比如用户列表、文章列表或者商品信息,一次性把所有内容都加载出来,不仅会拖慢页面速度,还会让用户体验变得糟糕。这时候,分页就显得尤为重要。

想象一下,你去图书馆找一本书,如果整座图书馆的书都堆在你面前,你会怎么办?肯定不会从头翻到尾吧?你会先看目录,再按类别查找。网页中的分页机制,其实就是这个道理——把内容分成若干页,让用户“一页一页”地浏览。

Bootstrap5 分页,就是 Bootstrap 框架提供的一个现成的分页组件,它能让你用最少的代码,实现美观、响应式的分页效果。无论是手机、平板还是桌面电脑,它都能自动适配,真正做到“一次编写,处处可用”。

Bootstrap5 分页不仅美观,还内置了多种状态(如当前页、禁用页、上一页、下一页),并且支持自定义样式和交互逻辑。对于初学者来说,它是快速上手前端开发的绝佳工具;对于中级开发者,它则是提升开发效率、保证界面一致性的利器。


基础结构:构建一个最简单的分页组件

我们先从最基础的结构开始。Bootstrap5 分页的核心是 <nav> 标签配合 .pagination 类,再通过 <a><button> 元素来表示每一页。

<nav aria-label="Page navigation example">
  <ul class="pagination">
    <li class="page-item">
      <a class="page-link" href="#" aria-label="Previous">
        <span aria-hidden="true">&laquo;</span>
      </a>
    </li>
    <li class="page-item"><a class="page-link" href="#">1</a></li>
    <li class="page-item"><a class="page-link" href="#">2</a></li>
    <li class="page-item"><a class="page-link" href="#">3</a></li>
    <li class="page-item">
      <a class="page-link" href="#" aria-label="Next">
        <span aria-hidden="true">&raquo;</span>
      </a>
    </li>
  </ul>
</nav>

代码详解:

  • <nav aria-label="Page navigation example">:这是分页区域的容器,aria-label 是无障碍访问的重要属性,告诉屏幕阅读器这是一个分页导航。
  • <ul class="pagination">:这是分页的列表容器,pagination 类是 Bootstrap 的核心类,它会自动设置间距、边框、圆角等样式。
  • <li class="page-item">:每一页的独立项,必须包裹在 <li> 中。
  • <a class="page-link">:每个页码的点击区域,page-link 类负责样式美化,比如颜色、悬停效果和点击反馈。
  • aria-label="Previous"aria-label="Next":为前后按钮提供语义化标签,提升可访问性。
  • &laquo;&raquo;:分别是“上一页”和“下一页”的符号,用 HTML 实体表示。

这个结构虽然简单,但已经具备了完整的分页功能。你可以把它直接复制到项目中,立刻看到效果。


常见状态:当前页、禁用页和引导性按钮

Bootstrap5 分页支持多种状态,这些状态让界面更直观。我们来逐一讲解。

当前页的高亮显示

当用户处于第 2 页时,这一页应该被高亮,以示区分。只需在对应的 <li> 上添加 .active 类即可。

<li class="page-item active">
  <a class="page-link" href="#">2</a>
</li>

这个 active 类会自动改变背景色和字体颜色,让用户一眼看出当前所在页。就像你在一本电子书中,当前页的页码会用不同颜色标出一样。

禁用页码

当某些页码不可点击时(比如第 0 页或超出范围),可以用 .disabled 类。

<li class="page-item disabled">
  <a class="page-link" href="#" tabindex="-1" aria-disabled="true">5</a>
</li>
  • disabled 类会添加灰色背景和透明文字。
  • tabindex="-1" 阻止该元素被键盘导航聚焦。
  • aria-disabled="true" 告诉屏幕阅读器该按钮不可用。

这就像你在一个游戏里,某些关卡还没解锁,按钮会变灰,不能点击。

引导性按钮:首页和末页

除了“上一页”“下一页”,你还可以添加“首页”和“末页”按钮,方便用户快速跳转。

<li class="page-item">
  <a class="page-link" href="#" aria-label="First">
    <span aria-hidden="true">&laquo;&laquo;</span>
  </a>
</li>
<li class="page-item">
  <a class="page-link" href="#" aria-label="Last">
    <span aria-hidden="true">&raquo;&raquo;</span>
  </a>
</li>

这里使用了双符号 &laquo;&laquo;&raquo;&raquo;,表示“跳转到第一页”和“跳转到最后一页”。这些按钮在数据量大时特别有用。


响应式设计:适配移动端

Bootstrap5 的优势之一就是响应式。分页组件在不同设备上会自动调整布局。

在手机上,分页项会自动堆叠成一列,避免过宽;在桌面端,它们会水平排列,更节省空间。

你不需要写任何额外的 CSS,Bootstrap5 已经帮你处理好了。这是框架的“开箱即用”特性,让你专注于业务逻辑,而不是布局细节。

如果你希望在移动端隐藏某些按钮(比如首页、末页),可以使用 Bootstrap 的响应式工具类:

<li class="page-item d-none d-md-block">
  <a class="page-link" href="#">首页</a>
</li>
  • d-none:默认隐藏。
  • d-md-block:在中等及以上屏幕(≥768px)显示。

这样,只有在桌面端才会显示“首页”按钮,手机上只保留“上一页”“下一页”,保持简洁。


实际案例:动态生成分页(结合 JavaScript)

光靠 HTML 是静态的,真正的分页系统需要 JavaScript 动态生成。我们来做一个小例子:模拟一个 100 条数据的列表,每页显示 10 条,共 10 页。

<!-- 分页容器 -->
<nav aria-label="Page navigation example" id="pagination">
  <ul class="pagination"></ul>
</nav>

<!-- 数据容器 -->
<div id="data-container"></div>
// 模拟 100 条数据
const data = Array.from({ length: 100 }, (_, i) => `第 ${i + 1} 条数据`);

// 每页显示多少条
const itemsPerPage = 10;
// 总页数
const totalPages = Math.ceil(data.length / itemsPerPage);

// 当前页码(从 1 开始)
let currentPage = 1;

// 渲染分页按钮
function renderPagination() {
  const paginationEl = document.getElementById('pagination').querySelector('.pagination');
  paginationEl.innerHTML = ''; // 清空

  // 首页
  const firstLi = document.createElement('li');
  firstLi.className = 'page-item';
  const firstLink = document.createElement('a');
  firstLink.className = 'page-link';
  firstLink.href = '#';
  firstLink.textContent = '首页';
  firstLink.addEventListener('click', (e) => {
    e.preventDefault();
    currentPage = 1;
    renderPage();
    renderPagination();
  });
  firstLi.appendChild(firstLink);
  paginationEl.appendChild(firstLi);

  // 上一页
  const prevLi = document.createElement('li');
  prevLi.className = 'page-item';
  const prevLink = document.createElement('a');
  prevLink.className = 'page-link';
  prevLink.href = '#';
  prevLink.textContent = '上一页';
  prevLink.disabled = currentPage === 1;
  prevLink.addEventListener('click', (e) => {
    e.preventDefault();
    if (currentPage > 1) {
      currentPage--;
      renderPage();
      renderPagination();
    }
  });
  prevLi.appendChild(prevLink);
  paginationEl.appendChild(prevLi);

  // 中间页码
  const startPage = Math.max(1, currentPage - 2);
  const endPage = Math.min(totalPages, currentPage + 2);

  for (let i = startPage; i <= endPage; i++) {
    const li = document.createElement('li');
    li.className = 'page-item' + (i === currentPage ? ' active' : '');
    const link = document.createElement('a');
    link.className = 'page-link';
    link.href = '#';
    link.textContent = i;
    link.addEventListener('click', (e) => {
      e.preventDefault();
      currentPage = i;
      renderPage();
      renderPagination();
    });
    li.appendChild(link);
    paginationEl.appendChild(li);
  }

  // 下一页
  const nextLi = document.createElement('li');
  nextLi.className = 'page-item';
  const nextLink = document.createElement('a');
  nextLink.className = 'page-link';
  nextLink.href = '#';
  nextLink.textContent = '下一页';
  nextLink.disabled = currentPage === totalPages;
  nextLink.addEventListener('click', (e) => {
    e.preventDefault();
    if (currentPage < totalPages) {
      currentPage++;
      renderPage();
      renderPagination();
    }
  });
  nextLi.appendChild(nextLink);
  paginationEl.appendChild(nextLi);

  // 末页
  const lastLi = document.createElement('li');
  lastLi.className = 'page-item';
  const lastLink = document.createElement('a');
  lastLink.className = 'page-link';
  lastLink.href = '#';
  lastLink.textContent = '末页';
  lastLink.addEventListener('click', (e) => {
    e.preventDefault();
    currentPage = totalPages;
    renderPage();
    renderPagination();
  });
  lastLi.appendChild(lastLink);
  paginationEl.appendChild(lastLi);
}

// 渲染当前页数据
function renderPage() {
  const start = (currentPage - 1) * itemsPerPage;
  const end = start + itemsPerPage;
  const pageData = data.slice(start, end);

  const container = document.getElementById('data-container');
  container.innerHTML = pageData.map(item => `<p>${item}</p>`).join('');
}

// 初始化
renderPage();
renderPagination();

代码说明:

  • data 是模拟的数据数组。
  • itemsPerPage 控制每页显示条数。
  • renderPage() 负责根据当前页码从数据中截取对应部分并渲染。
  • renderPagination() 动态生成分页按钮,包括首页、上一页、中间页码、下一页、末页。
  • 每个按钮都绑定了 click 事件,点击后更新 currentPage,重新渲染数据和分页。

这个例子展示了如何将 Bootstrap5 分页与 JavaScript 结合,实现完整的分页功能。它适合用于后台管理系统、博客列表等场景。


高级技巧:自定义样式与主题扩展

Bootstrap5 分页默认样式美观,但你也可以根据项目风格自定义。

比如你想让分页按钮有圆角、阴影,或者换颜色:

.pagination .page-link {
  border-radius: 50px; /* 圆角 */
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); /* 阴影 */
  transition: all 0.2s ease;
}

.pagination .page-link:hover {
  background-color: #007bff;
  color: white;
}

.pagination .page-link.active {
  background-color: #007bff;
  border-color: #007bff;
  color: white;
}

你还可以通过 Sass 变量来自定义颜色:

$pagination-color: #6c757d;
$pagination-bg: #fff;
$pagination-hover-color: #007bff;
$pagination-active-bg: #007bff;
$pagination-active-border-color: #007bff;

这些变量可以在 bootstrap.scss 中覆盖,实现全局统一风格。


总结:Bootstrap5 分页,让分页更简单

Bootstrap5 分页不仅是一个 UI 组件,更是一种开发思维的体现:用标准、可复用的组件,解决常见问题

从基础结构到动态交互,从响应式适配到无障碍支持,它几乎覆盖了所有实际开发中的需求。无论你是初学者,还是有一定经验的开发者,都可以快速上手并提升开发效率。

掌握它,意味着你不再需要从零写分页样式,也不用担心兼容性问题。只需几行代码,就能构建出专业级的分页体验。

在实际项目中,建议将分页逻辑封装成组件,方便复用。比如在 Vue 或 React 中,你可以创建一个 <Pagination /> 组件,传入数据总数、每页条数、回调函数等参数,就能自动渲染分页。

Bootstrap5 分页,是你前端开发工具箱中不可或缺的一环。多用几次,你会发现它真的“好用到上头”。