Cards - National Design System

A composable container for grouping content, metrics, or actions with stroke, shadow, color-fill, and on-color treatments for any surface

Standard

Build product, article, or service cards by combining header, content, tags, rating, and action sub-components

Card Title Card Subtitle

Short description of this card content goes here for demonstration.

Category Topic Active
<div class="nds-card nds-stroke"> <div class="nds-card-header"> <div class="nds-card-featured-icon"> <span class="nds-featured-icon nds-circle nds-lg"> <i class="hgi hgi-stroke hgi-stars"></i> </span> </div> </div> <div class="nds-card-content"> <div class="nds-card-text"> <span class="nds-card-title">Card Title</span> <span class="nds-card-subtitle">Card Subtitle</span> <p class="nds-card-description">Short description of this card content goes here for demonstration.</p> </div> <div class="nds-card-meta"> <div class="nds-card-tags"> <span class="nds-tag nds-blue nds-sm"> <span class="nds-label">Category</span> </span> <span class="nds-tag nds-gray nds-sm"> <span class="nds-label">Topic</span> </span> <span class="nds-tag nds-green nds-sm"> <span class="nds-label">Active</span> </span> </div> </div> </div> </div>

Statistic

A centered metric layout for headline numbers in dashboards and stats grids

0

Active Users

<div class="nds-card nds-stroke nds-statistic"> <div class="nds-card-header"> <div class="nds-card-featured-icon"> <span class="nds-featured-icon nds-circle nds-xl"> <i class="nds-icon nds-icon-avatar" aria-hidden="true"></i> </span> </div> </div> <div class="nds-card-content"> <div class="nds-card-text"> <span class="nds-card-number nds-counter-value nds-number-format" data-target="125847">0</span> <p class="nds-card-description">Active Users</p> </div> </div> </div>

Product Pricing

A clear price line for product and service cards, built on the Numbers utility: a prominent amount with its currency icon, an optional crossed-out original for sale pricing, and a muted unit suffix as plain text

Sale pricing with the original crossed out
Smart Watch
Smart Watch

AMOLED display, water resistant to 50 meters.

1299 1599
<div class="nds-card nds-stroke"> <div class="nds-card-image"> <img src="https://images.unsplash.com/photo-1523275335684-37898b6baf30?auto=format&fit=crop&w=800&q=60" alt="Smart Watch" loading="lazy"> </div> <div class="nds-card-content"> <div class="nds-card-text"> <span class="nds-card-title">Smart Watch</span> <p class="nds-card-description">AMOLED display, water resistant to 50 meters.</p> </div> <div class="nds-card-value"> <span class="nds-number-format" data-currency="SAR">1299</span> <s class="nds-number-format" data-currency="SAR">1599</s> </div> </div> <div class="nds-card-actions"> <button class="nds-btn nds-primary nds-full" type="button"> <span class="nds-label">Add to Cart</span> </button> </div> </div>
Unit pricing with a plain-text suffix
Specialty Coffee
Specialty Coffee

Medium-roast single-origin Arabica beans.

89 / kg
<div class="nds-card nds-stroke"> <div class="nds-card-image"> <img src="https://images.unsplash.com/photo-1447933601403-0c6688de566e?auto=format&fit=crop&w=800&q=60" alt="Specialty Coffee" loading="lazy"> </div> <div class="nds-card-content"> <div class="nds-card-text"> <span class="nds-card-title">Specialty Coffee</span> <p class="nds-card-description">Medium-roast single-origin Arabica beans.</p> </div> <div class="nds-card-value"> <span class="nds-number-format" data-currency="SAR">89</span> / kg </div> </div> <div class="nds-card-actions"> <button class="nds-btn nds-primary nds-full" type="button"> <span class="nds-label">Add to Cart</span> </button> </div> </div>

Card Group

Pair cards with nds-grid for responsive column-shifting layouts

0

Active Users

0

Completed

0

Success Rate

0

Pending

