Skip to content
NuvoUI

Pricing table

A pricing table with three plans, one highlighted, each with a price, a feature list and a call to action. The plans stack below 768px.

Preview

Starter

$0 per month

For one person trying the product on a side project.

  • 1 project
  • 5 GB storage
  • Community support
Start for free

Team

Most popular

$12 per user per month

For teams that share projects and review work together.

  • Unlimited projects
  • 100 GB storage
  • Shared workspaces and roles
  • Email support
Start a 14-day trial

Business

$29 per user per month

For organizations with security and billing requirements.

  • Everything in Team
  • 1 TB storage
  • Single sign-on and audit log
  • Priority support
Contact sales

With utility classes

The markup of the preview. Classes come from the prebuilt dist/nuvoui.min.css, or from your own build with $generate-utility-classes: true.

HTML
<div class="grid cols-1 cols-3@md gap-6">
    <article class="flex col gap-4 bg-surface text-regular border rounded-lg p-6">
        <h3 class="text-lg font-semibold m-0">Starter</h3>
        <p class="m-0"><span class="text-4xl font-bold">$0</span> <span class="text-sm text-muted">per month</span></p>
        <p class="text-sm text-muted m-0">For one person trying the product on a side project.</p>
        <ul class="grow flex col gap-2 m-0 p-0 text-sm" role="list">
            <li>1 project</li>
            <li>5 GB storage</li>
            <li>Community support</li>
        </ul>
        <a class="block text-center border rounded-md px-4 py-2 font-medium text-regular hover:bg-hover" href="/signup/?plan=starter">Start for free</a>
    </article>
    <article class="flex col gap-4 bg-surface text-regular border-2 border-brand rounded-lg p-6">
        <div class="flex between x-center gap-2">
            <h3 class="text-lg font-semibold m-0">Team</h3>
            <span class="bg-brand-subtle text-brand text-xs font-medium rounded-full px-2 py-1">Most popular</span>
        </div>
        <p class="m-0"><span class="text-4xl font-bold">$12</span> <span class="text-sm text-muted">per user per month</span></p>
        <p class="text-sm text-muted m-0">For teams that share projects and review work together.</p>
        <ul class="grow flex col gap-2 m-0 p-0 text-sm" role="list">
            <li>Unlimited projects</li>
            <li>100 GB storage</li>
            <li>Shared workspaces and roles</li>
            <li>Email support</li>
        </ul>
        <a class="block text-center bg-brand text-on-brand rounded-md px-4 py-2 font-medium" href="/signup/?plan=team">Start a 14-day trial</a>
    </article>
    <article class="flex col gap-4 bg-surface text-regular border rounded-lg p-6">
        <h3 class="text-lg font-semibold m-0">Business</h3>
        <p class="m-0"><span class="text-4xl font-bold">$29</span> <span class="text-sm text-muted">per user per month</span></p>
        <p class="text-sm text-muted m-0">For organizations with security and billing requirements.</p>
        <ul class="grow flex col gap-2 m-0 p-0 text-sm" role="list">
            <li>Everything in Team</li>
            <li>1 TB storage</li>
            <li>Single sign-on and audit log</li>
            <li>Priority support</li>
        </ul>
        <a class="block text-center border rounded-md px-4 py-2 font-medium text-regular hover:bg-hover" href="/contact/">Contact sales</a>
    </article>
</div>

With apply()

The same result with BEM class names and no utility classes. @use "@nuvoui/core" as *; emits the tokens and base styles, and each apply() writes one rule.

SCSS
@use "@nuvoui/core" as *;

.pricing {
    @include apply(
        grid, // display: grid
        cols(1), // one grid column
        cols(3) md, // three columns from md (768px) up
        gap(6) // gap: spacing key 6 (1.5rem)
    );
}

.plan {
    @include apply(
        flex, // display: flex
        col, // flex direction: column
        gap(4), // gap: spacing key 4 (1rem)
        p(6), // padding: spacing key 6 (1.5rem)
        bg(surface), // surface background, follows the theme
        text-color(regular), // regular text color, follows the theme
        border(1), // 1px border (width key 1), regular color
        rounded(lg) // corner radius: size key lg (0.75rem)
    );
}

.plan--featured {
    @include apply(border(2, solid, brand)); // 2px solid border (width key 2), brand color
}

.plan__header {
    @include apply(
        flex, // display: flex
        between, // main axis: space between (justify-content)
        x-center, // cross axis: center (align-items)
        gap(2) // gap: spacing key 2 (0.5rem)
    );
}

