@use 'sprucecss/scss/spruce' as *;
$reviews-star: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="m12 2 3.1 6.3 6.9 1-5 4.9 1.2 6.8L12 17.8 5.8 21l1.2-6.8-5-4.9 6.9-1z"/></svg>';
.reviews-block {
padding-block: spacer-clamp('xl', 'xxl');
&__inner {
display: grid;
gap: spacer-clamp('l', 'xl');
@include breakpoint('lg') {
grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
}
}
&__summary {
align-self: start;
@include layout-stack('m');
@include breakpoint('lg') {
inset-block-start: spacer('l');
position: sticky;
}
}
&__average {
align-items: center;
display: flex;
flex-wrap: wrap;
gap: spacer('xs') spacer('s');
strong {
color: color('heading');
font-family: config('font-family-heading', $typography);
font-size: font-size('h1');
line-height: 1;
}
span:last-child {
color: color('muted');
font-size: config('font-size-sm', $typography);
inline-size: 100%;
}
}
&__stars {
--direction: to right;
--rating: 0;
--size: 1.1rem;
background-image: linear-gradient(var(--direction), #{color('warning', 'alert')} calc(var(--rating) / 5 * 100%), #{color('border-strong')} 0);
block-size: var(--size);
display: inline-block;
flex-shrink: 0;
inline-size: calc(var(--size) * 5);
mask: url('#{svg-escape($reviews-star)}') 0 0 / var(--size) var(--size) repeat-x;
vertical-align: middle;
}
&__distribution {
font-size: config('font-size-sm', $typography);
list-style: none;
padding: 0;
@include layout-stack('xxs');
li {
align-items: center;
display: grid;
gap: spacer('xs');
grid-template-columns: 4rem 1fr 2.5rem;
}
meter {
block-size: 0.5rem;
}
span:last-child {
color: color('muted');
text-align: end;
}
}
&__grid {
@include clear-list;
@include layout-grid('m', 16rem);
> li {
margin-block: 0;
padding-block: 0;
}
}
&__card {
article {
background-color: color('surface');
block-size: 100%;
border: config('border-width-base', $display) solid color('border');
border-radius: radius('lg');
display: flex;
flex-direction: column;
gap: spacer('xs');
padding: spacer('m');
}
}
&__rating {
margin: 0;
}
&__title {
font-size: font-size('h5');
margin-block: 0;
}
&__text {
color: color('text');
flex-grow: 1;
margin-block: 0;
}
&__footer {
align-items: center;
border-block-start: config('border-width-base', $display) solid color('border');
display: flex;
flex-wrap: wrap;
font-size: config('font-size-sm', $typography);
gap: spacer('xs');
justify-content: space-between;
padding-block-start: spacer('s');
}
}
[dir='rtl'] .reviews-block__stars {
--direction: to left;
}
<section class="reviews-block" aria-labelledby="reviews-title">
<div class="container">
<div class="reviews-block__inner">
<div class="reviews-block__summary">
<header class="block-heading block-heading--start">
<p class="block-heading__eyebrow">Reviews</p>
<h2 class="block-heading__title" id="reviews-title">What our customers say</h2>
</header>
<p class="reviews-block__average">
<strong>4.8</strong>
<span class="reviews-block__stars" style="--rating: 4.8;" aria-hidden="true"></span>
<span>4.8 out of 5, based on 1,284 reviews</span>
</p>
<ul class="reviews-block__distribution" role="list" aria-label="Rating distribution">
<li>
<span>5 stars</span>
<meter min="0" max="100" value="82" aria-label="5 stars: 82%">82%</meter>
<span>82%</span>
</li>
<li>
<span>4 stars</span>
<meter min="0" max="100" value="12" aria-label="4 stars: 12%">12%</meter>
<span>12%</span>
</li>
<li>
<span>3 stars</span>
<meter min="0" max="100" value="4" aria-label="3 stars: 4%">4%</meter>
<span>4%</span>
</li>
<li>
<span>2 stars</span>
<meter min="0" max="100" value="1" aria-label="2 stars: 1%">1%</meter>
<span>1%</span>
</li>
<li>
<span>1 stars</span>
<meter min="0" max="100" value="1" aria-label="1 stars: 1%">1%</meter>
<span>1%</span>
</li>
</ul>
</div>
<ul class="reviews-block__grid" role="list">
<li class="reviews-block__card">
<article>
<p class="reviews-block__rating"><span class="reviews-block__stars" style="--rating: 5;" aria-hidden="true"></span><span class="sr-only">Rated 5 out of 5</span></p>
<h3 class="reviews-block__title">Finally, CSS that scales</h3>
<p class="reviews-block__text">We moved three products to Spruce. The tokens keep everything consistent.</p>
<footer class="reviews-block__footer">
<span><strong>Leo Novak</strong> · Frontend Lead</span>
<span class="badge badge--success">Verified on G2</span>
</footer>
</article>
</li>
<li class="reviews-block__card">
<article>
<p class="reviews-block__rating"><span class="reviews-block__stars" style="--rating: 5;" aria-hidden="true"></span><span class="sr-only">Rated 5 out of 5</span></p>
<h3 class="reviews-block__title">Beautiful defaults</h3>
<p class="reviews-block__text">The design styles saved us weeks of theming work for our white-label clients.</p>
<footer class="reviews-block__footer">
<span><strong>Sara Kim</strong> · Agency Owner</span>
<span class="badge badge--success">Verified on Capterra</span>
</footer>
</article>
</li>
<li class="reviews-block__card">
<article>
<p class="reviews-block__rating"><span class="reviews-block__stars" style="--rating: 4;" aria-hidden="true"></span><span class="sr-only">Rated 4 out of 5</span></p>
<h3 class="reviews-block__title">Great docs</h3>
<p class="reviews-block__text">The documentation answers every question. The AI skills are a nice touch.</p>
<footer class="reviews-block__footer">
<span><strong>Omar Haddad</strong> · Developer</span>
<span class="badge badge--success">Verified on Product Hunt</span>
</footer>
</article>
</li>
<li class="reviews-block__card">
<article>
<p class="reviews-block__rating"><span class="reviews-block__stars" style="--rating: 5;" aria-hidden="true"></span><span class="sr-only">Rated 5 out of 5</span></p>
<h3 class="reviews-block__title">Accessible out of the box</h3>
<p class="reviews-block__text">Focus states, RTL and reduced motion are handled. Our audit was a breeze.</p>
<footer class="reviews-block__footer">
<span><strong>Ava Martinez</strong> · Accessibility Specialist</span>
<span class="badge badge--success">Verified on G2</span>
</footer>
</article>
</li>
<li class="reviews-block__card">
<article>
<p class="reviews-block__rating"><span class="reviews-block__stars" style="--rating: 5;" aria-hidden="true"></span><span class="sr-only">Rated 5 out of 5</span></p>
<h3 class="reviews-block__title">Small and fast</h3>
<p class="reviews-block__text">Our CSS bundle got smaller after the migration, not bigger.</p>
<footer class="reviews-block__footer">
<span><strong>Daniel Okafor</strong> · Engineer</span>
<span class="badge badge--success">Verified on Capterra</span>
</footer>
</article>
</li>
<li class="reviews-block__card">
<article>
<p class="reviews-block__rating"><span class="reviews-block__stars" style="--rating: 4;" aria-hidden="true"></span><span class="sr-only">Rated 4 out of 5</span></p>
<h3 class="reviews-block__title">Lovely components</h3>
<p class="reviews-block__text">The blocks are a great starting point for landing pages.</p>
<footer class="reviews-block__footer">
<span><strong>Maya Chen</strong> · Designer</span>
<span class="badge badge--success">Verified on Product Hunt</span>
</footer>
</article>
</li>
</ul>
</div>
</div>
</section>