<div class="nds-grid" style="--max-col: 4; --mid-col: 2; --min-col: 2;"> <div class="nds-card nds-stroke nds-statistic"> <div class="nds-card-header"> <div class="nds-card-featured-icon"> <span class="nds-featured-icon nds-circle nds-xl"> <i class="hgi hgi-stroke hgi-user-multiple"></i> </span> </div> </div> <div class="nds-card-content"> <div class="nds-card-text"> <span class="nds-card-number nds-counter-value nds-number-format" data-target="125847">0</span> <p class="nds-card-description">Active Users</p> </div> </div> </div> <div class="nds-card nds-stroke nds-statistic"> <div class="nds-card-header"> <div class="nds-card-featured-icon"> <span class="nds-featured-icon nds-circle nds-xl"> <i class="nds-icon nds-hgi-checkmark-circle-02" aria-hidden="true"></i> </span> </div> </div> <div class="nds-card-content"> <div class="nds-card-text"> <span class="nds-card-number nds-counter-value nds-number-format" data-target="8542">0</span> <p class="nds-card-description">Completed</p> </div> </div> </div> <div class="nds-card nds-stroke nds-statistic"> <div class="nds-card-header"> <div class="nds-card-featured-icon"> <span class="nds-featured-icon nds-circle nds-xl"> <i class="hgi hgi-stroke hgi-star"></i> </span> </div> </div> <div class="nds-card-content"> <div class="nds-card-text"> <span class="nds-card-number nds-counter-value nds-number-format" data-target="92%">0</span> <p class="nds-card-description">Success Rate</p> </div> </div> </div> <div class="nds-card nds-stroke nds-statistic"> <div class="nds-card-header"> <div class="nds-card-featured-icon"> <span class="nds-featured-icon nds-circle nds-xl"> <i class="hgi hgi-stroke hgi-queue-01"></i> </span> </div> </div> <div class="nds-card-content"> <div class="nds-card-text"> <span class="nds-card-number nds-counter-value nds-number-format" data-target="+1247">0</span> <p class="nds-card-description">Pending</p> </div> </div> </div> </div>

Built-in Features

What you get out of the box with zero configuration

Composable Anatomy

Mix header, content, tags, rating, price, checkbox, status, and actions to build product, article, service, or user cards.

Seven Color Variants

Default, neutral, yellow, red, and blue treatments adjust title, border, and icon tints together. Combine with nds-color for a tinted fill.

Statistic Mode

Centered metric layout with display-sized numbers and an icon for dashboards and stats grids.

Image with Overlay

Aspect ratio, focal point, and gradient overlay are tunable per card through CSS variables on the image container.

On-Color Treatment

Add nds-oncolor to adapt text, borders, and icon tints for dark sections, hero backgrounds, or photographic surfaces.

Interactive States

Use the card as <a> or <button> to get hover and active feedback on stroke and shadow variants.

CSS-Driven Theming

Override padding, gap, radius, colors, and width per instance via --card-* custom properties.

Responsive Layout

Card actions stack on mobile. Pair with nds-grid for column-shifting card groups.

Usage Guidelines

When and how to use cards effectively

Best Practices

  • Use cards to group related content into scannable units: service tiles, product listings, article previews, and dashboard widgets
  • Use nds-statistic for headline metrics in dashboards: a single number, a label, and an optional icon. Pair multiple statistic cards inside a grid for KPI rows
  • Choose nds-stroke for flat or content-heavy layouts. Use nds-shadow for elevated, floating, or modal-adjacent cards
  • Use nds-color together with a color variant (nds-blue, nds-yellow, etc.) to category-code or status-code groups of cards in dashboards
  • Use nds-oncolor when placing cards on dark sections, hero backgrounds, or imagery so text and borders stay readable
  • Make the entire card clickable by using <a> or <button> as the root element, not by wrapping a card in a separate link
  • Don't use a card for a transient status message: use an Alert instead. Don't use a card to block the user for a decision: use a Modal
  • Wrap tags in nds-card-meta only when a second meta row sits beside them, such as a rating. The wrapper is a flex column that groups those rows. Tags on their own go straight inside nds-card-content, with no wrapper: nds-card-tags is styled by the card root, not by the wrapper
  • Don't nest cards inside cards. If you need internal structure, use nds-card-meta, nds-card-tags, or a definition list inside the content area
  • Place nds-card-actions after nds-card-content, not inside it. Only the content area scrolls inside a modal, so buttons placed inside it scroll out of reach on a long form. Actions inside the content still work: a modal pins them to the bottom, and an nds-rowView card keeps them in the content column
  • Add a featured icon or avatar in the header for quick visual recognition. Size up (nds-lg, nds-xl) on statistic cards and grid contexts where the icon carries the meaning
  • Show a price, a rate, or a size with nds-card-value, not tags: the value is an Numbers span (data-currency renders the riyal icon), a <s> child is the crossed-out original, and a unit suffix like / kg is plain text
  • Keep card descriptions to one or two lines. For longer copy, add nds-truncate on the title and description, or link out to a detail page from the actions area

