This stats section HTML CSS tutorial shows you how to build a responsive statistics grid with oversized numbers, colorful cards, a circular section label, and decorative badges. The three-column layout collapses to a single column on mobile, with responsive typography and an offset box shadow adding visual depth.
Final output:
Impact Report
No vague promises.
Proof that good business can do good.
Here’s what happened when we treated sustainability like a brief, not a buzzword.
Steps for Stats Section HTML CSS:
1. Start with the section structure.
Link the Space Grotesk font 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=Space+Grotesk:wght@300..700&display=swap" rel="stylesheet">
Let’s start with a .stats-section section with a .section-container div. Inside it, add a .stats-header for the heading content and a .stats-blocks-wrapper for the three statistic cards.
<section class="stats-section">
<div class="section-container">
<div class="stats-header">
<p class="section-name"><span>Impact Report</span></p>
<div>
<p class="section-label">No vague promises.</p>
<h2 class="stats-title">Proof that good business can do good.</h2>
</div>
<p class="stats-description">Here's what happened when we treated sustainability like a brief, not a buzzword.</p>
</div>
<div class="stats-blocks-wrapper"></div>
</div>
</section>
Then reset the default margins and set box-sizing: border-box so element dimensions include padding and borders. Give the section a pale cream background, dark green text, and responsive horizontal padding. Center the inner container with a maximum width.
* {
margin: 0;
box-sizing: border-box;
}
body {
font-family: "Space Grotesk", sans-serif;
}
.stats-section {
background-color: hsla(46, 59%, 91%, 1);
color: hsla(142, 25%, 17%, 1);
padding: 4rem clamp(2rem, calc(1rem + 3.33vw), 4rem);
}
.stats-section .section-container {
max-width: 82rem;
margin-inline: auto;
}
2. Style the stats header.
Use CSS Grid with three columns to position the circular label, heading, and description side by side. Align the content to the bottom and add spacing between the columns. At widths below 768px, switch to a single column.
Style .section-name as a circular outlined label. Use clamp() for its dimensions so the circle scales with the viewport, and rotate it slightly for a more organic look.
.stats-section .stats-header {
display: grid;
grid-template-columns: auto 2.5fr 1fr;
align-items: end;
gap: 2rem 3.5rem;
margin-bottom: 4rem;
}
.stats-section .section-name {
width: clamp(5rem, calc(1rem + 6.94vw), 7.25rem);
height: clamp(5rem, calc(1rem + 6.94vw), 7.25rem);
display: flex;
align-items: center;
justify-content: center;
text-align: center;
border-radius: 50%;
border: 2px solid hsla(142, 25%, 17%, 1);
transform: rotate(-8deg);
}
.stats-section .section-name span {
font-size: 0.625rem;
line-height: 1.4;
text-transform: uppercase;
max-width: 2.5rem;
}
@media screen and (max-width: 768px) {
.stats-section .stats-header {
grid-template-columns: 1fr;
}
}
Style the small section label with uppercase text and letter spacing. Use a bold, oversized heading with responsive typography, tight line height, and negative letter spacing. Keep the description relatively narrow for readability.
.stats-section .section-label {
font-size: 0.75rem;
line-height: 1.4;
letter-spacing: 0.92px;
text-transform: uppercase;
margin-bottom: 0.75rem;
}
.stats-section .stats-title {
font-weight: 700;
font-size: clamp(3rem, calc(1rem + 5.14vw), 5.625rem);
line-height: 0.85;
letter-spacing: -0.0744em;
}
.stats-section .stats-description {
font-size: 0.95rem;
line-height: 1.5;
max-width: 15.25rem;
}
Output:
Impact Report
No vague promises.
Proof that good business can do good.
Here’s what happened when we treated sustainability like a brief, not a buzzword.
3. Add the statistic cards
Fill .stats-blocks-wrapper with three .stats-block divs. Each card contains a label, a large statistic, a heading, and a short description. The first card also has an arrow link, the second has a circular material-saving badge, and the third uses a decorative symbol.
<div class="stats-blocks-wrapper">
<div class="stats-block">
<p class="stats-block-label">A — 01</p>
<p class="stats-block-number">18t</p>
<h3 class="stats-block-heading">Waste diverted</h3>
<p class="stats-block-description">That's roughly the weight of three very
opinionated elephants.</p>
<a href="#">
<svg width="54" height="54" viewBox="0 0 54 54" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="54" height="54" rx="27" fill="#213729" />
<path d="M21.793 32.2077L32.2096 21.791M32.2096 31.166V21.791H22.8346" stroke-width="1.875"
stroke="#F6F0DC" />
</svg>
</a>
</div>
<div class="stats-block">
<p class="stats-block-label">B — 02</p>
<p class="stats-block-number">64%</p>
<h3 class="stats-block-heading">Less packaging</h3>
<p class="stats-block-description">Less stuff around the stuff. More room
for what matters.</p>
<p><span>↓ 8.4t
material</span></p>
</div>
<div class="stats-block">
<p class="stats-block-label">C — 03</p>
<p class="stats-block-number">12K</p>
<h3 class="stats-block-heading">Hours volunteered</h3>
<p class="stats-block-description">Skills, sleeves, and occasionally garden
gloves rolled up.</p>
<p>✣</p>
</div>
</div>
Add a three-column grid to .stats-blocks-wrapper and use a small gap with a dark green background to create the dividers between cards. Add a matching border and an offset box shadow for a bold, layered effect. On screens below 768px, switch to a single column.
.stats-section .stats-blocks-wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 2px;
background-color: hsla(142, 25%, 17%, 1);
border: 2px solid hsla(142, 25%, 17%, 1);
box-shadow: 8px 8px 0 0 hsla(142, 25%, 17%, 1);
}
@media screen and (max-width: 768px) {
.stats-section .stats-blocks-wrapper {
grid-template-columns: 1fr;
}
}
.stats-section .stats-block {
padding: 1.75rem 1.5rem;
}
Use :nth-child() to give each card a different background color. The first card uses lime green, the second yellow, and the third coral.
.stats-section .stats-block:nth-child(1) {
background-color: hsla(79, 100%, 67%, 1);
}
.stats-section .stats-block:nth-child(2) {
background-color: hsla(47, 100%, 65%, 1);
}
.stats-section .stats-block:nth-child(3) {
background-color: hsla(10, 100%, 70%, 1);
}
Output:
Impact Report
No vague promises.
Proof that good business can do good.
Here’s what happened when we treated sustainability like a brief, not a buzzword.
4. Style the statistics and card content
Style .stats-block-label with a small font size. Make .stats-block-number the focal point using a bold weight, a responsive clamp() font size, tight line height, and negative letter spacing. Add spacing above the heading and description.
.stats-section .stats-block-label {
font-size: 0.675rem;
line-height: 1.5;
}
.stats-section .stats-block-number {
margin-top: 4rem;
font-weight: 700;
font-size: clamp(5rem, calc(1rem + 8.89vw), 9rem);
line-height: 0.85;
letter-spacing: -0.09em;
}
.stats-section .stats-block-heading {
margin-top: 1.5rem;
font-weight: 700;
font-size: 1.25rem;
line-height: 1.5;
}
.stats-section .stats-block-description {
margin-top: 0.75rem;
font-size: 0.875rem;
line-height: 1.5;
max-width: 17rem;
}
.stats-section .stats-block a {
margin-top: 0.5rem;
display: block;
text-align: right;
}
Output:
Impact Report
No vague promises.
Proof that good business can do good.
Here’s what happened when we treated sustainability like a brief, not a buzzword.
5. Style decorative details
For the second card, style the final paragraph as a circular badge with a border and a slight rotation. Position it in the bottom-right corner on desktop, but let it flow naturally on smaller screens. The third card uses a large rotated decorative symbol aligned to the right.
.stats-section .stats-block:nth-child(2) {
position: relative;
}
.stats-section .stats-block:nth-child(2) p:last-child {
width: 5.25rem;
height: 5.25rem;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
border-radius: 50%;
border: 2px solid hsla(142, 25%, 17%, 1);
transform: rotate(8deg);
margin-left: auto;
}
@media screen and (min-width: 769px) {
.stats-section .stats-block:nth-child(2) p:last-child {
position: absolute;
right: 1.5rem;
bottom: 1.75rem;
}
}
.stats-section .stats-block:nth-child(2) p:last-child span {
font-size: 0.625rem;
line-height: 1.4;
max-width: 2.5rem;
}
.stats-section .stats-block:nth-child(3) p:last-child {
font-size: 6rem;
line-height: 1;
text-align: right;
transform: rotate(12deg);
margin-top: -2rem;
padding-bottom: 1rem;
}
Output:
Impact Report
No vague promises.
Proof that good business can do good.
Here’s what happened when we treated sustainability like a brief, not a buzzword.
Final Output Code for Stats Section HTML CSS:
HTML
<section class="stats-section">
<div class="section-container">
<div class="stats-header">
<p class="section-name"><span>Impact Report</span></p>
<div>
<p class="section-label">No vague promises.</p>
<h2 class="stats-title">Proof that good
business can do
good.</h2>
</div>
<p class="stats-description">Here's what happened when we
treated sustainability like a brief,
not a buzzword.</p>
</div>
<div class="stats-blocks-wrapper">
<div class="stats-block">
<p class="stats-block-label">A — 01</p>
<p class="stats-block-number">18t</p>
<h3 class="stats-block-heading">Waste diverted</h3>
<p class="stats-block-description">That's roughly the weight of three very
opinionated elephants.</p>
<a href="#">
<svg width="54" height="54" viewBox="0 0 54 54" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="54" height="54" rx="27" fill="#213729" />
<path d="M21.793 32.2077L32.2096 21.791M32.2096 31.166V21.791H22.8346" stroke-width="1.875"
stroke="#F6F0DC" />
</svg>
</a>
</div>
<div class="stats-block">
<p class="stats-block-label">B — 02</p>
<p class="stats-block-number">64%</p>
<h3 class="stats-block-heading">Less packaging</h3>
<p class="stats-block-description">Less stuff around the stuff. More room
for what matters.</p>
<p><span>↓ 8.4t
material</span></p>
</div>
<div class="stats-block">
<p class="stats-block-label">C — 03</p>
<p class="stats-block-number">12K</p>
<h3 class="stats-block-heading">Hours volunteered</h3>
<p class="stats-block-description">Skills, sleeves, and occasionally garden
gloves rolled up.</p>
<p>✣</p>
</div>
</div>
</div>
</section>
CSS
* {
margin: 0;
box-sizing: border-box;
}
body {
font-family: "Space Grotesk", sans-serif;
}
.stats-section {
background-color: hsla(46, 59%, 91%, 1);
color: hsla(142, 25%, 17%, 1);
padding: 4rem clamp(2rem, calc(1rem + 3.33vw), 4rem);
}
.stats-section .section-container {
max-width: 82rem;
margin-inline: auto;
}
.stats-section .stats-header {
display: grid;
grid-template-columns: auto 2.5fr 1fr;
align-items: end;
gap: 2rem 3.5rem;
margin-bottom: 4rem;
}
.stats-section .section-name {
width: clamp(5rem, calc(1rem + 6.94vw), 7.25rem);
height: clamp(5rem, calc(1rem + 6.94vw), 7.25rem);
display: flex;
align-items: center;
justify-content: center;
text-align: center;
border-radius: 50%;
border: 2px solid hsla(142, 25%, 17%, 1);
transform: rotate(-8deg);
}
.stats-section .section-name span {
font-size: 0.625rem;
line-height: 1.4;
text-transform: uppercase;
max-width: 2.5rem;
}
.stats-section .section-label {
font-size: 0.75rem;
line-height: 1.4;
letter-spacing: 0.92px;
text-transform: uppercase;
margin-bottom: 0.75rem;
}
.stats-section .stats-title {
font-weight: 700;
font-size: clamp(3rem, calc(1rem + 5.14vw), 5.625rem);
line-height: 0.85;
letter-spacing: -0.0744em;
}
.stats-section .stats-description {
font-size: 0.95rem;
line-height: 1.5;
max-width: 15.25rem;
}
.stats-section .stats-blocks-wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 2px;
background-color: hsla(142, 25%, 17%, 1);
border: 2px solid hsla(142, 25%, 17%, 1);
box-shadow: 8px 8px 0 0 hsla(142, 25%, 17%, 1);
}
.stats-section .stats-block {
padding: 1.75rem 1.5rem;
}
.stats-section .stats-block-label {
font-size: 0.675rem;
line-height: 1.5;
}
.stats-section .stats-block-number {
margin-top: 4rem;
font-weight: 700;
font-size: clamp(5rem, calc(1rem + 8.89vw), 9rem);
line-height: 0.85;
letter-spacing: -0.09em;
}
.stats-section .stats-block-heading {
margin-top: 1.5rem;
font-weight: 700;
font-size: 1.25rem;
line-height: 1.5;
}
.stats-section .stats-block-description {
margin-top: 0.75rem;
font-size: 0.875rem;
line-height: 1.5;
max-width: 17rem;
}
.stats-section .stats-block a {
margin-top: 0.5rem;
display: block;
text-align: right;
}
.stats-section .stats-block:nth-child(1) {
background-color: hsla(79, 100%, 67%, 1);
}
.stats-section .stats-block:nth-child(2) {
background-color: hsla(47, 100%, 65%, 1);
position: relative;
}
.stats-section .stats-block:nth-child(2) p:last-child {
width: 5.25rem;
height: 5.25rem;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
border-radius: 50%;
border: 2px solid hsla(142, 25%, 17%, 1);
transform: rotate(8deg);
margin-left: auto;
}
.stats-section .stats-block:nth-child(2) p:last-child span {
font-size: 0.625rem;
line-height: 1.4;
max-width: 2.5rem;
}
.stats-section .stats-block:nth-child(3) {
background-color: hsla(10, 100%, 70%, 1);
}
.stats-section .stats-block:nth-child(3) p:last-child {
font-size: 6rem;
line-height: 1;
text-align: right;
transform: rotate(12deg);
margin-top: -2rem;
padding-bottom: 1rem;
}
@media screen and (max-width: 768px) {
.stats-section .stats-header {
grid-template-columns: 1fr;
}
.stats-section .stats-blocks-wrapper {
grid-template-columns: 1fr;
}
}
@media screen and (min-width: 769px) {
.stats-section .stats-block:nth-child(2) p:last-child {
position: absolute;
right: 1.5rem;
bottom: 1.75rem;
}
}
If you have any doubts or stuck somewhere, you can reach out through Coding Yaar's Discord server.