Sticky Positioning: The Best of Both Worlds
When you scroll a web page, some elements move away, and some stay fixed at the top. But what if you want something that moves at first and then sticks when it reaches the top? That’s exactly what CSS position: sticky does.
In this article, you’ll learn what sticky positioning is, why it’s useful, and how to use it with simple, beginner-friendly examples. You’ll write real HTML and CSS, see what each part does, and know what to expect on the screen.
What is Sticky Positioning?
Web pages are made of boxes: headings, paragraphs, menus, sidebars, and so on. CSS controls how these boxes are positioned.
There are a few common position types:
- static – the default; elements flow normally down the page
- fixed – elements stay in one place on the screen, even when you scroll
- sticky – a mix of both: scrolls like normal until a certain point, then “sticks”
Think of position: sticky like a magnet: the element scrolls with the page, and when it reaches a “magnetic zone” (for example, the top of the window), it attaches there and stays visible.
Why Use position: sticky?
Sticky positioning is great when you want:
- A header that stays at the top only after you scroll down
- A table header that follows you as you read a long table
- A sidebar that stays visible while the main content scrolls
The big benefit: the element behaves normally at first, so it doesn’t cover important content at the top, and then it sticks when it’s actually useful.
Example 1: Your First Sticky Header
Let’s build a simple page with a header that sticks to the top after you scroll down.
HTML
Create a file called sticky1.html and add this code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Simple Sticky Header</title>
<style>
body {
margin: 0; /* Remove default browser margin */
font-family: Arial, sans-serif;
line-height: 1.5;
}
header {
position: sticky; /* Make the header sticky */
top: 0; /* Stick to the top of the window */
background: #4a90e2; /* Blue background */
color: white; /* White text */
padding: 10px 20px; /* Space inside the header */
}
.content {
padding: 20px; /* Add space around the text */
}
</style>
</head>
<body>
<header>
<h1>My Sticky Header</h1>
</header>
<div class="content">
<p>Scroll down to see the header stick to the top.</p>
<!-- Repeat this paragraph to create a long page -->
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit...</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit...</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit...</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit...</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit...</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit...</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit...</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit...</p>
</div>
</body>
</html>
What’s happening here?
position: sticky;tells the browser this element can stick.top: 0;tells it where to stick: at the very top of the screen.- At first, the header is just a normal block at the top.
- As you scroll, once the header reaches the top edge, it stays there.
Expected result: When you open this file in your browser and scroll down, the blue header starts near the top, scrolls up, and then “locks” into place at the top. The rest of the page keeps moving underneath it.
Try it yourself
- Change the header’s background color.
- Increase the
paddingto make the header taller. - Add more paragraphs to see how it behaves on a longer page.
Experimenting like this is one of the best ways to learn.
Example 2: Sticky Only After Some Space
What if you want the element to stick after some space from the top? That’s easy: change the top value.
Here’s a header that becomes sticky 50 pixels below the top.
<style>
body {
margin: 0;
font-family: Arial, sans-serif;
}
header {
position: sticky; /* Sticky header */
top: 50px; /* Stick 50px below the top */
background: #333;
color: #fff;
padding: 10px 20px;
}
.spacer {
height: 80px; /* Extra space at the top */
background: #eee;
}
.content {
padding: 20px;
}
</style>
<div class="spacer">This is some space above the header.</div>
<header>
<h2>Sticky, but not at the very top</h2>
</header>
<div class="content">
<p>Scroll down to see when the header sticks.</p>
<!-- Add more content here -->
</div>
What’s different?
top: 50px;means the header will stop 50 pixels from the top.- It scrolls like normal until its top would go above 50px from the top of the window.
- At that point, it sticks and stays at that position.
This is helpful when you have another bar above it, like a site-wide notice or a logo area.
Try it yourself: Change top: 50px; to top: 100px; and see how the sticking point moves.
Example 3: Sticky Sidebar Next to Main Content
Let’s make something more practical: a sticky sidebar that stays visible while the main content scrolls.
This is common for menus, article outlines, or small info boxes.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Sticky Sidebar</title>
<style>
body {
margin: 0;
font-family: Arial, sans-serif;
}
.layout {
display: flex; /* Place children side by side */
align-items: flex-start; /* Align items at the top */
}
.sidebar {
position: sticky; /* Make sidebar sticky */
top: 10px; /* Stick 10px from the top */
width: 200px;
background: #f8f8f8;
border-right: 1px solid #ddd;
padding: 10px;
height: 200px; /* Give it some height */
}
.main {
padding: 20px;
flex: 1; /* Take the remaining width */
}
.section {
margin-bottom: 40px; /* Space between sections */
}
</style>
</head>
<body>
<div class="layout">
<div class="sidebar">
<strong>On this page</strong>
<ul>
<li>Intro</li>
<li>Feature 1</li>
<li>Feature 2</li>
</ul>
</div>
<div class="main">
<div class="section">
<h2>Intro</h2>
<p>Some intro text... (add more text here)</p>
</div>
<div class="section">
<h2>Feature 1</h2>
<p>More text... (add more text here)</p>
</div>
<div class="section">
<h2>Feature 2</h2>
<p>Even more text... (add more text here)</p>
</div>
<!-- Duplicate sections to make the page longer -->
</div>
</div>
</body>
</html>
What you’ll see:
- The sidebar starts near the top on the left.
- As you scroll down the main content, the sidebar stays visible.
- This makes it easier for readers to jump around or see important info.
Try it yourself:
- Add more list items in the sidebar.
- Add more
.sectionblocks with more text. - Increase
top: 10px;totop: 60px;and see the difference.
Common Gotchas with position: sticky
Sometimes sticky elements don’t work the way you expect. Here are a few common issues and simple checks.
The parent is too short
A sticky element can only stick inside the area of its parent container. If the parent isn’t tall enough, the sticky effect may be hard to see.Overflow on parent
If a parent element hasoverflow: hidden,overflow: scroll, oroverflow: auto, it can break sticky behavior. If your sticky element doesn’t work, check the CSS of its parents.Missing
top,bottom,left, orright
Sticky needs at least one of these. Most often you’ll usetop: 0;.
If your sticky element isn’t sticking, review these points one by one. Debugging is a normal part of learning—don’t be discouraged.
Example 4: Sticky Table Header (Bonus)
Here’s a very common use for sticky: keeping table headers visible.
<style>
table {
border-collapse: collapse;
width: 100%;
}
th, td {
border: 1px solid #ccc;
padding: 8px;
text-align: left;
}
thead th {
position: sticky; /* Make table headers sticky */
top: 0; /* Stick to top of table area */
background: #fff; /* White background so text is readable */
}
.table-wrapper {
max-height: 200px; /* Limit height so scrolling happens */
overflow-y: auto; /* Allow vertical scrolling */
}
</style>
<div class="table-wrapper">
<table>
<thead>
<tr>
<th>Name</th>
<th>Age</th>
<th>City</th>
</tr>
</thead>
<tbody>
<!-- Add many rows here to see the effect -->
<tr><td>Alice</td><td>25</td><td>London</td></tr>
<tr><td>Bob</td><td>30</td><td>Paris</td></tr>
<tr><td>Carol</td><td>22</td><td>Berlin</td></tr>
<!-- Duplicate rows -->
</tbody>
</table>
</div>
Result: When you scroll inside the table box, the header row stays at the top, while the data rows move underneath.
Quick Recap and What’s Next
You’ve just learned how position: sticky gives you the best of both worlds: normal scrolling and smart sticking.
Key takeaways:
position: stickylets an element scroll until it hits a position, then stick there.- You must set an offset like
top: 0;to tell it where to stick. - It’s perfect for headers, sidebars, and table headers.
- Sticky behavior happens inside the element’s parent container, and certain
overflowsettings can break it.
If you’ve followed along and tried the examples, you’ve taken real steps into CSS layout—well done. Next, you can explore more layout tools like Flexbox and Grid, and combine them with sticky positioning to build richer, more user-friendly pages.
Keep experimenting, keep breaking things (on purpose!), and you’ll keep learning.
