STO Hero Entrance Animations
Lessons 01–04 built the vocabulary. This lesson uses it. You have three @keyframes rules in style.css — fadeIn, slideUpFade, and pulse. None of them are applied to any STO element yet. By the end of this lesson, the STO hero section loads with a staggered entrance: the heading slides up and fades in, the subheading follows 150ms later, and the CTA button fades in last. The effect takes less than a second and makes the page feel intentional rather than static.
Planning the sequence
Section titled “Planning the sequence”Before writing any CSS, decide what moves, how, and when.
What moves:
- The
h1— the main hero heading - The
p— the subheading below it - The
.btn— the call-to-action button
What motion:
- Heading and subheading:
slideUpFade— they rise 24px into position while fading in. This combines vertical motion with opacity, which reads as more purposeful than a plain fade. - CTA button:
fadeIn— the button appears after the text is readable. A slide on the button as well would be too much motion in one area.
What timing:
- Heading: starts immediately (
0msdelay), completes in 600ms - Subheading: 150ms delay — it begins while the heading is still animating, creating overlap that reads as a single fluid sequence
- CTA button: 300ms delay — it starts appearing just after the subheading begins, giving the text time to be readable first
The total visible animation span is about 950ms (300ms delay + 600ms duration ≈ 900ms for the last element). That is well within the 1-second threshold for entrance animations — fast enough to feel sharp, slow enough to read.
Step 1 — Add classes to the HTML
Section titled “Step 1 — Add classes to the HTML”The hero elements in index.html currently rely on descendant selectors like .hero-content h1. For animations, add dedicated classes directly to each element so the animation rules are explicit and not tied to the document structure:
<section class="hero-section"> <div class="hero-content"> <h1 class="hero-heading">Summit Trail Outfitters</h1> <p class="hero-subheading">Guided hiking adventures in the Pacific Northwest.</p> <a href="tours.html" class="btn btn-primary hero-cta">Browse Tours</a> </div></section>The three new classes are hero-heading, hero-subheading, and hero-cta. They are additive — hero-heading sits alongside whatever other classes or styling the h1 already has.
Step 2 — Apply the animations in CSS
Section titled “Step 2 — Apply the animations in CSS”In style.css, below your /* === Animations === */ section (after the @keyframes blocks), add:
/* STO Hero Entrance */.hero-heading { animation: slideUpFade 600ms ease-out both;}
.hero-subheading { animation: slideUpFade 600ms ease-out 150ms both;}
.hero-cta { animation: fadeIn 500ms ease-out 300ms both;}The shorthand order is name duration timing-function delay fill-mode. The delay is the fourth value — the second time value. Where there is no delay (.hero-heading), only one time value appears, and the browser assigns it to duration.
Why animation-fill-mode: both matters here
Section titled “Why animation-fill-mode: both matters here”Without fill-mode: both, each element would be fully visible in its normal styled state from the moment the page loads. When the animation starts — even with zero delay — the element would jump to the 0% keyframe (opacity: 0, translateY: 24px) and then animate forward. That jump is visible as a flash of the element before it disappears and re-animates.
fill-mode: backwards prevents that flash by applying the 0% keyframe values during the delay period — the element starts invisible. fill-mode: forwards keeps the 100% keyframe values after the animation ends — the element stays visible. both applies both behaviors.
Because the hero loads on page load with no user interaction, this is exactly the scenario fill-mode: both is designed for. The elements are invisible from the first painted frame until each one’s animation begins.
Step 3 — Check it in the browser
Section titled “Step 3 — Check it in the browser”Open index.html and watch the hero section load. You should see:
- The page loads with a fully opaque hero background image — the dark green overlay and background color are set in CSS properties unrelated to the animation, so they appear immediately.
- The heading fades in and rises into position over 600ms, starting immediately.
- The subheading begins its entrance 150ms into the page load — overlapping with the heading’s animation.
- The CTA button fades in at 300ms, completing at around 800ms.
If any element appears before its animation and then jumps — you are missing fill-mode: both on that element’s rule.
If the whole sequence feels sluggish, reduce the duration values. If it feels too fast to read, increase the delays slightly. Animation timing is calibrated by watching it, not by calculating it.
Adjusting the stagger
Section titled “Adjusting the stagger”The 0 / 150ms / 300ms delays are a starting point. If the hero has more elements — a badge, a secondary link, a rating — extend the pattern by 100–150ms per additional item. If you want a more dramatic pause before each element, increase to 0 / 200ms / 400ms. If you want a tighter cascade, compress to 0 / 100ms / 200ms.
The pattern to hold onto: each successive element should start before the previous one finishes. Overlapping animations read as a sequence. Waiting for each animation to complete before the next starts reads as a list.
Exercise
Section titled “Exercise”Apply the hero entrance animation to your STO index.html and style.css:
-
Add
class="hero-heading"to theh1,class="hero-subheading"to the subheadingp, andclass="hero-cta"to the CTA button or link inside.hero-content. -
In
style.css, below the existing@keyframesblocks, add the three animation rules from Step 2 above. -
Open
index.htmlin the browser. Watch the sequence at normal speed. -
Open DevTools. In the Elements panel, select
.hero-headingand look at the Computed tab — you should see theanimationproperty applied. In the Animations panel (Chrome: More tools → Animations, or the drawer at the bottom), you can scrub the timeline and slow it down to 25% speed to inspect the stagger. -
Try removing
bothfrom one rule and reloading. Observe the flash. Then put it back. -
Adjust the delays to your preference — the 150ms stagger is a guideline, not a rule.
- Plan sequence animation in three steps: what moves, what motion, what timing. Writing CSS before answering those questions produces animation that happens rather than animation that communicates.
- Add dedicated classes (
hero-heading,hero-subheading,hero-cta) to animated elements rather than relying on descendant selectors — the animation rules stay explicit and easy to update. animation-fill-mode: bothis required for page-load entrance animations. Without it, elements flash visible before the0%keyframe takes effect.- Overlapping delays (each element starts before the previous finishes) create a cascade. Back-to-back delays (each waits for the previous to complete) create a list.
- Use DevTools Animations panel at 25% speed to inspect stagger timing — watching at normal speed is too fast to evaluate individual element timing.
Lesson 06 extends this pattern to the featured tours section — a staggered card reveal that triggers as the cards scroll into view, using the same slideUpFade keyframe applied to multiple elements with incremental delays.