CSS only

Card

A structural surface with named regions — media, head, subhead, body, sections, subfoot and a three-way foot. SCSS-only: compose the regions you need, skip the rest.

Every region is optional and order-free in authoring, but renders in the structural order: ng-card-mediang-card-head (-left/-right) → ng-card-subheadng-card-body (with ng-card-section blocks) → ng-card-subfootng-card-foot (-left/-center/-right). Other components nest naturally inside: badges, buttons, progress, dropdowns, grids.

Basic

Head with icon and badge, one body section, foot with meta and action:

Project Aurora

Active

Design system rollout for the customer portal: tokens, dark mode and the component inventory, shipped in three milestones.

Updated 2 hours ago
card.html
<div class="ng-card">
    <div class="ng-card-head">
        <div class="ng-card-head-left">
            <i class="ph ph-rocket-launch text-purple fs-2xl"></i>
            <h3>Project Aurora</h3>
        </div>
        <div class="ng-card-head-right">
            <span class="ng-badge ng-badge-success-soft">Active</span>
        </div>
    </div>
    <div class="ng-card-body">
        <div class="ng-card-section">
            <p>Design system rollout for the customer portal: tokens, dark mode
               and the component inventory, shipped in three milestones.</p>
        </div>
    </div>
    <div class="ng-card-foot">
        <div class="ng-card-foot-left">
            <span class="fs-sm text-mute">Updated 2 hours ago</span>
        </div>
        <div class="ng-card-foot-right">
            <a href="#" class="ng-btn ng-btn-primary sm">Open</a>
        </div>
    </div>
</div>

Full anatomy

All regions together — subhead and subfoot draw their dashed separator lines, the body stacks sections with a consistent gap. Real components inside: a flex-grid stats row and a progress bar.

Performance Analytics

LIVE

Traffic and conversions across all active campaigns.

Total views

24.5K

+12.3%

Conversions

1.2K

+8.1%

Data refreshes every 5 minutes.

card.html
<div class="ng-card">
    <div class="ng-card-head">
        <div class="ng-card-head-left">
            <i class="ph ph-chart-line-up text-info fs-2xl"></i>
            <h3>Performance Analytics</h3>
        </div>
        <div class="ng-card-head-right">
            <span class="ng-badge ng-badge-indigo">LIVE</span>
        </div>
    </div>
    <div class="ng-card-subhead">
        <p class="fs-sm text-mute">Traffic and conversions across all active campaigns.</p>
    </div>
    <div class="ng-card-body">
        <div class="ng-card-section">
            <div class="ng-row">
                <div class="ng-col-6">
                    <p class="fs-sm text-mute">Total views</p>
                    <h2>24.5K</h2>
                    <p class="fs-sm text-aguagreen">+12.3%</p>
                </div>
                <div class="ng-col-6">
                    <p class="fs-sm text-mute">Conversions</p>
                    <h2>1.2K</h2>
                    <p class="fs-sm text-info">+8.1%</p>
                </div>
            </div>
        </div>
        <div class="ng-card-section">
            <div class="ng-progress ng-progress-info" style="--ng-progress-value: 68%">
                <div class="ng-progress-bar"></div>
            </div>
        </div>
    </div>
    <div class="ng-card-subfoot">
        <p class="fs-sm">Data refreshes every 5 minutes.</p>
    </div>
    <div class="ng-card-foot">
        <div class="ng-card-foot-left">
            <a href="#" class="text-info">View full report</a>
        </div>
        <div class="ng-card-foot-right">
            <i class="ph-duotone ph-share-network"></i>
            <i class="ph-duotone ph-paper-plane-tilt"></i>
        </div>
    </div>
</div>

Head titles v1.2

New in v1.2: .ng-card-head-titles stacks a .ng-card-title over a .ng-card-subtitle inside head-left, without forcing the whole head-left into a column.

Ada Lovelace
Lead engineer
Online

Title above, subtitle below — without forcing head-left into a column.

