Skip to content

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();
    });