CSSThe Cover Layout

The Cover Layout

The Cover layout — another pattern from Every Layout — is the classic full-viewport hero section: a header at the top, a footer at the bottom (or neither), and a centered block of content that takes up whatever space is left, growing or shrinking with the viewport instead of scrolling awkwardly. It is the pattern behind almost every landing-page hero.

The core recipe

Flexbox in column direction, with the centered content pushed to fill remaining space using flex: 1 and its own auto-margins for centering.

CSS
.cover {
  display: flex;
  flex-direction: column;
  min-height: 100dvh; /* fills the real visible viewport height */
  padding: 1.5rem;
}

.cover > * {
  margin-block: 1rem; /* default rhythm between direct children */
}

.cover > .cover-centered {
  margin-block: auto; /* pushes itself to vertical center of remaining space */
  text-align: center;
}

/* Header/footer opt out of centering, stay pinned to their edge */
.cover > header,
.cover > footer {
  margin-block: 0;
}
Why margin-block: auto, not align-items: center
If you center everything with align-items: center directly on .cover, the header and footer also get pulled to the middle. Using auto margins on just the centered child lets it consume the leftover space and center itself, while header and footer stay naturally pinned to the top and bottom.
Full hero section example

HTML
<div class="cover">
  <header class="cover-header">
    <img src="/logo.svg" alt="Company logo" />
  </header>

  <div class="cover-centered">
    <h1>Build faster, ship sooner</h1>
    <p>Everything your team needs, in one place.</p>
    <a class="cta" href="/signup">Get started</a>
  </div>

  <footer class="cover-footer">
    <p>Scroll to learn more &#8595;</p>
  </footer>
</div>

CSS
.cover {
  display: flex;
  flex-direction: column;
  min-height: 100dvh;
  padding: 2rem;
  background: linear-gradient(160deg, #1e293b, #0f172a);
  color: white;
}

.cover-header {
  display: flex;
  justify-content: center;
}

.cover-centered {
  margin-block: auto;
  text-align: center;
  max-width: 40ch;
  margin-inline: auto;
}

.cover-centered h1 {
  font-size: clamp(2rem, 5vw, 3.5rem);
  margin-bottom: 0.5rem;
}

.cta {
  display: inline-block;
  margin-top: 1.5rem;
  padding: 0.75rem 1.5rem;
  border-radius: 8px;
  background: white;
  color: #0f172a;
  font-weight: 600;
  text-decoration: none;
}

.cover-footer {
  text-align: center;
  opacity: 0.7;
  font-size: 0.875rem;
}
Why min-height: 100dvh instead of 100vh
100vh includes hidden mobile chrome
On mobile browsers, 100vh is measured against the largest possible viewport, which includes space behind the collapsing address bar. That can push the footer off-screen on load.100dvh (dynamic viewport height) tracks the actually visible viewport, so the cover always fits the real screen.

CSS
.cover {
  min-height: 100vh;   /* fallback for browsers without dvh support */
  min-height: 100dvh;  /* preferred, overrides the line above where supported */
}
Variation: cover without header/footer

Not every cover needs both edges — a simple "centered content, full height" section is just the same recipe with only one child.

CSS
.cover-simple {
  display: flex;
  flex-direction: column;
  justify-content: center; /* fine here since there's nothing else to push away */
  align-items: center;
  min-height: 100dvh;
  text-align: center;
}
  • Use margin-block: auto on the centered child when a header and/or footer must stay pinned to the edges

  • Use plain justify-content: center on the container when there is nothing else competing for space

  • Always use 100dvh (with a 100vh fallback) for full-viewport height on anything mobile users will see

  • Constrain the centered content with a max-width in ch units so hero copy stays readable on ultra-wide screens

Variation: background image with an overlay

A common hero variant layers a dark scrim over a background photo so white text stays legible. The Cover recipe itself does not change — only the background layers do.

CSS
.cover--photo {
  display: flex;
  flex-direction: column;
  min-height: 100dvh;
  padding: 2rem;
  color: white;
  background-image:
    linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)),
    url('/hero-photo.jpg');
  background-size: cover;
  background-position: center;
}
Why the gradient comes first
Background images stack in the order they are listed, with the first layer on top. Listing the semi-transparent black gradient before the photo URL means it renders as a scrim over the image, which is what darkens the photo enough for white text to stay readable, satisfying color-contrast requirements.
Stacking multiple cover sections

A landing page is often several Cover sections stacked vertically — a hero, then a feature highlight, then a call-to-action footer section — each independently full-height and independently centered.

CSS
.cover {
  display: flex;
  flex-direction: column;
  min-height: 100dvh;
}

/* Each section reuses the same recipe, scroll-snapping between them
   for a slide-deck feel if desired */
.sections {
  scroll-snap-type: y mandatory;
}

.cover {
  scroll-snap-align: start;
}
Accessibility considerations
  • Add a visually-hidden skip link before the first cover section so keyboard users can bypass a tall hero and reach the main content directly

  • Ensure text over a background image/gradient still meets contrast requirements at every viewport size, not just the one used to design it

  • If cover sections scroll-snap, respect prefers-reduced-motion and consider disabling forced snapping for users who opted out of motion

  • Do not rely on scroll position alone to convey content order for screen readers — the underlying DOM order must already make sense read top to bottom

CSS
@media (prefers-reduced-motion: reduce) {
  .sections {
    scroll-snap-type: none; /* let users scroll freely without a
                                snapping motion effect */
  }
}
Sticky nav inside a cover section

When the header inside a cover section must remain visible while the rest of the page scrolls past, position: sticky on the header (rather than the whole section) keeps the Cover recipe's flex structure intact while pinning just that one child.

CSS
.cover-header {
  position: sticky;
  top: 0;
  z-index: 10;
  background: rgba(15, 23, 42, 0.9);
  backdrop-filter: blur(8px);
}
Next
Combine Cover with the tag/button grouping pattern from The Cluster Layout for a complete hero section with a call-to-action group.