Layout Positioning Code Challenges
Test your mastery of position, overflow, and layout techniques with these real-world challenges. Each solves a pattern you'll encounter regularly in WordPress builds.
Challenge 1 — Sticky Nav + FAB + Badge
Build this single-page UI with correct positioning for each element:
<body>
<nav class="sticky-nav">Brand · Home · About · Contact</nav>
<main class="page-content">
<div class="card">
<span class="card__badge">Featured</span>
<h2>Article Title</h2>
<p>Long article content that fills the page...</p>
</div>
</main>
<button class="fab">↑</button>
</body>
Requirements:
.sticky-nav: Sticks to the top of the viewport on scroll..card: Acts as the positioning anchor for the badge..card__badge: In the top-right corner of the card..fab: Fixed to the bottom-right corner of the viewport.
💡 Solution
/* Sticky navigation */
.sticky-nav {
position: sticky;
top: 0;
z-index: var(--z-sticky, 200);
background: rgba(15, 15, 15, 0.85);
backdrop-filter: blur(12px);
padding: 1rem 2rem;
display: flex;
gap: 2rem;
}
/* Card: positioning anchor */
.card {
position: relative; /* ← THE KEY: creates coordinate space for badge */
padding: 2rem;
background: var(--color-surface, #1c1c1e);
border-radius: 12px;
margin: 2rem auto;
max-width: 720px;
}
/* Badge: absolute to card */
.card__badge {
position: absolute;
top: 16px;
right: 16px;
background: var(--color-primary, #6c63ff);
color: white;
padding: 4px 12px;
border-radius: 9999px;
font-size: 0.75rem;
font-weight: 600;
}
/* FAB: fixed to viewport */
.fab {
position: fixed;
bottom: 2rem;
right: 2rem;
width: 52px;
height: 52px;
border-radius: 50%;
background: var(--color-primary, #6c63ff);
color: white;
font-size: 1.5rem;
border: none;
cursor: pointer;
box-shadow: 0 4px 20px rgba(108, 99, 255, 0.5);
z-index: var(--z-toast, 500);
transition: transform 0.2s, box-shadow 0.2s;
}
.fab:hover {
transform: translateY(-3px);
box-shadow: 0 8px 28px rgba(108, 99, 255, 0.7);
}
Challenge 2 — Image Overlay on Hover
Build a portfolio card where an overlay appears on hover using position: absolute and opacity transition.
<div class="portfolio-card">
<img src="project.jpg" alt="Project">
<div class="portfolio-card__overlay">
<span class="portfolio-card__label">View Project</span>
</div>
</div>
💡 Solution
.portfolio-card {
position: relative; /* Anchor for overlay */
overflow: hidden; /* Clip overlay to card bounds */
border-radius: 12px;
}
.portfolio-card img {
width: 100%;
display: block;
transition: transform 0.5s ease;
}
.portfolio-card__overlay {
position: absolute;
inset: 0; /* top:0; right:0; bottom:0; left:0 */
background: rgba(108, 99, 255, 0.85);
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity 0.35s ease;
}
.portfolio-card__label {
color: white;
font-weight: 700;
font-size: 1.1rem;
letter-spacing: 0.05em;
transform: translateY(8px);
transition: transform 0.35s ease;
}
/* Hover state */
.portfolio-card:hover .portfolio-card__overlay { opacity: 1; }
.portfolio-card:hover img { transform: scale(1.05); }
.portfolio-card:hover .portfolio-card__label { transform: translateY(0); }
Challenge 3 — Sticky Sidebar in a Blog Layout
Build a two-column blog layout where the sidebar sticks while the content scrolls.
<div class="blog-layout">
<main class="blog-content"><!-- long content --></main>
<aside class="blog-sidebar"><!-- sticky sidebar --></aside>
</div>
💡 Solution
.blog-layout {
display: flex;
gap: 2rem;
align-items: flex-start; /* ← REQUIRED: flex-start prevents sidebar stretching */
max-width: 1200px;
margin: 0 auto;
padding: 2rem;
}
.blog-content {
flex: 1;
min-width: 0; /* Prevents content overflow */
}
.blog-sidebar {
flex: 0 0 300px;
position: sticky;
top: 80px; /* Offset for any fixed nav */
max-height: calc(100vh - 100px); /* Don't overflow viewport */
overflow-y: auto; /* Scroll if content is taller */
}
[!NOTE]
align-items: flex-startis the critical property — without it,flexstretches items to equal height, which prevents sticky from working.
Challenge 4 — Tooltip with Pure CSS
Create a tooltip that appears above an element on hover using only CSS positioning.
<button class="has-tooltip" data-tip="This is helpful info">
Hover me
</button>
💡 Solution
.has-tooltip {
position: relative;
}
.has-tooltip::before {
content: attr(data-tip); /* Reads the tooltip text from HTML attribute */
position: absolute;
bottom: calc(100% + 8px); /* Position above the button with 8px gap */
left: 50%;
transform: translateX(-50%); /* Center horizontally */
background: #333;
color: white;
padding: 6px 12px;
border-radius: 6px;
font-size: 0.8rem;
white-space: nowrap;
pointer-events: none;
opacity: 0;
transition: opacity 0.2s ease;
z-index: 100;
}
/* Arrow below the tooltip */
.has-tooltip::after {
content: '';
position: absolute;
bottom: calc(100% + 2px);
left: 50%;
transform: translateX(-50%);
border: 6px solid transparent;
border-top-color: #333;
opacity: 0;
transition: opacity 0.2s ease;
pointer-events: none;
}
.has-tooltip:hover::before,
.has-tooltip:hover::after { opacity: 1; }
Challenge 5 — Full-Screen Loading Overlay
Create a loading overlay that covers the entire page with a centered spinner.
💡 Solution
.loading-overlay {
position: fixed;
inset: 0; /* Covers full viewport */
background: rgba(0, 0, 0, 0.8);
display: flex;
align-items: center;
justify-content: center;
z-index: var(--z-modal, 400);
opacity: 1;
transition: opacity 0.3s;
}
.loading-overlay.is-hidden { opacity: 0; pointer-events: none; }
.spinner {
width: 48px; height: 48px;
border: 4px solid rgba(255, 255, 255, 0.15);
border-top-color: var(--color-primary, #6c63ff);
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }