Pagination
Guidelines
The Pagination component enables users to select a specific page from a range of pages, helping them navigate large sets of content in a clear and manageable way.
Main Component
Code
nav.pagination ul.pagination-items {
display: flex;
flex-direction: row;
justify-content: center;
padding: 0;
list-style: none;
gap: 0.5rem;
margin: 0;
}
.pagination .pagination-items .pagebutton {
width: $pagination-button-size;
height: $pagination-button-size;
margin: 0;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
background: none;
border: none;
border-radius: 50%;
cursor: pointer;
-webkit-transition: 0.3s;
transition: 0.3s;
.pageicon {
display: flex;
color: $icon-color-default;
}
&:hover,
&.hover {
background-color: $pagination-button-bg-hover;
}
&:focus,
&.focused {
background-color: $pagination-button-bg-focused;
}
&:active,
&.selected {
background-color: $pagination-button-bg-selected;
.pageicon {
color: $icon-color-active;
}
}
&:disabled,
&.disabled {
cursor: not-allowed;
.pageicon {
color: $icon-color-disabled;
}
}
}
.pagination-items .pagebutton.-ctrl {
background: none;
border: $pagination-button-border-default;
.pageicon .twemoji {
height: $icon-size;
width: $icon-size;
}
&:hover,
&.hover {
border: 0;
background-color: $pagination-button-bg-hover;
}
&:disabled,
&.disabled {
border: $pagination-button-border-disabled;
background: none;
cursor: not-allowed;
.pageicon {
color: $icon-color-disabled;
}
}
}
.pagination-items .pagebutton.-more {
cursor: default;
pointer-events: none;
.pageicon .twemoji {
width: $icon-size;
height: $icon-size;
}
}
<div class="pagination">
<ul class="pagination-items">
<li class="pagebutton -ctrl"><a class="pageicon">:material-chevron-left:</a></li>
<li class="pagebutton selected"><a class="pageicon">1</a></li>
<li class="pagebutton"><a class="pageicon">2</a></li>
<li class="pagebutton -more"><a class="pageicon">:material-dots-horizontal:</a></li>
<li class="pagebutton"><a class="pageicon">5</a></li>
<li class="pagebutton -ctrl"><a class="pageicon">:material-chevron-right:</a></li>
</ul>
</div>
document.addEventListener('DOMContentLoaded', () => {
const pagination = document.querySelector(".pagination");
if (!pagination) return;
const pages = pagination.querySelectorAll(".pagebutton:not(.-more):not(.-ctrl):not(.disabled)");
const prevControl = pagination.querySelector(".pagebutton.-ctrl:first-child");
const nextControl = pagination.querySelector(".pagebutton.-ctrl:last-child");
let currentIndex = Array.from(pages).findIndex( (btn) => btn.classList.contains("selected"));
if (currentIndex == -1) currentIndex = 0;
function updatePagination() {
// Update page states
pages.forEach((page, i) => page.classList.toggle("selected", i === currentIndex));
// Disable controls for bounding pages
prevControl.classList.toggle("disabled", currentIndex === 0);
nextControl.classList.toggle("disabled", currentIndex === pages.length - 1);
}
//Control button listeners
prevControl.addEventListener("click", () => {
//in case of CSS class but no HTML attribute
if (prevControl.classList.contains("disabled")) return;
currentIndex--;
updatePagination();
});
nextControl.addEventListener("click", () => {
//in case of CSS class but no HTML attribute
if (nextControl.classList.contains("disabled")) return;
currentIndex++;
updatePagination();
});
// Page button listeners, consider refactor for dynamic/ lots of pages
pages.forEach( (page, i) => {
page.addEventListener("click", () => {
currentIndex = i;
updatePagination();
});
});
updatePagination();
});