Skip to content
WovenUI LogoWovenUI

Templates

Pricing table template

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

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
Live preview of the pricing table, rendered from the HTML on this page.

HTML to copy

The markup of the preview, in WovenUI core utility classes. It needs only the prebuilt@wovenui/core/dist/wovenui.min.css, or your own build with $generate-utility-classes: true. No components package and no JavaScript.

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 "@wovenui/core" as *; emits the tokens and base styles, and each apply() writes one rule.

SCSS
@use "@wovenui/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 template 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.