CSS
Positioning
Place elements exactly where you want them — floating headers, overlays, and complex layouts.
CSS positioning controls exactly where elements appear on your page. Think of it like placing stickers on a poster — you can put them in the normal flow with other stickers, stick them to specific spots, or even make them float on top of everything else. By default, HTML elements stack like books on a table — each new element sits below the previous one. But what if you want a navigation menu that stays at the top while users scroll? Or a popup that appears over your content? That's where positioning becomes essential.Understanding Position Types
Theposition property has five main values that control how elements behave. Each one changes how the element relates to other elements and the page itself.
Default behavior — elements follow normal document flow
Move from original position but keep the space reserved
Position relative to nearest positioned parent
Stay in same spot even when page scrolls
Static Positioning (Default)
Every element starts withposition: static. This means elements appear in normal document flow — paragraphs below headings, images after text, exactly as you'd expect when reading HTML from top to bottom.
/* WanderLust hero section with static positioning */
.hero-content {
position: static; /* This is the default */
background: #0ea5e9;
color: white;
padding: 40px;
text-align: center;
}What just happened?
Elements appear in normal order — the hero section comes first, followed by the destination card. Static positioning means "just put it where it naturally belongs."
Relative Positioning
position: relative allows you to nudge an element from its original spot using `top`, `right`, `bottom`, and `left` properties. The element moves, but its original space stays reserved — like moving a book but leaving a bookmark where it was.
/* Move WanderLust booking button slightly up */
.booking-button {
position: relative;
top: -10px; /* Move up 10 pixels from normal position */
left: 20px; /* Move right 20 pixels */
background: #f97316;
color: white;
padding: 15px 30px;
border: none;
border-radius: 8px;
}What just happened?
The button shifted up and right from where it would normally appear, but the space below still treats the button as if it's in its original position. That's why there's extra space between sections.
Absolute Positioning
position: absolute removes an element completely from normal document flow. The element positions itself relative to the nearest positioned parent (any parent with position other than static). If no positioned parent exists, it positions relative to the entire page body.
This is perfect for creating overlays, tooltips, or elements that need precise placement regardless of surrounding content.
/* Position WanderLust sale badge over destination card */
.destination-card {
position: relative; /* Creates positioning context */
background: white;
border-radius: 12px;
padding: 20px;
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
}
.sale-badge {
position: absolute;
top: 15px; /* 15px from top of card */
right: 15px; /* 15px from right of card */
background: #dc2626;
color: white;
padding: 8px 12px;
border-radius: 20px;
font-size: 12px;
font-weight: bold;
}What just happened?
The sale badge positioned itself 15px from the top-right corner of its parent card. Because the card has position: relative, it became the positioning context for the absolutely positioned badge.
Centering with Absolute Position
A common technique uses absolute positioning to perfectly center elements. This works by positioning the element's top-left corner at 50% from the top and left, then using transforms to shift it back by half its own size./* Center WanderLust loading popup on screen */
.loading-popup {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%); /* Move back by half width/height */
background: white;
padding: 40px;
border-radius: 16px;
box-shadow: 0 8px 24px rgba(0,0,0,0.15);
text-align: center;
min-width: 200px;
}What just happened?
The popup positioned its top-left corner at 50% from top and left, then the transform shifted it back by half its own width and height. This creates perfect centering regardless of the popup's size. Try this: resize your browser — the popup stays centered!
Fixed Positioning
position: fixed creates elements that stay in the exact same spot even when users scroll. This is perfect for navigation bars, chat buttons, or notifications that should always be visible.
Fixed elements position themselves relative to the browser viewport (the visible area of the page), not any parent element.
/* WanderLust sticky navigation that stays at top */
.fixed-nav {
position: fixed;
top: 0; /* Stick to very top of screen */
left: 0;
right: 0; /* Stretch full width */
background: #0f172a;
color: white;
padding: 15px 30px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
z-index: 100; /* Stay above other content */
}
/* Add top padding to body so content doesn't hide under nav */
body {
padding-top: 70px;
}What just happened?
The navigation fixed itself to the top of the viewport and stays there during scrolling. We added padding-top to the content so it doesn't get hidden behind the fixed nav. The z-index ensures the nav appears above other content.
Sticky Positioning
position: sticky combines the best of relative and fixed positioning. Elements behave normally until they reach a specified scroll position, then they "stick" in place until their parent container scrolls out of view.
/* WanderLust section header that sticks while scrolling */
.sticky-header {
position: sticky;
top: 20px; /* How far from top before it sticks */
background: #f97316;
color: white;
padding: 15px 25px;
border-radius: 8px;
font-weight: bold;
margin-bottom: 20px;
}
.destination-section {
margin-bottom: 50px;
padding: 20px;
background: white;
border-radius: 12px;
}What just happened?
Each section header starts in normal document flow, but when you scroll and the header reaches 20px from the top, it sticks there. When you scroll past that section, the header unsticks and the next section's header takes over. This creates a floating table of contents effect.
Positioning Properties
Once you set a position value other than static, you can usetop, right, bottom, and left properties to specify exactly where the element should go. These values can be pixels, percentages, or other CSS units.
identifier Property
name Property
value Distance
measurement
top: 20px means "place this element 20 pixels down from the top edge of the nearest positioned parent."
Common Gotcha
When using absolute positioning, remember that top and bottom work together, as do left and right. Setting top: 10px and bottom: 10px will stretch the element to fill the space between those points, not position it at both locations.
Overlapping Elements
When elements overlap due to positioning, the stacking order becomes important. Elements that appear later in HTML naturally stack on top of earlier elements, but you can control this with the `z-index` property./* Layer WanderLust destination images with different z-index */
.image-stack {
position: relative;
height: 200px;
width: 300px;
margin: 30px;
}
.destination-image {
position: absolute;
width: 150px;
height: 100px;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: bold;
}
.image-1 {
background: #0ea5e9;
top: 0;
left: 0;
z-index: 3; /* Front layer */
}
.image-2 {
background: #f97316;
top: 30px;
left: 40px;
z-index: 2; /* Middle layer */
}
.image-3 {
background: #7c3aed;
top: 60px;
left: 80px;
z-index: 1; /* Back layer */
}What just happened?
Three destination cards overlap at different positions. The z-index values control which appears in front — Paris (z-index: 3) appears on top, Tokyo (z-index: 2) in the middle, and Sydney (z-index: 1) in the back, regardless of their HTML order.
Practical Positioning Patterns
Real websites use positioning for specific interface patterns. The WanderLust team frequently needs these common layouts for their booking system and destination galleries./* Complete WanderLust card with multiple positioned elements */
.travel-card {
position: relative;
background: white;
border-radius: 16px;
overflow: hidden;
box-shadow: 0 6px 20px rgba(0,0,0,0.1);
max-width: 320px;
}
.card-image {
height: 180px;
background: linear-gradient(45deg, #0ea5e9, #3b82f6);
position: relative;
}
.price-badge {
position: absolute;
top: 15px;
right: 15px;
background: rgba(255,255,255,0.9);
color: #0f172a;
padding: 8px 12px;
border-radius: 20px;
font-weight: bold;
backdrop-filter: blur(10px);
}
.favorite-heart {
position: absolute;
top: 15px;
left: 15px;
background: rgba(0,0,0,0.3);
color: white;
width: 40px;
height: 40px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
.card-content {
padding: 20px;
}
.book-button {
position: absolute;
bottom: 20px;
right: 20px;
background: #f97316;
color: white;
border: none;
padding: 10px 20px;
border-radius: 8px;
cursor: pointer;
font-weight: bold;
}What just happened?
This travel card combines multiple positioning techniques — the price badge and heart icon use absolute positioning to float over the image, while the book button positions itself in the bottom-right corner of the entire card. The main card uses relative positioning to create a positioning context for all the absolute elements inside it.
Quiz
1. The WanderLust team wants to position a sale badge on top of a destination card. What must they do to the card element first?
2. WanderLust wants their navigation menu to remain visible at the top of the screen while users scroll through destination listings. Which position value should they use?
3. What happens when you apply position: relative with top: -20px to a WanderLust booking button?
Overflow and Z-Index
Control what happens when content doesn't fit and manage layering between overlapping elements.