Skip to main content
Cards is available in sandbox only while we finish development. Dakota enables Cards per account. The Cards endpoints are in the API reference, marked Sandbox only. Endpoints, fields, and flows can still change before release.
Card details are styled in three independent layers. Reach for the lowest one that gets you the look you need:
  1. The default stylesheet — a finished card face you import and use as-is.
  2. Your own CSS — override custom properties, or re-declare any rule, on the documented DOM recipe.
  3. The theme option — text styling that carries into the revealed value frames.

The default stylesheet

This paints the Dakota card face: a black card with a diagonal charcoal gradient, the DAKOTA wordmark top-left, the card-network mark top-right, and a grain-textured disc in the bottom-right — with a Barlow PAN and Lato labels. The brand marks and the disc are inlined as SVG, and the fonts are self-hosted inside the package and served from your own origin, so rendering the face makes no third-party requests.

The DOM recipe

Both the vanilla and React integrations render the same structure. The React <CardDetails> component produces it for you. In plain JS, you write it yourself and point the mount targets at the four value nodes:
Into each value node, the SDK injects its own field markup:
.dk-field__masked holds the placeholder glyphs, and .dk-field__frame hosts the value frame. The SDK toggles their hidden attribute as the card reveals and re-masks. The swap happens at the start of a reveal: the frame side becomes visible while the value frames are still loading. The default stylesheet paints an empty visible host as a quiet loading pulse (.dk-field__frame:not([hidden]):empty). Restyle that selector to change the loading look. A failed reveal swaps back to the masked side. The visually-hidden .dk-live region announces transitions to screen readers.

The style contract

These class names, the data-dk-field attribute, and the custom properties below are a public contract covered by semantic versioning. They will not change without a major release. Target them freely from your own CSS.

Custom markup (the headless hook)

Rendering your own face with useCardDetails makes the per-field internals (.dk-field__masked and .dk-field__frame) part of your stylesheet. Four of those rules are load-bearing:
  1. Never display:none a hidden frame host. Browsers deny rendering to display:none subtrees, and the card-data processor’s frames only finish mounting once they render. Hide with visibility: hidden and keep the box, as the default stylesheet does.
  2. Explicitly size visible frame hosts — with slack. An auto-sized host lets the frame fall back to the browser’s default iframe dimensions (300×150). An exactly-fitted one lets fractional rounding overflow the embedded page, and its own scrollbars render over the digits. Give every frame a text-line height and a per-field width, each a few pixels larger than the text needs.
  3. Host height must cover the captured line-height. The frames copy each host’s computed text styles (see below). If the host box is shorter than that line box, the digits clip at the bottom.
  4. Re-anchor inline placements while revealed. A revealed .dk-field has no text baseline, because the masked glyphs are hidden. A widget placed inline next to text therefore aligns by its bottom edge, and the digits ride high. Center it on the line instead: .dk-field:has(.dk-field__masked[hidden]) { vertical-align: middle }.
The SDK-injected .dk-live announcer hides itself, inline through the CSSOM, which content security policies do not block. Custom stylesheets need no rule for it. Frame hosts likewise declare color-scheme: light on themselves, matching the frame documents, so browsers keep the frames transparent inside dark-scheme apps. No rule is needed, and there is no white backdrop behind the digits. Per-field text metrics come from your CSS on the mount targets — each frame captures its host’s computed styles — while the theme option carries the uniform brand values (color, family, weight, spacing) into every frame. Set sizes per field in CSS. Set the shared look once in theme.

Restyle with CSS

The quickest reskin is to override the custom properties on .dk-card:
Need more than the properties expose? Re-declare any rule on the recipe’s classes. The default stylesheet is a set of sensible defaults, not a locked black box, so you can change the dimensions, fonts, or layout without forking it.
The face styling above lives in your DOM. It does not reach inside the revealed value frames. For those, use the theme option.

The theme option

The revealed values render inside frames that the SDK cannot restyle from the outside. To make them match your face, pass a theme when you create the handle. Its keys are text-style overrides that are forwarded into the value frames:
In React, pass the same object as the theme prop. Inside the frames, Barlow resolves only on systems that have it installed. The frames load no webfonts (see the constraints below), so otherwise the system-ui fallback carries the look. List your brand font first if you want it where available, but choose a fallback you are happy to ship. CardTheme accepts exactly these keys. Each one maps to the CSS property of the same name: Two constraints apply to the values:
  • They must be concrete. The values are serialized into the frame documents, where your page’s CSS custom properties do not exist. A var() reference is rejected, and the handle throws an invalid_theme error at creation. Resolve design tokens to literal values before you pass them. In React, the handle is created while mounting, so the throw surfaces as a component error that your nearest error boundary catches.
  • Fonts must be available inside the frames. The frames load no webfonts, so name widely-available families with a generic fallback, rather than your brand’s loaded font: 'Courier New, monospace', not a webfont-only family.
Fidelity note. These five text properties are the styles that carry into the value frames. Dakota confirms the exact rendering inside the frames against the live card-data processor for each release. Treat the propagated result as verified for the version you install, and check it again after you upgrade if pixel-exact matching matters to you.

Internationalization

The masked face and its screen-reader announcements use a small set of strings that you can override for each handle, through the strings option. Any key you omit falls back to its default.
In React, the <CardDetails> component reads validThru and cvvLabel for the on-face captions, and passes the full strings object through to the core for the placeholder and the announcements.