How to Implement Pagination with HTML, CSS and JavaScript

Share this article

How to Implement Pagination with HTML, CSS and JavaScript

On the Web, pagination is a way to break up large pieces of content into more bite-sized pieces. In this article, we’ll look at a simple way to divide content into a series of “pages” using HTML, CSS and vanilla JavaScript.

Although pagination can be implemented using frameworks such as React and Angular, the aim of this article is to provide a straightforward, step-by-step guide to setting up pagination, so that we can understand the basic concepts involved.

Table of Contents
  1. Creating Our Base Web Page
  2. Implementing the Pagination Functionality with JavaScript
  3. Adapting Our Code to Other Scenarios
  4. Conclusion

Creating Our Base Web Page

Before implementing our pagination system, let’s create an HTML structure that stores the content we want to display. This can be any kind of content, but for this tutorial, we’ll use a table of five columns and 15 rows that stores the names of students in different grades. Here’s a snippet of our HTML:

<article class="content">
  <table>
    <thead>
      <tr>
        <th>Grade 1</th>
        <th>Grade 2</th>
        <th>Grade 3</th>
        <th>Grade 4</th>
        <th>Grade 5</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>Faith Andrew</td>
        <td>Angela Christopher`</td>
        <td>David Elias</td>
        <td>Samuel Thomas</td>
        <td>Richard Elias</td>
      </tr></tbody>
  </table>
</article>

We’ve wrapped the table in a container element (<article class="content">). While we don’t strictly need a container element, it’s handy to have it, especially if there are other elements on our page. (It gives a useful context for the pagination buttons that we’ll be adding.)

You can view our full HTML code, along with some styling, on CodePen.

Implementing the Pagination Functionality with JavaScript

With our HTML and CSS in place, the next step is to implement pagination. We’ll firstly use JavaScript to divide the table into different “pages” and to add button functionality for navigating through those pages.

Creating a function that divides the table into pages

Here’s our code for dividing the table into separate pieces:

document.addEventListener('DOMContentLoaded', function () {
  const content = document.querySelector('.content'); 
  const itemsPerPage = 5;
  let currentPage = 0;
  const items = Array.from(content.getElementsByTagName('tr')).slice(1);

The first line creates an event listener that ensures that the JavaScript code runs after the HTML content has been fully loaded and parsed. This is to prevent any manipulation or interaction with elements before the content becomes available in the DOM.

With document.querySelector('.content'), we’re selecting the <article class="content"> wrapper and initializing it as a variable.

With const itemsPerPage = 5;, we’re setting the number of rows to display on each page.

With let currentPage = 0;, we’re creating a variable that keeps track of the current page number. It starts at 0, which represents the first page. (The first index in JavaScript is 0, so it counts from 0 instead of 1.)

The last line uses the getElementsByTagName method to select all the elements with a <tr> tag within the table. We create an array (items) of all the child elements and used the slice(1) to exclude the first row (header) and create an array of the remaining rows.

This means that the heading will remain in place as we switch pages.

Working out the showPage() functionality

Next, let’s work on the code for showing pages:

function showPage(page) {
  const startIndex = page * itemsPerPage;
  const endIndex = startIndex + itemsPerPage;
  items.forEach((item, index) => {
    item.classList.toggle('hidden', index < startIndex || index >= endIndex);
  });
  updateActiveButtonStates();
}

We start by creating a showPage() function that accepts a page parameter. This function is responsible for displaying the items connected to that specific page when it’s called.

Next, we calculate the startIndex, which is the first item that should be displayed on the current page by multiplying the page parameter with the itemsPerPage. We also calculate the endIndex that comes immediately after the last item that should be displayed on the current page.

By doing this, we’re creating a range of items to be displayed. For example, let’s say we have ten items and we want to display five items per page. If we’re on the first page (page = 0), startIndex will be 0, and endIndex will be 0 + 5 = 5. This range ([0, 5]) includes the first five items. On the next page (page = 1), startIndex will be 5, and endIndex will be 5 + 5 = 10. This range ([5, 10]) includes the remaining items.

With items.forEach(), we create a loop that iterates through each row and checks if its index falls within the range of items to be displayed on the current page — that is, if it’s either before the startIndex or after/equal to the endIndex. If the index is within the range, the toggle keyword applies the hidden class (which we’ll define in our CSS code) to the item, effectively hiding it. If the index doesn’t meet either condition, the hidden class is removed, making the item visible.

Our hidden class moves the items off screen, hiding them from view but still allowing them to be accessible to those using screen readers:

.hidden {
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  height: 1px;
  overflow: hidden;
  position: absolute;
  white-space: nowrap;
  width: 1px;
}

Adding buttons

Let’s now look at how to add our navigation buttons. In the code below, we’ll create and add the button functionality based on the content of the table:

function createPageButtons() {
  const totalPages = Math.ceil(items.length / itemsPerPage);
  const paginationContainer = document.createElement('div');
  const paginationDiv = document.body.appendChild(paginationContainer);
  paginationContainer.classList.add('pagination');

Firstly, we create a createPageButtons() function that will store the logic to create our buttons. Then we calculate the total pages we’ll need to display our table. We do this by dividing the total number of items by the desired number of items per page. The result is rounded up using the Math.ceil() function. This ensures that all the rows of our table items are covered by the available pages.

Next, we create a div to contain our dynamically generated page buttons (document.createElement('div')). Then we appended the <div> element to the body of our HTML structure using document.body.appendChild(paginationDiv). (We haven’t actually told it where to sit in the HTML structure yes. We’ll do that shortly.) Lastly, we add a class of pagination to that button container so that we can target it with styles.

The next step is to create buttons for each page, using a loop to iterate through each possible page index:

for (let i = 0; i < totalPages; i++) {
const pageButton = document.createElement('button');
pageButton.textContent = i + 1;
pageButton.addEventListener('click', () => {
  currentPage = i;
  showPage(currentPage);
  updateActiveButtonStates();
});

The for loop ranges from 0 (which is the first page) to the total number of pages minus 1.

Within each page iteration, a new individual page button is created using the document.createElement() method, increasing the page number by 1 each time it loops.

Next, we create a click event listener and attach it to the page buttons. When a button is clicked, the event listener’s callback function gets executed.

Here’s an explanation of the callback function:

  • The currentPage variable is updated to the current value of i, which corresponds to the index of the clicked page.
  • The showPage() function is called with the updated currentPage value, causing the content of the clicked page to be displayed.

To finish off our button creation code, we end with this:

content.appendChild(paginationContainer);
paginationDiv.appendChild(pageButton);

We append our button container to the end of our .content wrapper, and then place our buttons inside the button container.

Highlighting active buttons

To make our buttons more user-friendly, we’ll add a distinctive style to the currently “active” button. Let’s create a function that applies the styles of the active CSS class to a button once its page is active:

function updateActiveButtonStates() {
  const pageButtons = document.querySelectorAll('.pagination button');
  pageButtons.forEach((button, index) => {
    if (index === currentPage) {
      button.classList.add('active');
    } else {
      button.classList.remove('active');
    }
  });
}

First, we retrieve all the pagination buttons using the document.querySelectorAll and assign them to the pageButtons variable.

The updateActiveButtonStates() function then goes through each of these buttons one by one, using a forEach loop, and compares its index with the value of the currentPage variable.

Next, we use the conditional if statement to assign the styles of the active class if the button’s index matches the current page.

If the button’s index doesn’t match the current page, the active class is removed. This ensures that the other buttons don’t retain the active class.

To implement this feature, we call the updateActiveButtonStates() function whenever a page is changed or displayed.

Calling on the script

Our pagination script ends with the following two lines:

createPageButtons();
showPage(currentPage);

We call the createPageButtons() function before the showPage() function. This ensures that the buttons are created once the page loads.

Our script now calculates the appropriate range of items to display for each page, listens for button clicks, and updates the page display.

The final result

The following Pen shows the final result.

Adapting Our Code to Other Scenarios

The script we’ve created is handy for breaking up a table into a series of pages. But what if our content is something other than a table? Instead of table content, let’s try our script with some other kinds of content.

Pagination for section elements

Instead of a table element, let’s place some <section> elements inside our container and see how to adapt our script. Here’s our basic HTML:

<article class="content">
  <section></section>
  <section></section>
  <section></section>
  <section></section>
  <section></section>
</article>

We only need to make three very simple changes to our script:

document.addEventListener('DOMContentLoaded', function () {
const content = document.querySelector('.content'); 
const itemsPerPage = 1;
let currentPage = 0;
const items = Array.from(content.getElementsByTagName('section')).slice(0);

The changes are:

  • set itemsPerPage to 1, so that only one section appears per page
  • change the targeted tag name to section, as we’re now looping through <section> elements rather than <tr> elements
  • set slice() to 0, which limits the selection to the first section element (which has index 0)

The following CodePen demo shows this in action.

Pagination for an unordered list

We can easily adapt the demo above to work with a list of items. In the example below, we change the wrapping element from an <article> to a <ul>, and change the <section> elements to <li> elements:

<ul class="content">
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
</ul>

In our JavaScript, we’ll just make two changes:

  • getElementsByTagName('section') becomes getElementsByTagName('li')
  • let’s set const itemsPerPage to 2 to show two list items per page

After some minor CSS changes to account for the unordered list, we end up with the result below.

Conclusion

In this tutorial, we learned how to implement pagination using HTML, CSS and JavaScript. For those without JavaScript enabled (for whatever reason), the full content is still available — just without pagination. By using semantic <button> elements, the page is still keyboard accessible. We’ve also hidden our non-active content by moving it off screen, rather than using display: none, so that it’s still accessible to screen readers.

We could go further by adding descriptive ARIA labels and attributes to convey the purpose and role of elements such as pagination buttons to screen readers.

I hope this demo will get you thinking about simple pagination functionality without needing to reach for a framework.

Frequently Asked Questions (FAQs) about Simple Pagination in HTML, CSS, and JavaScript

How Can I Add Page Numbers to My HTML Document?

Adding page numbers to an HTML document involves using JavaScript to create a pagination system. First, you need to create a list in your HTML where the page numbers will be displayed. Then, in your JavaScript, you will create a function that generates the page numbers based on the total number of items you want to display and how many items you want per page. This function will then be called whenever the page loads or the content changes.

Can I Customize the Look of My Page Numbers with CSS?

Yes, you can customize the look of your page numbers using CSS. You can change the color, size, font, and even the shape of your page numbers. You can also add hover effects to make your page numbers more interactive. To do this, you simply need to target the HTML element that contains your page numbers in your CSS and apply the desired styles.

How Can I Make My Page Numbers Responsive?

Making your page numbers responsive involves using CSS media queries to adjust the size and layout of your page numbers based on the size of the user’s screen. You can also use JavaScript to adjust the number of page numbers displayed based on the screen size. This ensures that your page numbers look good and are easy to use on all devices.

How Can I Start Page Numbering from a Specific Page?

Starting page numbering from a specific page can be achieved by adjusting your JavaScript function that generates the page numbers. You would need to add a parameter to this function that specifies the starting page number. Then, when generating the page numbers, you would start from this number instead of starting from 1.

Can I Add Page Numbers to a Word Document?

Yes, you can add page numbers to a Word document. This is usually done through the ‘Insert’ tab in the Word interface. However, this process is different from adding page numbers to an HTML document and requires a different set of skills.

How Can I Add Page Numbers in LaTeX?

Adding page numbers in LaTeX involves using the \pagenumbering command. This command allows you to specify the style of the page numbers and where they should start. However, this process is different from adding page numbers to an HTML document and requires a different set of skills.

What is the History of Page Numbering?

Page numbering has been used for centuries to help readers navigate books and documents. It originated in the times of hand-written manuscripts and has evolved over time with the development of printing and digital technologies. Today, page numbering is used in a variety of formats, including books, PDFs, and web pages.

Can I Use Pagination with a Database?

Yes, you can use pagination with a database. This involves querying the database to retrieve a specific number of records for each page and then using JavaScript to generate the page numbers. This allows you to display large amounts of data in a user-friendly way.

How Can I Add Previous and Next Buttons to My Page Numbers?

Adding previous and next buttons to your page numbers involves adding two additional elements to your HTML for the buttons and then updating your JavaScript function to change the current page when these buttons are clicked. You can also add styles to these buttons using CSS to make them stand out.

Can I Use Pagination with AJAX?

Yes, you can use pagination with AJAX. This involves using AJAX to load the content for each page without refreshing the entire page. This can make your website faster and more responsive, as only the necessary content is loaded.

Yemi OjedapoYemi Ojedapo
View Author

Yemi is a software developer and technical writer. She enjoys explaining technical concepts related to programming and software in understandable terms. You can read more of her blog posts at dev.to/hyemiie.

pagination
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week