Modifier Classes

ClassElementDescription
nds-strokecard rootAdds a 1px outline border around the card
nds-shadowcard rootAdds an elevation shadow; deepens on hover when the card is interactive
nds-colorcard rootTinted background fill that matches the active color variant
nds-rowViewcard rootSwitches the card to a horizontal row layout. The header sits beside the content and keeps its own size, so an avatar or featured icon stays compact. An image header is 160px wide; set --card-image-width to change it. When the card is too narrow for both columns, the header takes the full width and the content moves under it
nds-centercard rootCenters header, content, tags, rating, and actions horizontally. It must sit on the root, not on an inner part: the card also reads it to switch the featured icon's alignment, so a misplaced nds-center centers nothing and leaves the icon on the old rule
nds-statisticcard rootCentered metric layout with a large display number; size with nds-md or nds-sm on the number element
nds-usercard rootCompact user-card preset with a 224px default width
nds-full-width / nds-fullcard rootRemoves the max-width cap so the card fills its container
nds-oncolorcard rootAdapts text, borders, and icon tints for dark or photographic surfaces
nds-neutral, nds-yellow, nds-red, nds-blue, nds-greencard rootColor variants that retint title, border-hover, and icon. Combine with nds-color for a matching tinted fill
nds-end.nds-card-actionsRight-aligns the actions row within the card
nds-card-statuschild of the card rootAbsolute-positioned status badge slot pinned to the top-start corner of the card; place a tag or badge inside
nds-disabled / [disabled]card rootMutes colors, dims sub-content, and removes pointer interactions

Data Attributes

AttributeElementDescription
data-statuscard rootDeclares the state the card is in. Values: neutral, warning, error, critical, info, success. It renders as the matching color variant, but it is not a color picker. Set it only when the card really carries that state. For a tint on a card that asserts no status, use the color class instead (nds-blue, nds-green, and the rest), and leave data-status off
data-state="loading"card root, or a parent .nds-grid / .nds-paged-contentRenders skeleton shimmer placeholders on the card, or on every child card when set on the parent. Equivalent to adding nds-loading as a class

CSS Custom Properties

PropertyDefaultDescription
--card-bg--background-cardCard background color
--card-bg-hover--background-card-hoveredBackground when the card is interactive and hovered
--card-border--border-neutral-primaryStroke color for the nds-stroke variant
--card-border-hover--border-primaryStroke color when the card is hovered
--card-border-active--border-neutral-primaryStroke color when the card is pressed
--card-padding--spacing-xlInner padding of the card, on both axes
--card-padding-block--card-paddingTop and bottom padding alone. Set it to pad one axis without touching the other
--card-padding-inline--card-paddingStart and end padding alone. Tab content reads it too, so a card-style tab panel keeps the same gutter
--card-gap--spacing-3xlVertical gap between header, content, meta, and actions
--card-radius--radius-lgCorner radius
--card-width100%Card width inside its container
--card-width-min0Minimum width
--card-width-max360pxMaximum width cap
--card-title--text-displayTitle color
--card-subtitle--text-primarySubtitle color
--card-text--text-displayDescription and body text color
--card-number--text-primary-strongStatistic number color
--card-rating--text-secondary-paragraphRating helper text color
--featuredicon-color--featuredicons-icon-primaryFeatured-icon color (also drives the avatar color)
--featuredicon-bg--featuredicons-background-primary-lightFeatured-icon background color
--card-image-width160pxWidth of the image column in an nds-rowView card. It has no effect on a stacked card, where the image fills the card width
--img-ratio2 / 1Set on .nds-card-image to control aspect ratio
--img-pos-x50%Horizontal focal point of the image
--img-pos-y50%Vertical focal point of the image
--overlay0Opacity of the dark gradient overlay on the image (0 to 1)
Last Modified Date: 29/08/2026 - 02:41 PM
Was this page useful?
60% of users said Yes from 2843 Feedbacks