card.html
<div class="ng-card">
    <div class="ng-card-head">
        <div class="ng-card-head-left">
            <i class="ph ph-user-circle text-purple fs-2xl"></i>
            <div class="ng-card-head-titles">
                <div class="ng-card-title">Ada Lovelace</div>
                <div class="ng-card-subtitle">Lead engineer</div>
            </div>
        </div>
        <div class="ng-card-head-right">
            <span class="ng-badge ng-badge-success-soft">Online</span>
        </div>
    </div>
    <div class="ng-card-body">
        <div class="ng-card-section"><p>Title above, subtitle below — without forcing head-left into a column.</p></div>
    </div>
</div>

Media

ng-card-media bleeds to the card edges and rounds the top corners; hover lifts the card on mouse-over. Editorial composition with NG parts only: soft badge + icon meta in the body, tag chips in the subfoot, avatar and arrow link in the foot. Two cards in a lanes grid spaced with ng-gap-lg:

Post cover

Engineering 6 min read

Building modern SaaS interfaces

Reusable UI with scoped CSS variables, modular containers and a minimal JavaScript registry.

Author Claudio Pistidda · 12 Mar 2026
Release cover

Release 02 Jun 2026

Nexigrid 1.0 is here

A stable component contract, two grid systems and a fully brandable token layer.

tokens dark-mode grid
Author NexiGrid Team
card.html
<div class="ng-grid ng-lanes-md-2 ng-gap-lg">
    <article class="ng-card hover">
        <div class="ng-card-media">
            <img src="https://picsum.photos/seed/nexigrid-post/900/500" alt="Post cover">
        </div>
        <div class="ng-card-body">
            <div class="ng-card-section">
                <p class="fs-sm">
                    <span class="ng-badge ng-badge-info-soft">Engineering</span>
                    <span class="text-mute ml-8"><i class="ph ph-clock"></i> 6 min read</span>
                </p>
                <h3>Building modern SaaS interfaces</h3>
                <p>Reusable UI with scoped CSS variables, modular containers
                   and a minimal JavaScript registry.</p>
            </div>
        </div>
        <div class="ng-card-foot">
            <div class="ng-card-foot-left">
                <span class="ng-avatar sm circle"><img src="https://i.pravatar.cc/120?img=12" alt="Author"></span>
                <span class="fs-sm">Claudio Pistidda · 12 Mar 2026</span>
            </div>
            <div class="ng-card-foot-right">
                <a href="#" class="text-info fs-sm">Read <i class="ph ph-arrow-right"></i></a>
            </div>
        </div>
    </article>
    <article class="ng-card hover">
        <div class="ng-card-media">
            <img src="https://picsum.photos/seed/nexigrid-release/900/500" alt="Release cover">
        </div>
        <div class="ng-card-body">
            <div class="ng-card-section">
                <p class="fs-sm">
                    <span class="ng-badge ng-badge-purple-soft">Release</span>
                    <span class="text-mute ml-8"><i class="ph ph-calendar-blank"></i> 02 Jun 2026</span>
                </p>
                <h3>Nexigrid 1.0 is here</h3>
                <p>A stable component contract, two grid systems and a
                   fully brandable token layer.</p>
            </div>
        </div>
        <div class="ng-card-subfoot">
            <span class="ng-chip mr-8">tokens</span>
            <span class="ng-chip mr-8">dark-mode</span>
            <span class="ng-chip">grid</span>
        </div>
        <div class="ng-card-foot">
            <div class="ng-card-foot-left">
                <span class="ng-avatar sm circle"><img src="https://i.pravatar.cc/120?img=32" alt="Author"></span>
                <span class="fs-sm">NexiGrid Team</span>
            </div>
            <div class="ng-card-foot-right">
                <a href="#" class="text-purple fs-sm">Changelog <i class="ph ph-arrow-right"></i></a>
            </div>
        </div>
    </article>
</div>

Horizontal

Add horizontal: the media takes a 42% column and the image covers it. Collapses back to vertical under the md breakpoint.

Cover
Case study

Rebranding a booking platform in 6 weeks

One token override file, zero component rewrites: how the L1/L2 variable model carried a full visual refresh.

Read the story
card.html
<div class="ng-card horizontal">
    <div class="ng-card-media">
        <img src="https://picsum.photos/seed/nexigrid-travel/900/700" alt="Cover">
    </div>
    <div class="ng-card-body">
        <div class="ng-card-section">
            <span class="ng-badge ng-badge-aguagreen-soft">Case study</span>
            <h3 class="mt-16">Rebranding a booking platform in 6 weeks</h3>
            <p>One token override file, zero component rewrites: how the
               L1/L2 variable model carried a full visual refresh.</p>
            <a href="#" class="ng-btn ng-btn-primary sm mt-16">Read the story</a>
        </div>
    </div>
