Book a callGitHub5

It is live: hover, focus and its own controls respond. Actions that would change data (approve, send, delete) are for your app to wire. The width is a real 390 px, 768 px or 1280 px box, shrunk to fit your screen.

Source
<style>
.odl-pagination { box-sizing: border-box; inline-size: 100%; container-type: inline-size; color: var(--ds-color-text-primary); font: var(--ds-text-body-md); text-wrap: pretty; }
.odl-pagination *, .odl-pagination *::before { box-sizing: border-box; }
.odl-pagination .odl-bar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--ds-space-inline-sm) var(--ds-space-inline-md);
  padding: var(--ds-space-inset-xs) var(--ds-space-inset-sm); border-block-start: var(--ds-border-width-default) solid var(--ds-color-border-subtle); }
.odl-pagination .odl-info { display: flex; flex-wrap: wrap; align-items: center; gap: var(--ds-space-inline-xs) var(--ds-space-inline-md); }
.odl-pagination .odl-count { margin: 0; color: var(--ds-color-text-secondary); font: var(--ds-text-body-sm); font-variant-numeric: tabular-nums; white-space: nowrap; }
.odl-pagination .odl-count b { color: var(--ds-color-text-primary); font-weight: var(--ds-font-weight-label); }
.odl-pagination .odl-rows { display: inline-flex; align-items: center; gap: var(--ds-space-inline-xs); color: var(--ds-color-text-secondary); font: var(--ds-text-body-sm); white-space: nowrap; }
.odl-pagination .odl-select { position: relative; display: inline-grid; }
.odl-pagination select { appearance: none; min-block-size: max(var(--ds-size-control-sm), var(--ds-size-target-min)); padding: 0 calc(var(--ds-space-inset-xs) + var(--ds-size-icon-sm) + var(--ds-space-4)) 0 var(--ds-space-inset-xs);
  border: var(--ds-border-width-default) solid var(--ds-color-border-input); border-radius: var(--ds-radius-control); background: var(--ds-color-bg-field);
  color: var(--ds-color-text-primary); font: var(--ds-text-label-lg); font-variant-numeric: tabular-nums; cursor: pointer; }
.odl-pagination .odl-select svg { position: absolute; inset-inline-end: var(--ds-space-inset-xs); inset-block-start: 50%; translate: 0 -50%; inline-size: var(--ds-size-icon-sm); block-size: var(--ds-size-icon-sm);
  color: var(--ds-color-icon-subtle); pointer-events: none; }
.odl-pagination ol { display: flex; align-items: center; gap: var(--ds-space-2); margin: 0; padding: 0; list-style: none; }
.odl-pagination .odl-page, .odl-pagination .odl-step { display: inline-flex; align-items: center; justify-content: center; gap: var(--ds-space-inline-xs);
  min-inline-size: max(var(--ds-size-control-sm), var(--ds-size-target-min)); min-block-size: max(var(--ds-size-control-sm), var(--ds-size-target-min)); padding: 0 var(--ds-space-inset-xs);
  border: var(--ds-border-width-default) solid transparent; border-radius: var(--ds-radius-control); background: transparent; color: var(--ds-color-text-secondary);
  font: var(--ds-text-label-lg); font-variant-numeric: tabular-nums; cursor: pointer; transition: background-color var(--ds-motion-duration-short) var(--ds-motion-easing-hover); }
