This process section HTML CSS GSAP tutorial shows you how to build a dark-themed numbered process list with a serif heading, gold accent color, and a hover state that highlights each row and turns the step title gold. The section uses a GSAP ScrollTrigger animation that cascades each header element and process step into view as you scroll, with the animation tied directly to the scroll position using scrub.
Final output:
Process
Discovery
Understanding your goals, audience, and challenges before a single line of work begins.
02Planning
Defining scope, timelines, and deliverables so everyone knows what success looks like.
03Execution
Building with focus and clear communication, with regular check-ins along the way.
04Review and Refinement
Testing, gathering feedback, and polishing every detail until it meets the standard.
05Launch and Support
Going live with confidence, followed by ongoing support to keep results growing.
1. Link the Work Sans and Playfair Display fonts from Google Fonts in the head.
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400..900;1,400..900&family=Work+Sans:ital,wght@0,100..900;1,100..900&display=swap"
rel="stylesheet">
Let’s start with a section element with the class process-section. Inside it, add a .section-container div with a .process-header and a .process-steps-wrapper div.
<section class="process-section">
<div class="section-container">
<div class="process-header"></div>
<div class="process-steps-wrapper"></div>
</div>
</section>
Reset margins, set Work Sans as the font family, and define the Playfair Display font and a gold color as CSS variables on :root. Give the section a near-black background with a warm cream text color. Use clamp() on the top and bottom padding so it scales with the screen. Center .section-container with the margin inline property set to auto and a max-width.
* {
margin: 0;
box-sizing: border-box;
}
body {
font-family: "Work Sans", sans-serif;
}
:root {
--heading-font: "Playfair Display", serif;
--gold: hsl(39, 45%, 61%);
}
.process-section {
padding-block: clamp(3.5rem, calc(1rem + 7.78vw), 8rem);
background-color: hsl(0, 0%, 3%);
color: hsl(42, 25%, 92%);
}
.process-section .section-container {
max-width: 90rem;
margin-inline: auto;
}
2. Fill in .process-header with the section label and heading.
<div class="process-header">
<span class="section-label">How We Work</span>
<h2>Process</h2>
</div>
Add some bottom padding on .process-header to space it away from the steps below. Style the label with a small uppercase font in the gold color and a wide letter spacing. Style the heading with the Playfair Display font at a large size using clamp(). Set the line height property to 0.9 so the large serif text feels tight and editorial.
.process-section .process-header {
padding: 0 clamp(2.5rem, calc(1rem + 4.44vw), 5rem) clamp(2.5rem, calc(1rem + 4.44vw), 5rem);
}
.process-section .section-label {
font-size: .75rem;
line-height: 1.3;
letter-spacing: .3em;
text-transform: uppercase;
color: var(--gold);
}
.process-section .process-header h2 {
font-family: var(--heading-font);
font-weight: 600;
font-size: clamp(2.25rem, calc(1rem + 3.33vw), 4rem);
line-height: .9;
margin-top: .75rem;
}
Output:
Process
3. Fill in .process-steps-wrapper with five .process-step anchor tags. Each step has a number span, a heading, a description paragraph, and an arrow SVG icon.
<div class="process-steps-wrapper">
<a href="#" class="process-step">
<span>01</span>
<h3>Discovery</h3>
<p>Understanding your goals, audience, and challenges before a single line of work begins.</p>
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3 8H13M9 12L13 8L9 4" stroke="#7A7670" stroke-linecap="round" stroke-linejoin="round" />
</svg>
</a>
<!-- add more steps -->
</div>
Style each .process-step as a flex row with a gap between the number, heading, description, and arrow. Add a bottom border on each step to create clean dividers between them. Add a background color transition on hover so the row highlights subtly. On hover, also change the heading color to gold so the active step feels highlighted. On mobile, switch to flex-wrap: wrap so the row reflows naturally on smaller screens.
.process-section .process-step {
text-decoration: none;
padding: clamp(1.25rem, calc(1rem + 1.67vw), 2.5rem) clamp(2.5rem, calc(1rem + 4.44vw), 5rem);
display: flex;
gap: 2.5rem;
border-bottom: 1px solid hsla(42, 25%, 92%, 0.1);
transition: background-color .3s;
}
.process-section .process-step:hover {
background-color: hsl(180, 2%, 11%);
}
.process-section .process-step:hover h3 {
color: var(--gold);
}
@media screen and (max-width: 768px) {
.process-section .process-step {
flex-wrap: wrap;
align-items: center;
gap: 1rem;
}
}
Output:
Process
Discovery
Understanding your goals, audience, and challenges before a single line of work begins.
02Planning
Defining scope, timelines, and deliverables so everyone knows what success looks like.
03Execution
Building with focus and clear communication, with regular check-ins along the way.
04Review and Refinement
Testing, gathering feedback, and polishing every detail until it meets the standard.
05Launch and Support
Going live with confidence, followed by ongoing support to keep results growing.
4. Style the number span with a small muted font and a fixed flex basis so it doesn’t shrink. Style the heading with the Playfair Display font and a fixed flex basis so each step title takes up the same amount of horizontal space. Add a color transition so the gold hover state from step 3 animates smoothly. On mobile, cap the heading width so it doesn’t stretch too wide when the row wraps.
.process-section .process-step span {
flex-basis: 2rem;
font-size: .75rem;
line-height: 1.3;
letter-spacing: .2rem;
color: hsl(36, 4%, 46%);
margin-top: .25rem;
}
.process-section .process-step h3 {
color: hsl(42, 25%, 92%);
flex-basis: 11rem;
font-family: var(--heading-font);
font-weight: 600;
font-size: 1.5rem;
line-height: 1.3;
transition: color .3s;
}
@media screen and (max-width: 768px) {
.process-section .process-step h3 {
max-width: 80%;
}
}
Style the description with a light font weight and a muted gray color so it reads as secondary to the heading. Set a max-width so it doesn’t stretch across the full row on large screens. Set the margin left property to auto on the SVG so it always pushes to the right edge of the row regardless of the description length.
.process-section .process-step p {
font-weight: 300;
font-size: 1rem;
line-height: 1.625;
color: hsl(36, 4%, 46%);
max-width: 32rem;
}
@media screen and (max-width: 768px) {
.process-section .process-step p {
max-width: 80%;
}
}
.process-section .process-step svg {
width: 2rem;
margin-left: auto;
}
Output:
Process
Discovery
Understanding your goals, audience, and challenges before a single line of work begins.
02Planning
Defining scope, timelines, and deliverables so everyone knows what success looks like.
03Execution
Building with focus and clear communication, with regular check-ins along the way.
04Review and Refinement
Testing, gathering feedback, and polishing every detail until it meets the standard.
05Launch and Support
Going live with confidence, followed by ongoing support to keep results growing.
5. Now add the GSAP scroll animation. Link the GSAP and ScrollTrigger libraries just before the closing body tag, then link your script.js file after them.
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15/dist/ScrollTrigger.min.js"></script>
In script.js, register ScrollTrigger and use gsap.from() to animate all .process-header children and each .process-step. Each element starts 40px below its natural position with an opacity of 0, so they all fade and slide up into place.
The stagger option makes each element start slightly after the previous one, so the header and steps cascade in one after another as the section scrolls into view.
Setting scrub: true ties the animation directly to the scroll position, and once: true means it only plays once instead of resetting every time.
document.addEventListener("DOMContentLoaded", () => {
gsap.registerPlugin(ScrollTrigger);
gsap.from(
".process-header *, .process-step",
{
y: 40,
opacity: 0,
duration: 0.5,
ease: "power4.in",
stagger: 0.15,
scrollTrigger: {
trigger: ".process-section",
start: "top bottom+=15%",
end: "90% bottom",
scrub: true,
once: true,
},
}
);
});
Output:
Process
Discovery
Understanding your goals, audience, and challenges before a single line of work begins.
02Planning
Defining scope, timelines, and deliverables so everyone knows what success looks like.
03Execution
Building with focus and clear communication, with regular check-ins along the way.
04Review and Refinement
Testing, gathering feedback, and polishing every detail until it meets the standard.
05Launch and Support
Going live with confidence, followed by ongoing support to keep results growing.
Final Output Code for Process Section HTML CSS GSAP:
Head
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400..900;1,400..900&family=Work+Sans:ital,wght@0,100..900;1,100..900&display=swap"
rel="stylesheet">
HTML
<section class="process-section">
<div class="section-container">
<div class="process-header">
<span class="section-label">How We Work</span>
<h2>Process</h2>
</div>
<div class="process-steps-wrapper">
<a href="#" class="process-step">
<span>01</span>
<h3>Discovery
</h3>
<p>Understanding your goals, audience, and challenges before a single line of work begins.</p>
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3 8H13M9 12L13 8L9 4" stroke="#7A7670" stroke-linecap="round" stroke-linejoin="round" />
</svg>
</a>
<a href="#" class="process-step">
<span>02</span>
<h3>Planning
</h3>
<p>Defining scope, timelines, and deliverables so everyone knows what success looks like.</p>
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3 8H13M9 12L13 8L9 4" stroke="#7A7670" stroke-linecap="round" stroke-linejoin="round" />
</svg>
</a>
<a href="#" class="process-step">
<span>03</span>
<h3>Execution
</h3>
<p>Building with focus and clear communication, with regular check-ins along the way.</p>
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3 8H13M9 12L13 8L9 4" stroke="#7A7670" stroke-linecap="round" stroke-linejoin="round" />
</svg>
</a>
<a href="#" class="process-step">
<span>04</span>
<h3>Review and Refinement
</h3>
<p>Testing, gathering feedback, and polishing every detail until it meets the standard.</p>
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3 8H13M9 12L13 8L9 4" stroke="#7A7670" stroke-linecap="round" stroke-linejoin="round" />
</svg>
</a>
<a href="#" class="process-step">
<span>05</span>
<h3>Launch and Support
</h3>
<p>Going live with confidence, followed by ongoing support to keep results growing.</p>
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3 8H13M9 12L13 8L9 4" stroke="#7A7670" stroke-linecap="round" stroke-linejoin="round" />
</svg>
</a>
</div>
</div>
</section>
CSS
* {
margin: 0;
box-sizing: border-box;
}
body {
font-family: "Work Sans", sans-serif;
}
:root {
--heading-font: "Playfair Display", serif;
--gold: hsl(39, 45%, 61%);
}
.process-section {
padding-block: clamp(3.5rem, calc(1rem + 7.78vw), 8rem);
background-color: hsl(0, 0%, 3%);
color: hsl(42, 25%, 92%);
}
.process-section .section-container {
max-width: 90rem;
margin-inline: auto;
}
.process-section .process-header {
padding: 0 clamp(2.5rem, calc(1rem + 4.44vw), 5rem) clamp(2.5rem, calc(1rem + 4.44vw), 5rem);
}
.process-section .section-label {
font-size: .75rem;
line-height: 1.3;
letter-spacing: .3em;
text-transform: uppercase;
color: var(--gold);
}
.process-section .process-header h2 {
font-family: var(--heading-font);
font-weight: 600;
font-size: clamp(2.25rem, calc(1rem + 3.33vw), 4rem);
line-height: .9;
margin-top: .75rem;
}
.process-section .process-step {
text-decoration: none;
padding: clamp(1.25rem, calc(1rem + 1.67vw), 2.5rem) clamp(2.5rem, calc(1rem + 4.44vw), 5rem);
display: flex;
gap: 2.5rem;
border-bottom: 1px solid hsla(42, 25%, 92%, 0.1);
transition: background-color .3s;
}
.process-section .process-step:hover {
background-color: hsl(180, 2%, 11%);
}
.process-section .process-step:hover h3 {
color: var(--gold);
}
@media screen and (max-width: 768px) {
.process-section .process-step {
flex-wrap: wrap;
align-items: center;
gap: 1rem;
}
}
.process-section .process-step span {
flex-basis: 2rem;
font-size: .75rem;
line-height: 1.3;
letter-spacing: .2rem;
color: hsl(36, 4%, 46%);
margin-top: .25rem;
}
.process-section .process-step h3 {
color: hsl(42, 25%, 92%);
flex-basis: 11rem;
font-family: var(--heading-font);
font-weight: 600;
font-size: 1.5rem;
line-height: 1.3;
transition: color .3s;
}
@media screen and (max-width: 768px) {
.process-section .process-step h3 {
max-width: 80%;
}
}
.process-section .process-step p {
font-weight: 300;
font-size: 1rem;
line-height: 1.625;
color: hsl(36, 4%, 46%);
max-width: 32rem;
}
@media screen and (max-width: 768px) {
.process-section .process-step p {
max-width: 80%;
}
}
.process-section .process-step svg {
width: 2rem;
margin-left: auto;
}
Footer(before </body>):
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15/dist/ScrollTrigger.min.js"></script>
JS:
document.addEventListener("DOMContentLoaded", () => {
gsap.registerPlugin(ScrollTrigger);
gsap.from(
".process-header *,.process-step",
{
y: 40,
opacity: 0,
duration: 0.5,
ease: "power4.in",
stagger: 0.15,
scrollTrigger: {
trigger: ".process-section",
start: "top bottom+=15%",
end: "90% bottom",
scrub: true,
once: true,
},
}
);
});
If you have any doubts or stuck somewhere, you can reach out through Coding Yaar's Discord server.