Difficulty: Intermediate
The CSS position property controls how an element is placed within the document layout. It is one of the most fundamental CSS properties, and understanding its values is essential for building any non-trivial layout. The two simplest values are static (the default) and relative, which form the foundation for all other positioning modes.
position: static is the default value for every element. A statically positioned element follows the normal document flow - block elements stack vertically, inline elements flow horizontally. The offset properties (top, right, bottom, left) and z-index have absolutely no effect on a statically positioned element. You rarely need to write position: static explicitly, but it can be useful to reset an element's positioning when overriding inherited styles or media query breakpoints.
position: relative shifts an element from its normal position without removing it from the document flow. When you set position: relative and apply top: 20px, the element renders 20px lower than where it would normally appear, but the space it originally occupied is preserved. Other elements do not move to fill the gap. Think of it as the element leaving a "ghost" in its original position while visually shifting elsewhere.
The offset properties work directionally with relative positioning: top pushes the element down from its normal position, left pushes it right, bottom pushes it up, and right pushes it left. If you set both top and bottom, top takes precedence. If you set both left and right, left takes precedence (in LTR languages). Offsets can be negative values, which push the element in the opposite direction.
The most important use of position: relative is not for shifting elements, but for establishing a containing block for absolutely positioned children. When an element has position: relative (even without any offsets), it becomes the reference point for any descendant element with position: absolute. This parent-child relationship is the foundation of most complex positioning patterns in CSS.
<style>
.box {
width: 150px;
height: 80px;
margin: 10px;
border: 2px solid #e2e8f0;
}
.static-box {
position: static;
background: #dbeafe;
/* top, left have NO effect on static elements */
top: 50px;
left: 50px;
}
.relative-box {
position: relative;
background: #dcfce7;
top: 30px;
left: 40px;
}
</style>
<div class="box static-box">Static (top/left ignored)</div>
<div class="box relative-box">Relative (shifted 30px down, 40px right)</div>
<div class="box static-box">Static (notice the gap above)</div>
The static box ignores top and left. The relative box shifts visually but its original space is preserved - the third box does not move up to fill the gap. The relative box appears to overlap content below its original position.
<style>
.container {
padding: 40px;
background: #f8fafc;
position: relative;
}
.item {
width: 120px;
height: 60px;
background: #3b82f6;
color: white;
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
}
.move-down { position: relative; top: 30px; }
.move-right { position: relative; left: 50px; }
.move-up { position: relative; bottom: 20px; }
.move-left { position: relative; right: 40px; }
.negative { position: relative; top: -15px; left: -10px; }
</style>
<div class="container">
<div class="item">Normal</div>
<div class="item move-down">top: 30px</div>
<div class="item move-right">left: 50px</div>
<div class="item move-up">bottom: 20px</div>
<div class="item move-left">right: 40px</div>
<div class="item negative">top: -15px</div>
</div>
top pushes down, left pushes right, bottom pushes up, right pushes left. Negative values reverse the direction. Each element's original space is preserved in the flow, so subsequent elements do not reposition.
<style>
.card {
position: relative; /* Creates containing block */
width: 300px;
padding: 20px;
background: white;
border: 1px solid #e2e8f0;
margin: 20px;
}
.badge {
position: absolute;
top: -10px;
right: -10px;
background: #ef4444;
color: white;
width: 24px;
height: 24px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
}
</style>
<div class="card">
<span class="badge">3</span>
<h3>Notifications</h3>
<p>You have 3 unread messages.</p>
</div>
The card has position: relative with no offsets - it stays in its normal position. But it now serves as the containing block for the absolutely positioned badge. The badge positions itself relative to the card's edges, not the viewport.
<style>
.sidebar {
position: relative;
top: 20px;
left: 10px;
width: 250px;
background: #f1f5f9;
padding: 16px;
}
@media (max-width: 768px) {
.sidebar {
position: static; /* Reset to normal flow on mobile */
width: 100%;
/* top and left are now ignored */
}
}
</style>
<aside class="sidebar">
<h3>Sidebar</h3>
<p>Relatively positioned on desktop, static on mobile.</p>
</aside>
Explicitly setting position: static resets the element to normal document flow. This is useful in responsive designs where an element needs positioning on desktop but should flow normally on mobile.
position: static, position: relative, top, right, bottom, left, Document Flow