.plan__name {
    @include apply(
        m(0), // margin: 0
        font-size(lg), // font size key lg (1.25rem)
        font(semibold) // font weight: semibold (600)
    );
}

.plan__badge {
    @include apply(
        px(2), // horizontal padding: spacing key 2 (0.5rem)
        py(1), // vertical padding: spacing key 1 (0.25rem)
        rounded(full), // fully rounded ends (pill shape)
        bg(brand-subtle), // light brand tint background
        text-color(brand), // brand text color
        font-size(xs), // font size key xs (0.75rem)
        font(medium) // font weight: medium (500)
    );
}

.plan__price {
    @include apply(m(0)); // margin: 0
}

.plan__amount {
    @include apply(
        font-size(4xl), // font size key 4xl (2.5rem)
        font(bold) // font weight: bold (700)
    );
}

.plan__period,
.plan__text {
    @include apply(
        font-size(sm), // font size key sm (0.875rem)
        text-color(muted) // muted text color, follows the theme
    );
}

.plan__text {
    @include apply(m(0)); // margin: 0
}

// grow keeps the calls to action level when the lists differ in length
.plan__features {
    @include apply(
        grow, // grow to fill free space (flex: 1 1 0%)
        flex, // display: flex
        col, // flex direction: column
        gap(2), // gap: spacing key 2 (0.5rem)
        m(0), // margin: 0
        p(0), // padding: 0
        font-size(sm) // font size key sm (0.875rem)
    );
}

.plan__cta {
    @include apply(
        block, // display: block
        px(4), // horizontal padding: spacing key 4 (1rem)
        py(2), // vertical padding: spacing key 2 (0.5rem)
        border(1), // 1px border (width key 1), regular color
        rounded(md), // corner radius: size key md (0.5rem)
        font(medium), // font weight: medium (500)
        text-center, // center the text
        text-color(regular), // regular text color, follows the theme
        bg(hover) hover // hover background on hover
    );

    &:focus-visible {
        outline: token(border-focus-width) solid token(border-focus);
        outline-offset: token(border-focus-offset);
    }
}

.plan__cta--primary {
    @include apply(
        bg(brand), // brand fill background
        text-color(on-brand), // text color made for the brand fill
        border-color(brand), // border color: brand
        bg(brand-hover) hover // brand hover fill on hover
    );
}
HTML
<div class="pricing">
    <article class="plan">
        <h3 class="plan__name">Starter</h3>
        <p class="plan__price"><span class="plan__amount">$0</span> <span class="plan__period">per month</span></p>
        <p class="plan__text">For one person trying the product on a side project.</p>
        <ul class="plan__features" role="list">
            <li>1 project</li>
            <li>5 GB storage</li>
            <li>Community support</li>
        </ul>
        <a class="plan__cta" href="/signup/?plan=starter">Start for free</a>
    </article>
    <article class="plan plan--featured">
        <div class="plan__header">
            <h3 class="plan__name">Team</h3>
            <span class="plan__badge">Most popular</span>
        </div>
        <p class="plan__price"><span class="plan__amount">$12</span> <span class="plan__period">per user per month</span></p>
        <p class="plan__text">For teams that share projects and review work together.</p>
        <ul class="plan__features" role="list">
            <li>Unlimited projects</li>
            <li>100 GB storage</li>
            <li>Shared workspaces and roles</li>
            <li>Email support</li>
        </ul>
        <a class="plan__cta plan__cta--primary" href="/signup/?plan=team">Start a 14-day trial</a>
    </article>
    <article class="plan">
        <h3 class="plan__name">Business</h3>
        <p class="plan__price"><span class="plan__amount">$29</span> <span class="plan__period">per user per month</span></p>
        <p class="plan__text">For organizations with security and billing requirements.</p>
        <ul class="plan__features" role="list">
            <li>Everything in Team</li>
            <li>1 TB storage</li>
            <li>Single sign-on and audit log</li>
            <li>Priority support</li>
        </ul>
        <a class="plan__cta" href="/contact/">Contact sales</a>
    </article>
</div>

Tokens used

Every color comes from a theme token, so the recipe follows the light, dark and inverse themes with no extra CSS.

bg-surface, text-regular, border-regular
Each plan card.
brand
The featured plan border and the primary call to action fill.
brand-hover, text-on-brand
Primary call to action hover and text. No class exists for role states such as brand-hover, so the hover is in the SCSS version only.
brand-subtle, text-brand
The Most popular badge.
text-muted
Billing period and plan description.
bg-hover, border-focus
Secondary call to action hover and the focus ring.