DEV Community

Cover image for Rails Pagination with Tailwind
Chuck
Chuck

Posted on

10 3

Rails Pagination with Tailwind

Adding pagination to any web site can be a challenge. Luckily, there are a few ways to accomplish this is Rails. This article will add pagination to a simple post and then we will configure Tailwind for styling to pagination block.

TLTR: You can go view the code at the repository.

Setup

So, I have created a fairly basic Rails application using the basic defaults. I scaffold out a Post resource: rails g scaffold Post.

As mentioned I have set up TailwindCSS for styling. This is not a Tailwind CSS tutorial, per se, but if you need help installing and configuring Tailwind in a Rails 6 application, Tuna Çağlar Gümüş has written a wonderful tutorial for this purpose. I have included basic styling to get started as seen here in the following application.html.erb:

<!DOCTYPE html>
<html lang="en" class="h-full">
<head>
  <title>ArticlePagination</title>
  <%= csrf_meta_tags %>
  <%= csp_meta_tag %>

  <%= javascript_pack_tag 'application' %>
  <%= stylesheet_pack_tag 'stylesheets' %>
</head>

<body class="flex flex-col h-full bg-gray-200">
<main class="container mx-auto m-8 flex-1">
  <%= yield %>
</main>

</body>
</html>
Enter fullscreen mode Exit fullscreen mode

To get a post feed setup I have setup posts from JSONplaceholder in the following way:

Install Faraday to make the HTTP requests to JSONPlaceholder. Either bundle add faraday or add to your Gemfile: gem 'faraday' and then bundle install. Add the following to the db/seed.rb file:

@response = Faraday.get 'https://jsonplaceholder.typicode.com/posts'
post_data = JSON.parse(@response.body)

post_data.each do |post|
  Post.create!(
    content: post['body'],
    title: post['title']
  )
end
Enter fullscreen mode Exit fullscreen mode

Then seed the database: rails db:seed.

The post index page is setup like so with the appropriate styling:

<p id="notice"><%= notice %></p>

<h1 class="text-2xl font-semibold my-2">All Posts</h1>

<% @posts.each do |post| %>
  <h2 class="text-xl font-semibold"><%= post.title %></h2>
  <p class="m-1 pb-4"><%= post.content %></p>
<% end %>

<div class="mx-auto text-center my-4">
  <%= will_paginate @posts %>
</div>
<br>
Enter fullscreen mode Exit fullscreen mode

This is how our post feed appears now:
Alt Text

Pagination

Pagination in Rails can be fairly easy with the help of a gem called will_paginate. With this gem, it takes literally two lines of additional code. To get started, install the gem: bundle add will_paginate.

In your Post ERB for the index view, place where you want your pagination to appear: <%= will_paginate @posts %>. Your index.html.erb should like like this:

<h1 class="text-2xl font-semibold my-2">All Posts</h1>

<% @posts.each do |post| %>
  <h2 class="text-xl font-semibold"><%= post.title %></h2>
  <p class="m-1 pb-4"><%= post.content %></p>
<% end %>

<%= will_paginate @posts %>

Enter fullscreen mode Exit fullscreen mode

Add the following to the Post controller's index method:

def index
    @posts = Post.paginate(page: params[:page])
end
Enter fullscreen mode Exit fullscreen mode

The pagination defaults to 30 items and you will probably want to adjust the per_page maximum. Back in the controller file, tweak the index method to the following:

def index
    @posts = Post.paginate(page: params[:page], per_page: 10)
end
Enter fullscreen mode Exit fullscreen mode

You now have a working pagination, however, it is not styled:
Alt Text

There are gem's which will style will_paginate, for instance, if you use Bootstrap there are a few gem's that can quickly add styling for the pagination, but I have yet to find one for Tailwind CSS. This seems like a good future project ... hmm?

So, we will have to add the styling ourselves and fortunately will_paginate does add structured HTML code that already has classes in which we can target.

<div role="navigation" aria-label="Pagination" class="pagination">
  <span class="previous_page disabled">← Previous</span> 
  <em class="current" aria-label="Page 1" aria-current="page">1</em> 
  <a rel="next" aria-label="Page 2" href="/posts?page=2">2</a> 
  <a aria-label="Page 3" href="/posts?page=3">3</a> 
  <a aria-label="Page 4" href="/posts?page=4">4</a> 
  <a class="next_page" rel="next" href="/posts?page=2">Next →</a>
</div>
Enter fullscreen mode Exit fullscreen mode

So the first addition we add is to add a div wrapper that can target to center the pagination block:

<div class="text-center my-4">
    <div role="navigation" aria-label="Pagination" class="pagination">
      <span class="previous_page disabled">← Previous</span> 
      <em class="current" aria-label="Page 1" aria-current="page">1</em> 
      <a rel="next" aria-label="Page 2" href="/posts?page=2">2</a> 
      <a aria-label="Page 3" href="/posts?page=3">3</a> 
      <a aria-label="Page 4" href="/posts?page=4">4</a> 
      <a class="next_page" rel="next" href="/posts?page=2">Next →</a>
    </div>
</div>
Enter fullscreen mode Exit fullscreen mode

We will add the new styling to the app/javascript/css/application.scss stylesheet and will start with the pagination class.

@import "~tailwindcss/base";
@import "~tailwindcss/components";

.pagination {
  @apply flex justify-center;
  @apply my-2 py-2;
}

@import "~tailwindcss/utilities"; 
Enter fullscreen mode Exit fullscreen mode

FYI. Make sure you add your custom styling between the tailwindcss/components and utilities.

Then we need to target each child element of the parent pagination class:

.pagination * {
  @apply px-3 py-2 mx-2;
  @apply text-gray-700 no-underline bg-white rounded-lg;
}
Enter fullscreen mode Exit fullscreen mode

Now finally we add the hover styling:

.pagination a:hover {
  @apply font-semibold text-gray-200 bg-gray-700;
}
Enter fullscreen mode Exit fullscreen mode

Now you have a nice pagination block styled with Tailwind CSS:
Alt Text

Thank you for reading and message me with any question you may have.

Image of Datadog

The Future of AI, LLMs, and Observability on Google Cloud

Datadog sat down with Google’s Director of AI to discuss the current and future states of AI, ML, and LLMs on Google Cloud. Discover 7 key insights for technical leaders, covering everything from upskilling teams to observability best practices

Learn More

Top comments (2)

Collapse
 
duartemartins profile image
Duarte Martins

FYI Faker is a great gem for seeding.

Collapse
 
eertmanhidde profile image
eertmanhidde

Great article!

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more