.odl-pagination .odl-page:hover, .odl-pagination .odl-step:hover:not(:disabled) { background: var(--ds-color-bg-neutral-subtle); color: var(--ds-color-text-primary); }
.odl-pagination .odl-page[aria-current="page"] { background: var(--ds-color-surface-raised); border-color: var(--ds-color-border-strong); color: var(--ds-color-text-primary); font-weight: var(--ds-font-weight-heading); cursor: default; }
.odl-pagination .odl-step { color: var(--ds-color-text-primary); }
.odl-pagination .odl-step:disabled { color: var(--ds-color-text-disabled); cursor: not-allowed; }
.odl-pagination .odl-step svg { inline-size: var(--ds-size-icon-sm); block-size: var(--ds-size-icon-sm); }
.odl-pagination .odl-gap { display: inline-grid; place-items: center; min-inline-size: var(--ds-size-control-sm); color: var(--ds-color-text-tertiary); }
.odl-pagination .odl-pager { display: flex; align-items: center; gap: var(--ds-space-2); margin-inline-start: auto; }
.odl-pagination .odl-of { display: none; margin: 0; padding-inline: var(--ds-space-inset-xs); font: var(--ds-text-label-lg); font-variant-numeric: tabular-nums; white-space: nowrap; }
.odl-pagination .odl-of span { color: var(--ds-color-text-secondary); font-weight: var(--ds-font-weight-body); }
.odl-pagination select:focus-visible, .odl-pagination button:focus-visible { outline: var(--ds-focus-ring-width) solid var(--ds-color-border-focus); outline-offset: var(--ds-focus-ring-offset); }
@container (max-width: 640px) {
  .odl-pagination .odl-step span { display: none; }
}
@container (max-width: 520px) {
  .odl-pagination .odl-bar { padding-inline: 0; }
  .odl-pagination .odl-info { flex: 1 1 100%; justify-content: space-between; }
  .odl-pagination .odl-pager { flex: 1 1 100%; justify-content: space-between; }
  .odl-pagination ol { display: none; }
  .odl-pagination .odl-of { display: block; }
  .odl-pagination .odl-step { border-color: var(--ds-color-border-default); }
}
@media (prefers-reduced-motion: reduce) { .odl-pagination, .odl-pagination *, .odl-pagination *::before { transition: none !important; animation: none !important; } }
</style>
<nav class="odl-pagination" aria-label="Pagination">
  <div class="odl-bar">
    <div class="odl-info">
      <p class="odl-count" aria-live="polite">Showing <b>101–150</b> of <b>2,418</b></p>
      <label class="odl-rows">Rows per page
        <span class="odl-select"><select><option>25</option><option selected>50</option><option>100</option></select>
        <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><path d="m4.5 6.5 3.5 3.5 3.5-3.5"/></svg></span>
      </label>
    </div>
    <div class="odl-pager">
      <button type="button" class="odl-step" aria-label="Previous page"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><path d="m10 4-4 4 4 4"/></svg><span>Previous</span></button>
      <ol>
        <li><button type="button" class="odl-page" aria-label="Page 1">1</button></li>
        <li><button type="button" class="odl-page" aria-label="Page 2">2</button></li>
        <li><button type="button" class="odl-page" aria-label="Page 3" aria-current="page">3</button></li>
        <li><button type="button" class="odl-page" aria-label="Page 4">4</button></li>
        <li><button type="button" class="odl-page" aria-label="Page 5">5</button></li>
        <li class="odl-gap" aria-hidden="true">…</li>
        <li><button type="button" class="odl-page" aria-label="Page 49, last page">49</button></li>
      </ol>
      <p class="odl-of">Page 3 <span>of 49</span></p>
      <button type="button" class="odl-step" aria-label="Next page"><span>Next</span><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><path d="m6 4 4 4-4 4"/></svg></button>
    </div>
  </div>
</nav>

More like this

B2BQuiet · CRM

Page header with tabs

The top of a record page: breadcrumb, title with a favourite star and summary chips, two actions, and an underline tab bar with counts that scrolls on its own when narrow.

B2BTechnical · Dev tools

Command menu

A search-first menu for every action and page, grouped, with keyboard shortcuts, live filtering and an empty result that says what to try.

B2BFriendly · SaaS

Setup checklist

A short list of first steps with progress: what is done, the one step to do now with its time and a way to skip, and what comes next.

Your kit

Nothing here yet. Add parts with Add to kit, and a look if you want the whole system.

    Parts
    0
    Files to fetch
    0 KB
    Licence
    MIT
    Total
    Free, now and later

    How do you want it?

    Your prompt

    No sign-up. Nothing leaves your browser until you paste it.

    Free