Open demo

CSS code

HTML
<div><span class="lbl">Condensed to the neighbours</span>
<div class="frame"><nav aria-label="Pagination"><div class="pg narrow">
<a href="#" aria-label="Previous page">‹</a><a href="#">7</a><a href="#" aria-current="page">8</a><a href="#">9</a><span class="gap">…</span><a href="#">40</a><a href="#" aria-label="Next page">›</a></div></nav></div></div>

<div><span class="lbl">Large tap targets</span><nav aria-label="Pagination"><div class="pg tap">
<a href="#" aria-label="Previous page">‹</a><a href="#">4</a><a href="#" aria-current="page">5</a><a href="#">6</a><a href="#" aria-label="Next page">›</a></div></nav></div>

<div><span class="lbl">Jump to page</span><nav aria-label="Pagination"><div class="jump">
<a href="#" aria-label="Previous page">‹</a>
<label>Page
<select><option>1</option><option selected>12</option><option>13</option><option>40</option></select>
of 40</label>
<a href="#" aria-label="Next page">›</a></div></nav></div>
CSS
.pg{display:inline-flex;flex-wrap:wrap;align-items:center;gap:6px;list-style:none}
.pg a,.jump a{box-sizing:border-box;display:grid;place-items:center;min-width:38px;height:38px;padding:0 11px;
  text-decoration:none;font-size:.88rem;font-weight:600;color:#475569;border-radius:9px;
  transition:background .15s,color .15s,border-color .15s}
