CSS Position
What is Position?
The position property determines how an element is placed on the web page. Every element has a position type that affects how top, right, bottom, left, and z-index work.
CSS has five position values: static, relative, absolute, fixed, and sticky.
Position Values
static (Default)
This is the default value for all elements. The element follows the normal document flow — placed sequentially from top to bottom, left to right.
The top, right, bottom, left, and z-index properties have NO effect on static elements.
position: static;
relative
The element stays in the normal document flow, but can be shifted relative to its original position. The space occupied by the element remains the same — the element shifts visually, but does not affect the position of other elements.
position: relative;
top: 10px; /* Shift 10px down from the original position */
left: 20px; /* Shift 20px right from the original position */
absolute
The element is removed from the document flow. It is positioned relative to the nearest positioned ancestor (an ancestor with a position other than static). If no positioned ancestor exists, it is positioned relative to <html> (the viewport).
position: absolute;
top: 0;
right: 0;
fixed
The element is removed from the document flow. It is positioned relative to the browser's viewport. The element stays in the same place even when the page is scrolled.
position: fixed;
bottom: 20px;
right: 20px;
sticky
The element behaves like relative until it reaches the defined scroll threshold, then behaves like fixed (sticks in place).
position: sticky;
top: 0;
Code Example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSS Position</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
background-color: #f5f5f5;
padding: 20px;
color: #333;
padding-top: 60px;
}
h1 {
margin-bottom: 25px;
}
.section {
background-color: white;
border-radius: 8px;
padding: 20px;
margin-bottom: 25px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.08);
}
h2 {
margin-bottom: 15px;
color: #2c3e50;
}
p {
line-height: 1.6;
color: #555;
margin-bottom: 10px;
}
code {
background-color: #f0f0f0;
padding: 2px 6px;
border-radius: 3px;
font-size: 13px;
}
.demo-box {
padding: 10px 15px;
font-size: 13px;
font-weight: bold;
color: white;
border-radius: 4px;
margin-bottom: 5px;
}
/* === Static Position === */
.static-box {
background-color: #3498db;
}
/* === Relative Position === */
.relative-container {
background-color: #ecf0f1;
padding: 20px;
border-radius: 6px;
margin-bottom: 10px;
position: relative;
}
.relative-original {
background-color: #95a5a6;
color: white;
padding: 10px;
margin-bottom: 10px;
border-radius: 4px;
font-size: 13px;
}
.relative-box {
background-color: #e74c3c;
position: relative;
top: 10px;
left: 20px;
}
.relative-space-marker {
border: 2px dashed #e74c3c;
padding: 10px;
font-size: 12px;
color: #e74c3c;
border-radius: 4px;
background-color: rgba(231, 76, 60, 0.05);
}
/* === Absolute Position === */
.absolute-container {
position: relative;
background-color: #ecf0f1;
padding: 20px;
height: 200px;
border-radius: 6px;
margin-bottom: 10px;
}
.absolute-container-label {
font-size: 12px;
color: #888;
margin-bottom: 10px;
}
.absolute-box {
background-color: #2ecc71;
position: absolute;
padding: 10px 15px;
font-size: 13px;
font-weight: bold;
border-radius: 4px;
color: white;
}
.abs-top-left { top: 10px; left: 10px; }
.abs-top-right { top: 10px; right: 10px; }
.abs-bottom-left { bottom: 10px; left: 10px; }
.abs-bottom-right { bottom: 10px; right: 10px; }
.abs-center {
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
/* === Fixed Position === */
.fixed-header {
position: fixed;
top: 0;
left: 0;
right: 0;
background-color: #2c3e50;
color: white;
padding: 15px 20px;
font-weight: bold;
font-size: 16px;
z-index: 1000;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}
.fixed-fab {
position: fixed;
bottom: 30px;
right: 30px;
width: 56px;
height: 56px;
border-radius: 50%;
background-color: #e74c3c;
color: white;
border: none;
font-size: 24px;
cursor: pointer;
box-shadow: 0 4px 12px rgba(231, 76, 60, 0.4);
display: flex;
align-items: center;
justify-content: center;
z-index: 999;
}
/* === Sticky Position === */
.sticky-demo {
height: 300px;
overflow-y: scroll;
border: 2px solid #ddd;
border-radius: 6px;
}
.sticky-item {
padding: 12px 15px;
font-size: 14px;
border-bottom: 1px solid #eee;
}
.sticky-item:nth-child(odd) {
background-color: #f9f9f9;
}
.sticky-header {
position: sticky;
top: 0;
background-color: #3498db;
color: white;
padding: 10px 15px;
font-weight: bold;
font-size: 13px;
z-index: 1;
}
/* === Z-Index Demo === */
.z-index-container {
position: relative;
height: 200px;
background-color: #ecf0f1;
border-radius: 6px;
overflow: hidden;
}
.z-box {
position: absolute;
width: 120px;
height: 120px;
border-radius: 6px;
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
font-weight: bold;
color: white;
}
.z-1 { background-color: rgba(231, 76, 60, 0.8); top: 20px; left: 20px; z-index: 1; }
.z-2 { background-color: rgba(52, 152, 219, 0.8); top: 50px; left: 80px; z-index: 2; }
.z-3 { background-color: rgba(46, 204, 113, 0.8); top: 80px; left: 140px; z-index: 3; }
/* === Modal Overlay === */
.modal-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 2000;
}
.modal-content {
background-color: white;
padding: 30px;
border-radius: 12px;
max-width: 400px;
width: 90%;
text-align: center;
}
.modal-content h3 {
margin-bottom: 10px;
color: #2c3e50;
}
.modal-content p {
margin-bottom: 20px;
}
.modal-btn {
padding: 10px 24px;
background-color: #3498db;
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 14px;
font-weight: bold;
}
/* === Tooltip === */
.tooltip-demo {
position: relative;
display: inline-block;
}
.tooltip-text {
position: absolute;
bottom: 100%;
left: 50%;
transform: translateX(-50%);
background-color: #333;
color: white;
padding: 6px 12px;
border-radius: 4px;
font-size: 12px;
white-space: nowrap;
opacity: 0;
transition: opacity 0.3s;
margin-bottom: 8px;
}
.tooltip-text::after {
content: '';
position: absolute;
top: 100%;
left: 50%;
transform: translateX(-50%);
border: 6px solid transparent;
border-top-color: #333;
}
.tooltip-demo:hover .tooltip-text {
opacity: 1;
}
.tooltip-btn {
padding: 10px 20px;
background-color: #9b59b6;
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 14px;
font-weight: bold;
}
</style>
</head>
<body>
<h1>CSS Position</h1>
<!-- Fixed Header -->
<div class="fixed-header">
Fixed Header — Stays at the top when scrolling
</div>
<!-- Fixed FAB -->
<button class="fixed-fab">+</button>
<!-- Static Position -->
<div class="section">
<h2>position: static (Default)</h2>
<p>All elements use static by default. Elements follow the normal document flow:</p>
<div class="demo-box static-box">Static 1</div>
<div class="demo-box static-box">Static 2</div>
<div class="demo-box static-box">Static 3</div>
</div>
<!-- Relative Position -->
<div class="section">
<h2>position: relative</h2>
<p>The element shifts relative to its original position. The space it occupies stays the same:</p>
<div class="relative-container">
<div class="relative-original">Original box (before the red box shifted)</div>
<div class="relative-space-marker">This box stays in place — the red box's space is still here</div>
<div class="relative-box">
Relative — top: 10px, left: 20px
</div>
</div>
</div>
<!-- Absolute Position -->
<div class="section">
<h2>position: absolute</h2>
<p>The element is placed relative to the nearest positioned ancestor (the relative container below):</p>
<div class="absolute-container">
<div class="absolute-container-label">Positioned Parent (relative)</div>
<div class="absolute-box abs-top-left">Top Left</div>
<div class="absolute-box abs-top-right">Top Right</div>
<div class="absolute-box abs-bottom-left">Bottom Left</div>
<div class="absolute-box abs-bottom-right">Bottom Right</div>
<div class="absolute-box abs-center">Center</div>
</div>
</div>
<!-- Sticky Position -->
<div class="section">
<h2>position: sticky</h2>
<p>The element sticks when scrolled. Try scrolling inside the box below:</p>
<div class="sticky-demo">
<div class="sticky-item sticky-header">Sticky Header — Sticks on scroll</div>
<div class="sticky-item">Item 1</div>
<div class="sticky-item">Item 2</div>
<div class="sticky-item">Item 3</div>
<div class="sticky-item">Item 4</div>
<div class="sticky-item">Item 5</div>
<div class="sticky-item">Item 6</div>
<div class="sticky-item sticky-header">Sticky Header 2 — Sticks again</div>
<div class="sticky-item">Item 7</div>
<div class="sticky-item">Item 8</div>
<div class="sticky-item">Item 9</div>
<div class="sticky-item">Item 10</div>
</div>
</div>
<!-- Z-Index -->
<div class="section">
<h2>Z-Index (Stacking Order)</h2>
<p>z-index determines the stacking order of elements. The higher the value, the further on top:</p>
<div class="z-index-container">
<div class="z-box z-1">z-index: 1</div>
<div class="z-box z-2">z-index: 2</div>
<div class="z-box z-3">z-index: 3</div>
</div>
</div>
<!-- Tooltip -->
<div class="section">
<h2>Tooltip with Position Absolute</h2>
<p>Hover the button below to see the tooltip:</p>
<div class="tooltip-demo">
<span class="tooltip-text">This is a tooltip!</span>
<button class="tooltip-btn">Hover Me</button>
</div>
</div>
<!-- Modal Overlay -->
<div class="section">
<h2>Modal Overlay</h2>
<p>A modal overlay uses fixed position to cover the entire viewport:</p>
<div class="modal-overlay">
<div class="modal-content">
<h3>Confirmation</h3>
<p>Are you sure you want to continue?</p>
<button class="modal-btn" onclick="this.closest('.modal-overlay').style.display='none'">Close Modal</button>
</div>
</div>
</div>
<!-- Spacer for scroll demo -->
<div style="height: 400px;"></div>
</body>
</html>
Code Explanation
-
Static — Three blue boxes that follow the normal document flow.
top,left, etc. have no effect on static elements. -
Relative — The red box is shifted 10px down and 20px right from its original position. Note that its original space (marked with a dashed border) is still there.
-
Absolute — Five green boxes placed in different corners of the relative container:
top: 10px; left: 10px— Top-left cornertop: 10px; right: 10px— Top-right cornerbottom: 10px; left: 10px— Bottom-left cornerbottom: 10px; right: 10px— Bottom-right corner-
top: 50%; left: 50%; transform: translate(-50%, -50%)— Perfect center -
Fixed — A dark header at the top that stays visible even when the page is scrolled. There is also a red FAB (Floating Action Button) in the bottom-right corner that is always visible.
-
Sticky — A scrollable list of items. The blue header uses
position: sticky; top: 0so it sticks to the top of the container when scrolled. -
Z-Index — Three overlapping boxes showing the stacking order: red (z-index: 1) at the bottom, blue (z-index: 2) in the middle, green (z-index: 3) on top.
-
Tooltip — A purple button with a tooltip that appears on hover. It uses
position: absoluteon the tooltip andposition: relativeon the parent. -
Modal — A transparent overlay covering the entire viewport with the modal centered. It uses
position: fixedon the overlay.
Everyday Use Cases
<!DOCTYPE html>
<html lang="en">
<head>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: Arial, sans-serif;
background-color: #f5f5f5;
color: #333;
}
/* === Sticky Sidebar Layout === */
.layout {
display: flex;
min-height: 100vh;
}
.sidebar {
width: 260px;
background-color: #2c3e50;
color: white;
position: sticky;
top: 0;
height: 100vh;
overflow-y: auto;
}
.sidebar-header {
padding: 20px;
font-size: 18px;
font-weight: bold;
border-bottom: 1px solid #34495e;
}
.sidebar-nav {
list-style: none;
}
.sidebar-nav li a {
display: block;
padding: 12px 20px;
color: #bdc3c7;
text-decoration: none;
font-size: 14px;
transition: all 0.2s;
}
.sidebar-nav li a:hover,
.sidebar-nav li a.active {
background-color: #34495e;
color: white;
border-left: 3px solid #3498db;
}
.main-content {
flex: 1;
padding: 30px;
}
.main-content h1 {
font-size: 24px;
margin-bottom: 20px;
color: #2c3e50;
}
.content-card {
background-color: white;
padding: 24px;
border-radius: 8px;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
margin-bottom: 20px;
}
.content-card h2 {
font-size: 18px;
margin-bottom: 12px;
color: #2c3e50;
}
.content-card p {
line-height: 1.7;
color: #555;
}
/* === Badge on Card === */
.card-with-badge {
position: relative;
overflow: hidden;
}
.badge {
position: absolute;
top: 12px;
right: -30px;
background-color: #e74c3c;
color: white;
padding: 4px 40px;
font-size: 11px;
font-weight: bold;
transform: rotate(45deg);
}
/* === Floating Labels === */
.form-group {
position: relative;
margin-bottom: 20px;
max-width: 400px;
}
.form-group input {
width: 100%;
padding: 14px 12px 6px;
border: 2px solid #ddd;
border-radius: 6px;
font-size: 14px;
outline: none;
}
.form-group input:focus {
border-color: #3498db;
}
.form-group label {
position: absolute;
top: 14px;
left: 12px;
font-size: 14px;
color: #999;
transition: all 0.2s;
pointer-events: none;
}
.form-group input:focus + label,
.form-group input:not(:placeholder-shown) + label {
top: 4px;
font-size: 11px;
color: #3498db;
}
/* === Sticky Table of Contents === */
.toc {
position: sticky;
top: 20px;
background-color: white;
padding: 16px;
border-radius: 8px;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
max-width: 200px;
}
.toc h3 {
font-size: 14px;
margin-bottom: 10px;
color: #2c3e50;
}
.toc ul {
list-style: none;
}
.toc ul li {
margin-bottom: 6px;
}
.toc ul li a {
font-size: 13px;
color: #3498db;
text-decoration: none;
}
.toc ul li a:hover {
text-decoration: underline;
}
</style>
</head>
<body>
<div class="layout">
<!-- Sticky Sidebar -->
<aside class="sidebar">
<div class="sidebar-header">SkillVersitas</div>
<ul class="sidebar-nav">
<li><a href="#" class="active">Dashboard</a></li>
<li><a href="#">Courses</a></li>
<li><a href="#">Assignments</a></li>
<li><a href="#">Grades</a></li>
<li><a href="#">Settings</a></li>
<li><a href="#">Profile</a></li>
<li><a href="#">Help</a></li>
</ul>
</aside>
<!-- Main Content -->
<main class="main-content">
<h1>Student Dashboard</h1>
<!-- Card with Badge -->
<div class="content-card card-with-badge">
<div class="badge">NEW</div>
<h2>New Course: CSS Animation</h2>
<p>Our latest course on CSS Animation is now available. Learn how to create beautiful animations without JavaScript.</p>
</div>
<div class="content-card">
<h2>Learning Progress</h2>
<p>You have completed 12 of 20 CSS modules. Keep up the great learning momentum!</p>
</div>
<!-- Floating Label Form -->
<div class="content-card">
<h2>Form Floating Labels</h2>
<div class="form-group">
<input type="text" id="name" placeholder=" " value="">
<label for="name">Full Name</label>
</div>
<div class="form-group">
<input type="email" id="email" placeholder=" " value="[email protected]">
<label for="email">Email</label>
</div>
</div>
</main>
</div>
</body>
</html>
In the example above:
- Sticky Sidebar — The sidebar uses position: sticky; top: 0; height: 100vh so it stays visible while scrolling the main content
- Badge — The "NEW" label uses position: absolute; top: 12px; right: -30px; transform: rotate(45deg) to create a diagonal banner in the card corner
- Floating Labels — A form input with a label that moves up when the input is focused, using position: absolute and CSS transitions
Position Comparison
| Position | Document Flow | Relative To | Can use z-index |
|---|---|---|---|
static |
Follows flow | None | No |
relative |
Follows flow + offset | Its original position | Yes |
absolute |
Removed | Nearest positioned ancestor | Yes |
fixed |
Removed | Viewport | Yes |
sticky |
Relative → Fixed | Scroll container | Yes |
Conclusion
static— Default. The element follows the normal document flow.top/right/bottom/left/z-indexhave no effect.relative— The element shifts relative to its original position. The space it occupies stays the same.absolute— The element is removed from the document flow and positioned relative to the nearest positioned ancestor.fixed— The element is removed from the document flow and positioned relative to the viewport. It stays in place when scrolling.sticky— Relative until the scroll threshold, then becomes fixed. Useful for sticky headers and sidebars.z-index— Controls the stacking order of elements (only works on positioned elements: relative, absolute, fixed, sticky).- For perfect centering:
position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%).