Back

Creating a Minimalist Pagination Component

A clean, simple pagination design with just the essential elements for a distraction-free interface.

HTML

Let's create a minimalist pagination component that focuses on simplicity and elegance:

        <div class="minimal-pagination">
          <span class="page-item" data-page="1">1</span>
          <span class="page-item" data-page="2">2</span>
          <span class="page-item active" data-page="3">3</span>
          <span class="page-item" data-page="4">4</span>
          <span class="page-item" data-page="5">5</span>
        </div>
      
Our HTML structure is intentionally minimal: - We use a simple container with the class "minimal-pagination" - Each page number is a span element with the class "page-item" - We include a data attribute to store the page number for JavaScript - The active page has an additional "active" class - No previous/next buttons - just the page numbers themselves

JavaScript

The JavaScript for our minimalist pagination is straightforward:

        document.addEventListener('DOMContentLoaded', () => {
          const pageItems = document.querySelectorAll('.page-item');
          let currentPage = 3; // Start with page 3 active
          
          function setActivePage(newPage) {
            // Remove active class from current page
            const currentActive = document.querySelector('.page-item.active');
            if (currentActive) {
              currentActive.classList.remove('active');
            }
            
            // Add active class to new page
            const newActive = document.querySelector(`.page-item[data-page="${newPage}"]`);
            if (newActive) {
              newActive.classList.add('active');
              currentPage = newPage;
            }
            
            // In a real app, you would load content for the new page here
            console.log(`Changed to page ${newPage}`);
          }
          
          // Add click event listeners to all page items
          pageItems.forEach(item => {
            item.addEventListener('click', () => {
              const pageNum = parseInt(item.getAttribute('data-page'));
              if (pageNum !== currentPage) {
                setActivePage(pageNum);
              }
            });
          });
        });
      
Our JavaScript is simple and focused: - We track the current active page - We provide a function to change the active page - We add click event listeners to all page numbers - We only update if the user clicks on a different page

CSS

The CSS is where we create the minimalist aesthetic:

        /* Container */
        .minimal-pagination {
          --active-color: #111827;
          --text-color: #9ca3af;
          --hover-color: #4b5563;
          --spacing: 24px;
          --text-size: 18px;
          
          display: flex;
          align-items: center;
          justify-content: center;
          font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
          user-select: none;
        }

        /* Page items */
        .page-item {
          color: var(--text-color);
          font-size: var(--text-size);
          margin: 0 calc(var(--spacing) / 2);
          cursor: pointer;
          position: relative;
          transition: color 0.2s ease;
        }
      
Now let's style the different states of our pagination items:

        /* Hover state */
        .page-item:hover {
          color: var(--hover-color);
        }

        /* Active state */
        .page-item.active {
          color: var(--active-color);
          font-weight: 600;
        }

        /* Underline indicator for active page */
        .page-item.active::after {
          content: '';
          position: absolute;
          bottom: -6px;
          left: 0;
          right: 0;
          height: 2px;
          background-color: var(--active-color);
          border-radius: 2px;
          transform: scaleX(0.8);
          transition: transform 0.2s ease;
        }

        /* Hover effect for active page underline */
        .page-item.active:hover::after {
          transform: scaleX(1);
        }
      
Finally, let's add accessibility enhancements and dark mode support:

        /* Focus indicator for keyboard navigation */
        .page-item:focus-visible {
          outline: 2px solid var(--active-color);
          outline-offset: 2px;
          border-radius: 2px;
        }

        /* Dark mode support */
        @media (prefers-color-scheme: dark) {
          .minimal-pagination {
            --active-color: #f9fafb;
            --text-color: #6b7280;
            --hover-color: #d1d5db;
          }
        }
      
The beauty of this minimalist pagination lies in its simplicity: - Clean aesthetics: No borders, backgrounds, or unnecessary elements - Focus on content: The design doesn't compete with your main content - Subtle interactions: Delicate animations provide feedback without distraction - Adaptability: Works well in both light and dark interfaces - Visual hierarchy: The active page is clearly differentiated without being overwhelming - Reduced cognitive load: Users can focus on the content rather than the navigation This minimalist pagination is perfect for blogs, portfolios, photography sites, or any design-focused website where the interface should complement the content rather than draw attention to itself.

Whole code

<div class="minimal-pagination">
  <span class="page-item" data-page="1">1</span>
  <span class="page-item" data-page="2">2</span>
  <span class="page-item active" data-page="3">3</span>
  <span class="page-item" data-page="4">4</span>
  <span class="page-item" data-page="5">5</span>
</div>

<script>
document.addEventListener('DOMContentLoaded', () => {
  const pageItems = document.querySelectorAll('.page-item');
  let currentPage = 3; // Start with page 3 active
  
  function setActivePage(newPage) {
    // Remove active class from current page
    const currentActive = document.querySelector('.page-item.active');
    if (currentActive) {
      currentActive.classList.remove('active');
    }
    
    // Add active class to new page
    const newActive = document.querySelector(`.page-item[data-page="${newPage}"]`);
    if (newActive) {
      newActive.classList.add('active');
      currentPage = newPage;
    }
    
    // In a real app, you would load content for the new page here
    console.log(`Changed to page ${newPage}`);
  }
  
  // Add click event listeners to all page items
  pageItems.forEach(item => {
    item.addEventListener('click', () => {
      const pageNum = parseInt(item.getAttribute('data-page'));
      if (pageNum !== currentPage) {
        setActivePage(pageNum);
      }
    });
  });
});
</script>

<style>
/* Container */
.minimal-pagination {
  --active-color: #111827;
  --text-color: #9ca3af;
  --hover-color: #4b5563;
  --spacing: 24px;
  --text-size: 18px;
  
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  user-select: none;
}

/* Page items */
.page-item {
  color: var(--text-color);
  font-size: var(--text-size);
  margin: 0 calc(var(--spacing) / 2);
  cursor: pointer;
  position: relative;
  transition: color 0.2s ease;
}

/* Hover state */
.page-item:hover {
  color: var(--hover-color);
}

/* Active state */
.page-item.active {
  color: var(--active-color);
  font-weight: 600;
}

/* Underline indicator for active page */
.page-item.active::after {
  content: '';
  position: absolute;
  bottom: -6px;
  left: 0;
  right: 0;
  height: 2px;
  background-color: var(--active-color);
  border-radius: 2px;
  transform: scaleX(0.8);
  transition: transform 0.2s ease;
}

/* Hover effect for active page underline */
.page-item.active:hover::after {
  transform: scaleX(1);
}

/* Focus indicator for keyboard navigation */
.page-item:focus-visible {
  outline: 2px solid var(--active-color);
  outline-offset: 2px;
  border-radius: 2px;
}

/* Dark mode support */
@media (prefers-color-scheme: dark) {
  .minimal-pagination {
    --active-color: #f9fafb;
    --text-color: #6b7280;
    --hover-color: #d1d5db;
  }
}
</style>
      
Thank you for reading this article.

Comments

More paginations

Similar

See also