</div>

Compact

compact re-scopes the padding and gap variables for denser layouts:

Default density

Standard padding and gaps from the scoped variables.

Compact

Tighter padding and gaps — denser dashboards.

card.html
<div class="ng-grid ng-lanes-md-2 ng-gap-lg">
    <div class="ng-card">
        <div class="ng-card-head">
            <div class="ng-card-head-left"><h3>Default density</h3></div>
        </div>
        <div class="ng-card-body">
            <div class="ng-card-section">
                <p>Standard padding and gaps from the scoped variables.</p>
            </div>
        </div>
    </div>
    <div class="ng-card compact">
        <div class="ng-card-head">
            <div class="ng-card-head-left"><h3>Compact</h3></div>
        </div>
        <div class="ng-card-body">
            <div class="ng-card-section">
                <p>Tighter padding and gaps — denser dashboards.</p>
            </div>
        </div>
    </div>
</div>

Foot alignment

The three foot areas share the row equally and justify their content left, center and right; under md they stack full-width:

The foot splits into three flexible areas.

left
center
right
card.html
<div class="ng-card">
    <div class="ng-card-body">
        <div class="ng-card-section">
            <p>The foot splits into three flexible areas.</p>
        </div>
    </div>
    <div class="ng-card-foot">
        <div class="ng-card-foot-left">
            <span class="ng-badge ng-badge-clight">left</span>
        </div>
        <div class="ng-card-foot-center">
            <span class="ng-badge ng-badge-clight">center</span>
        </div>
        <div class="ng-card-foot-right">
            <span class="ng-badge ng-badge-clight">right</span>
        </div>
    </div>
</div>

Customization

Everything visual reads from scoped variables — override them on a wrapper instead of restyling the card:

custom.css
.my-dashboard .ng-card {
    --ng-card-radius: var(--ng-radius-lg);
    --ng-card-shadow: none;
    --ng-card-padding: 1.25rem;
}
--ng-card-bg / --ng-card-colorSurface and text colour (defaults follow the theme).
--ng-card-radiusCorner radius — defaults to --ng-radius-md via fallback-at-use.
--ng-card-border-width / --ng-card-border-colorBorder (defaults from the global border tokens).
--ng-card-shadow / --ng-card-shadow-hoverResting and hover elevation.
--ng-card-padding / --ng-card-body-padding / --ng-card-header-padding / --ng-card-footer-paddingRegion padding.
--ng-card-gap / --ng-card-section-gap / --ng-card-gap-footStacking gaps for body, sections and foot.

Anatomy

ng-card ng-card-media ng-card-head ng-card-head-left ng-card-head-right ng-card-subhead ng-card-body ng-card-section ng-card-subfoot ng-card-foot ng-card-foot-left ng-card-foot-center ng-card-foot-right

Modifiers

hover compact horizontal

Reference

Generated from the component source (_ng_card.scss).

Component info

NameCard
Typecss
Version1.4.0
Statuscss
CSS/assets/css/components/_ng_card.scss

Classes

.ng-btn .ng-card .ng-card-body .ng-card-foot .ng-card-foot-center .ng-card-foot-left .ng-card-foot-right .ng-card-head .ng-card-head-left .ng-card-head-right .ng-card-head-titles .ng-card-media .ng-card-section .ng-card-subfoot .ng-card-subhead .ng-card-subtitle .ng-card-title

Tokens

--ng-card-bg --ng-card-border-color --ng-card-border-topbot-line --ng-card-border-width --ng-card-color --ng-card-divider-color --ng-card-divider-style --ng-card-divider-width --ng-card-foot-border-top --ng-card-foot-gap-x --ng-card-foot-gap-y --ng-card-foot-pad-y --ng-card-gap --ng-card-gap-block --ng-card-head-border-bottom --ng-card-head-gap-x --ng-card-head-gap-y --ng-card-head-pad-y --ng-card-pad-x --ng-card-section-gap --ng-card-sub-color