.pg a:hover,.jump a:hover{background:#e2e8f0;color:#0f172a}
.pg a:focus-visible,.jump a:focus-visible,.jump select:focus-visible{outline:2px solid #2563eb;outline-offset:2px}
.pg .gap{min-width:26px;color:#64748b;display:grid;place-items:center;height:38px;font-weight:600}
.pg a[aria-current]{background:#2563eb;color:#fff}

.narrow{max-width:330px;gap:4px}
.tap a{min-width:46px;height:46px;font-size:.95rem}
.jump{display:inline-flex;align-items:center;gap:11px;font-size:.87rem;color:#475569}
.jump select{font:inherit;font-size:.87rem;padding:9px 12px;border:1px solid #8491a5;
  border-radius:9px;background:#fff;color:#0f172a}
.jump a{border:1px solid #e2e8f0;background:#fff}

@media(prefers-reduced-motion:reduce){.pg a,.jump a{transition:none}}

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS

HTML
<div><span class="lbl">Condensed to the neighbours</span>
<div class="frame"><nav aria-label="Pagination">
<ul class="pagination pagination-uic pagination-narrow mb-0">
  <li class="page-item"><a class="page-link" href="#" aria-label="Previous page">‹</a></li>
  <li class="page-item"><a class="page-link" href="#">7</a></li>
  <li class="page-item"><a class="page-link active" href="#" aria-current="page">8</a></li>
  <li class="page-item"><a class="page-link" href="#">9</a></li>
  <li class="page-item disabled page-gap"><span class="page-link">…</span></li>
  <li class="page-item"><a class="page-link" href="#">40</a></li>
  <li class="page-item"><a class="page-link" href="#" aria-label="Next page">›</a></li>
</ul>
</nav></div></div>

<div><span class="lbl">Large tap targets</span>
<nav aria-label="Pagination">
<ul class="pagination pagination-uic pagination-tap mb-0">
  <li class="page-item"><a class="page-link" href="#" aria-label="Previous page">‹</a></li>
  <li class="page-item"><a class="page-link" href="#">4</a></li>
  <li class="page-item"><a class="page-link active" href="#" aria-current="page">5</a></li>
  <li class="page-item"><a class="page-link" href="#">6</a></li>
  <li class="page-item"><a class="page-link" href="#" aria-label="Next page">›</a></li>
</ul>
</nav></div>

<div><span class="lbl">Jump to page</span>
<nav aria-label="Pagination">
<ul class="pagination pagination-uic pagination-bordered pagination-jump mb-0">
  <li class="page-item"><a class="page-link" href="#" aria-label="Previous page">‹</a></li>
  <li class="page-item"><label>Page
    <select class="form-select"><option>1</option><option selected>12</option><option>13</option><option>40</option></select>
    of 40</label></li>
  <li class="page-item"><a class="page-link" href="#" aria-label="Next page">›</a></li>
</ul>
</nav></div>
CSS
.pagination-uic{
  --bs-pagination-padding-x:11px;--bs-pagination-padding-y:0;--bs-pagination-font-size:.88rem;
  --bs-pagination-color:#475569;--bs-pagination-bg:transparent;
  --bs-pagination-border-width:1px;--bs-pagination-border-color:transparent;--bs-pagination-border-radius:9px;
  --bs-pagination-hover-color:#0f172a;--bs-pagination-hover-bg:#e2e8f0;--bs-pagination-hover-border-color:transparent;
  --bs-pagination-focus-color:#475569;--bs-pagination-focus-bg:transparent;--bs-pagination-focus-box-shadow:none;
  --bs-pagination-active-color:#fff;--bs-pagination-active-bg:#2563eb;--bs-pagination-active-border-color:#2563eb;
  --bs-pagination-disabled-color:#64748b;--bs-pagination-disabled-bg:transparent;--bs-pagination-disabled-border-color:transparent;
  flex-wrap:wrap;align-items:center;gap:6px}
.pagination-uic .page-item .page-link{display:grid;place-items:center;min-width:38px;height:38px;font-weight:600;
  margin-left:0;border-radius:var(--bs-pagination-border-radius)}
.pagination-uic .page-link:focus-visible{outline:2px solid #2563eb;outline-offset:2px}
.pagination-uic .page-gap .page-link{min-width:26px;padding:0;background:transparent;border-color:transparent}
.pagination-bordered{--bs-pagination-bg:#fff;--bs-pagination-focus-bg:#fff;
  --bs-pagination-border-color:#e2e8f0;--bs-pagination-hover-border-color:#e2e8f0}
.pagination-narrow{max-width:330px;gap:4px}
.pagination-tap{--bs-pagination-font-size:.95rem}
.pagination-tap .page-item .page-link{min-width:46px;height:46px}
.pagination-jump{gap:11px;font-size:.87rem;color:#475569}
.pagination-jump .form-select{display:inline-block;width:auto;margin:0 4px;font-size:.87rem;padding-top:9px;padding-bottom:9px;
  border-color:#8491a5;border-radius:9px;color:#0f172a}
.pagination-jump .form-select:focus-visible{outline:2px solid #2563eb;outline-offset:2px;box-shadow:none}
.frame{border:1px dashed #cbd5e1;border-radius:12px;padding:18px;display:inline-block}

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<div><span class="mb-4 block text-[.72rem] uppercase tracking-[.12em] text-slate-500">Condensed to the neighbours</span>
<div class="inline-block rounded-xl border border-dashed border-slate-300 p-[18px]"><nav aria-label="Pagination">
<div class="inline-flex flex-wrap items-center gap-1 max-w-[330px]">
  <a href="#" aria-label="Previous page" class="grid h-[38px] min-w-[38px] place-items-center text-[.88rem] font-semibold rounded-[9px] px-[11px] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand text-slate-600 hover:bg-slate-200 hover:text-slate-900 transition-[color,background-color,border-color] motion-reduce:transition-none">‹</a>
  <a href="#" class="grid h-[38px] min-w-[38px] place-items-center text-[.88rem] font-semibold rounded-[9px] px-[11px] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand text-slate-600 hover:bg-slate-200 hover:text-slate-900 transition-[color,background-color,border-color] motion-reduce:transition-none">7</a>
  <a href="#" aria-current="page" class="grid h-[38px] min-w-[38px] place-items-center text-[.88rem] font-semibold rounded-[9px] px-[11px] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand bg-brand text-white">8</a>
  <a href="#" class="grid h-[38px] min-w-[38px] place-items-center text-[.88rem] font-semibold rounded-[9px] px-[11px] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand text-slate-600 hover:bg-slate-200 hover:text-slate-900 transition-[color,background-color,border-color] motion-reduce:transition-none">9</a>
  <span class="grid h-[38px] min-w-[26px] place-items-center font-semibold text-slate-500">…</span>
  <a href="#" class="grid h-[38px] min-w-[38px] place-items-center text-[.88rem] font-semibold rounded-[9px] px-[11px] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand text-slate-600 hover:bg-slate-200 hover:text-slate-900 transition-[color,background-color,border-color] motion-reduce:transition-none">40</a>
  <a href="#" aria-label="Next page" class="grid h-[38px] min-w-[38px] place-items-center text-[.88rem] font-semibold rounded-[9px] px-[11px] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand text-slate-600 hover:bg-slate-200 hover:text-slate-900 transition-[color,background-color,border-color] motion-reduce:transition-none">›</a>
</div>
</nav></div></div>

<div><span class="mb-4 block text-[.72rem] uppercase tracking-[.12em] text-slate-500">Large tap targets</span>
<nav aria-label="Pagination">
<div class="inline-flex flex-wrap items-center gap-1.5">
  <a href="#" aria-label="Previous page" class="grid h-[46px] min-w-[46px] place-items-center rounded-[9px] px-[11px] text-[.95rem] font-semibold focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand text-slate-600 hover:bg-slate-200 hover:text-slate-900 transition-[color,background-color,border-color] motion-reduce:transition-none">‹</a>
  <a href="#" class="grid h-[46px] min-w-[46px] place-items-center rounded-[9px] px-[11px] text-[.95rem] font-semibold focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand text-slate-600 hover:bg-slate-200 hover:text-slate-900 transition-[color,background-color,border-color] motion-reduce:transition-none">4</a>
  <a href="#" aria-current="page" class="grid h-[46px] min-w-[46px] place-items-center rounded-[9px] px-[11px] text-[.95rem] font-semibold focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand bg-brand text-white">5</a>
  <a href="#" class="grid h-[46px] min-w-[46px] place-items-center rounded-[9px] px-[11px] text-[.95rem] font-semibold focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand text-slate-600 hover:bg-slate-200 hover:text-slate-900 transition-[color,background-color,border-color] motion-reduce:transition-none">6</a>
  <a href="#" aria-label="Next page" class="grid h-[46px] min-w-[46px] place-items-center rounded-[9px] px-[11px] text-[.95rem] font-semibold focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand text-slate-600 hover:bg-slate-200 hover:text-slate-900 transition-[color,background-color,border-color] motion-reduce:transition-none">›</a>
</div>
</nav></div>

<div><span class="mb-4 block text-[.72rem] uppercase tracking-[.12em] text-slate-500">Jump to page</span>
<nav aria-label="Pagination">
<div class="inline-flex items-center gap-[11px] text-[.87rem] text-slate-600">
  <a href="#" aria-label="Previous page" class="grid h-[38px] min-w-[38px] place-items-center text-[.88rem] font-semibold rounded-[9px] px-[11px] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand border border-slate-200 bg-white text-slate-600 hover:bg-slate-200 hover:text-slate-900 transition-[color,background-color,border-color] motion-reduce:transition-none">‹</a>
  <label>Page
    <select class="mx-1 rounded-[9px] border border-[#8491a5] bg-white px-3 py-[9px] text-[.87rem] text-slate-900 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand"><option>1</option><option selected>12</option><option>13</option><option>40</option></select>
    of 40</label>
  <a href="#" aria-label="Next page" class="grid h-[38px] min-w-[38px] place-items-center text-[.88rem] font-semibold rounded-[9px] px-[11px] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand border border-slate-200 bg-white text-slate-600 hover:bg-slate-200 hover:text-slate-900 transition-[color,background-color,border-color] motion-reduce:transition-none">›</a>
</div>
</nav></div>
CSS
@theme {
  --color-brand: #2563eb;
}

About this set

Three pagination patterns designed for narrow screens and touch. Condensed to the neighbours shows only the pages either side of the current one plus the last page, so a 40-page list fits inside a 330px container; the dashed frame in the demo marks that width. Large tap targets raises every link to 46 by 46 pixels, comfortably above the 44px touch-target guideline, for apps and kiosk-style layouts with only a few pages. Jump to page replaces the numbers entirely with a native select between two arrows, reading Page 12 of 40, which is the quickest way through very long lists on a phone because it opens the system picker. All three are links inside a nav labelled Pagination, with aria-current on the active page and named arrow links, and the select is wrapped in its label so the words around it become its accessible name. The Bootstrap version uses .pagination for the rows and .form-select for the picker; the Tailwind version keeps the native select and styles it with utilities.

What’s included

  • Condensed row that fits a 330px container
  • 46px tap targets for touch interfaces
  • Jump-to-page select between previous and next arrows
  • Native select opens the system picker on phones
  • Bootstrap version uses .pagination and .form-select

Accessibility

Each control is a nav labelled Pagination with aria-current="page" on the active link and Previous page / Next page names on the arrows. The page select is wrapped in its label, and its border reaches 3:1 contrast against the white background. Links and the select show a 2px blue focus outline, and hover transitions are removed under prefers-reduced-motion.

Customise it

In plain CSS change the 46px size on .tap a, the 330px max-width on .narrow and the #8491a5 select border. In Bootstrap edit the .pagination-tap and .pagination-jump rules and the pagination variables on .pagination-uic. In Tailwind swap h-[46px] min-w-[46px], max-w-[330px] and --color-brand.