Add infinite scroll with Django and HTMX in 60 seconds ♾️
Published: November 17, 2023
I’ll show you how to add infinite scrolling to your Django app in 60 seconds using HTMX.
Infinite scroll speeds up your initial page load. Instead of immediately loading all content, you only load content as your users scroll.
There are 5 steps to add infinite scroll with HTMX and Django below.
Our finished Django app with infinite scrolling will look like this:
Optional video tutorial featuring me below 📽️:

Update: Here's me presenting this guide at the Django Meetup in London 🇬🇧 in November
Let’s go 🚀
Setup Django app
- Install our requirements into a virtual environment and create our Django project and app:
pip install django fakerdjango-admin startproject core .python manage.py startapp sim
Update settings.py
INSTALLED_APPS = [# ...'sim',]
1. Create the Model and Sample Data
# sim/models.pyfrom django.db import modelsclass Article(models.Model):title = models.CharField(max_length=255)content = models.TextField()photo_url = models.URLField()def __str__(self):return self.title
- Run migrations:
python manage.py makemigrationspython manage.py migrate
- Generate some sample data:
python manage.py shell
# In the python shell:from sim.models import Articlefrom faker import Fakerfake = Faker()for i in range(100):sentences = ' '.join(fake.sentences(5))Article.objects.create(title=fake.sentence(),content=sentences,photo_url=f"https://picsum.photos/seed/{i+1}/600")
2. Create the views
# sim/views.pyfrom django.core.paginator import Paginatorfrom django.shortcuts import renderfrom .models import Articledef articles(request):"""Fetch paginated articles and render them."""page_number = request.GET.get('page', 1)paginator = Paginator(Article.objects.all(), 10)page_obj = paginator.get_page(page_number)return render(request, 'articles.html', {'page_obj': page_obj})
3. Update URLs
- Update core/urls.py
from django.contrib import adminfrom django.urls import path, includeurlpatterns = [path('admin/', admin.site.urls),path('', include('sim.urls')),]
- Create
sim/urls.py
containing:
from django.urls import pathfrom . import viewsurlpatterns = [path('', views.articles, name='articles'),]
4. Create HTML template
- Create templates folder at
sim/templates/
- Create
articles.html
insim/templates/
containing:
<!doctype html><html><head><scriptsrc="https://unpkg.com/htmx.org@1.9.6"integrity="sha384-FhXw7b6AlE/jyjlZH5iHa/tTe9EpJ1Y55RjcgPbjeWMskSxZt1v9qkxLJWNJaGni"crossorigin="anonymous"></script><style>/* Body and Container Styles */body {font-family: Arial, sans-serif;line-height: 1.6;margin: 0;padding: 0;}#articles {display: grid;grid-template-columns: repeat(3, 1fr);gap: 20px;max-width: 1200px;margin: auto;padding: 20px;}h1 {grid-column: 1 / -1;/* Span all columns */margin-bottom: 20px;text-align: center;text-decoration: underline;}/* Article Styles */.article {border: 1px solid #ccc;padding: 20px;border-radius: 8px;}.article h2 {font-size: 24px;margin-bottom: 10px;text-align: center;}.image-container {display: flex;justify-content: center;}.article img {max-width: 100%;height: auto;border-radius: 8px;}.article p {text-align: justify;}</style></head><body><h1>Articles</h1><div id="articles">{% for article in page_obj %}<div class="article"><h2>{{ article.title }}</h2><a class="image-container" href="{{ article.photo_url }}"><imgwidth="300"height="300"src="{{ article.photo_url }}"alt="A sample image"/></a><p>{{ article.content }}</p>{% if page_obj.has_next and forloop.last %}<spanhx-get="{% url 'articles' %}?page={{ page_obj.next_page_number }}"hx-swap="beforeend"hx-target="#articles"hx-select=".article"hx-trigger="revealed"></span>{% endif %}</div>{% endfor %}</div></body></html>
5. Run our server
python manage.py runserver
- Visit your development server, normally at http://127.0.0.1:8000/
Finished - You can now scroll infinitely through your articles 🎉
You've just built a sleek Django app complete with infinite scrolling. You get the benefits of loading the content that the user wants on demand, meaning a much faster initial page load.