Skip to main content

Styling & Appearance

Elements fields render inside iframes, so you can’t target them with your page’s CSS. Instead, you pass a style configuration object that the SDK applies inside each iframe.

Style Config Shape

type ElementStyleConfig = {
  base?:        StyleProperties; // default state
  focus?:       StyleProperties; // when the field has focus
  invalid?:     StyleProperties; // value is present but invalid
  complete?:    StyleProperties; // value is complete and valid
  placeholder?: StyleProperties; // styles the placeholder text
};
Each key maps to a StyleProperties object where the keys are camelCase CSS properties.

Passing Styles

Per-element — pass style in the options when creating an element:
const cardNumber = vault.createElement('cardNumber', {
  style: {
    base:        { color: '#1a1a2e', fontSize: '15px', padding: '12px 14px' },
    focus:       { caretColor: '#6366f1', backgroundColor: '#fff' },
    invalid:     { color: '#ef4444' },
    complete:    { color: '#22c55e' },
    placeholder: { color: '#94a3b8' },
  },
});
Global default — pass appearance when constructing OzVault. It accepts an Appearance object with an optional theme preset and/or variables overrides. All elements inherit this; per-element style merges on top.
const vault = new OzVault('YOUR_API_KEY', {
  pubKey: 'YOUR_PUB_KEY',
  appearance: {
    theme: 'flat',
    variables: {
      colorPrimary:     '#6366f1',
      colorText:        '#1a1a2e',
      fontFamily:       '"Inter", sans-serif',
      fontSize:         '15px',
      padding:          '12px 14px',
      colorPlaceholder: '#94a3b8',
    },
  },
});

Themes

The theme preset provides a complete set of defaults. Available themes:
ThemeDescription
'default'Light background, neutral text, indigo caret
'night'Dark-mode palette with light text
'flat'Flat style with bottom-border-only inputs

AppearanceVariables

VariableMaps to
colorTextbase.color
colorBackgroundbase.backgroundColor
colorPrimaryfocus.caretColor and focus.color
colorDangerinvalid.color
colorSuccesscomplete.color
colorPlaceholderplaceholder.color
fontFamilybase.fontFamily
fontSizebase.fontSize
fontWeightbase.fontWeight
letterSpacingbase.letterSpacing
lineHeightbase.lineHeight
paddingbase.padding
You can combine theme + variables — the theme applies first, then variables override on top.

Supported Style Properties

Typography

PropertyCSS equivalent
colorcolor
fontSizefont-size
fontFamilyfont-family
fontWeightfont-weight
fontStylefont-style
fontVariantfont-variant
letterSpacingletter-spacing
lineHeightline-height
textAligntext-align
textDecorationtext-decoration
textShadowtext-shadow
textTransformtext-transform

Spacing & Box

PropertyCSS equivalent
paddingpadding
paddingToppadding-top
paddingRightpadding-right
paddingBottompadding-bottom
paddingLeftpadding-left

Background & Border

PropertyCSS equivalent
backgroundColorbackground-color
opacityopacity
borderRadiusborder-radius
borderTopLeftRadiusborder-top-left-radius
borderTopRightRadiusborder-top-right-radius
borderBottomLeftRadiusborder-bottom-left-radius
borderBottomRightRadiusborder-bottom-right-radius
borderborder
borderColorborder-color
borderWidthborder-width
borderStyleborder-style
borderTop / borderRight / borderBottom / borderLeftindividual side shorthands
borderTopColor / borderRightColor / borderBottomColor / borderLeftColorindividual side colors
borderTopWidth / borderRightWidth / borderBottomWidth / borderLeftWidthindividual side widths
borderTopStyle / borderRightStyle / borderBottomStyle / borderLeftStyleindividual side styles
boxShadowbox-shadow
outlineoutline
outlineColoroutline-color
outlineWidthoutline-width
outlineStyleoutline-style
outlineOffsetoutline-offset

Sizing

PropertyCSS equivalent
heightheight
minHeightmin-height
maxHeightmax-height

Caret

PropertyCSS equivalent
caretColorcaret-color

Transitions & Cursors

PropertyCSS equivalent
transitiontransition
cursorcursor
Properties like position, display, and width that could affect iframe layout are not supported. Use height / minHeight to control the field’s vertical size.

Custom Fonts

To use a custom web font inside the iframes, pass a fonts array to OzVault. You can reference a Google Fonts URL:
const vault = new OzVault('YOUR_API_KEY', {
  pubKey: 'YOUR_PUB_KEY',
  fonts: [
    {
      cssSrc: 'https://fonts.googleapis.com/css2?family=Inter:wght@400;500&display=swap',
    },
  ],
  appearance: {
    variables: {
      fontFamily: "'Inter', sans-serif",
    },
  },
});
Or a self-hosted font:
fonts: [
  {
    family: 'MyFont',
    src:    'url(https://yourcdn.com/fonts/myfont.woff2) format("woff2")',
    weight: '400',
    style:  'normal',
  },
],

Complete Example

const vault = new OzVault('YOUR_API_KEY', {
  pubKey: 'YOUR_PUB_KEY',
  fonts: [
    { cssSrc: 'https://fonts.googleapis.com/css2?family=Inter:wght@400;500&display=swap' },
  ],
  appearance: {
    theme: 'default',
    variables: {
      fontFamily:       "'Inter', sans-serif",
      fontSize:         '15px',
      colorText:        '#111827',
      padding:          '11px 13px',
      colorBackground:  '#f9fafb',
      colorPrimary:     '#6366f1',
      colorDanger:      '#ef4444',
      colorSuccess:     '#16a34a',
      colorPlaceholder: '#9ca3af',
    },
  },
});

const cardNumber = vault.createElement('cardNumber');
const expiry     = vault.createElement('expirationDate');
const cvv        = vault.createElement('cvv', {
  style: {
    // override just the CVV field
    base: { letterSpacing: '0.15em' },
  },
});

Reflecting State with CSS Classes

Combine the change event with CSS classes on your wrapper element to style the border and background based on field state:
function watchField(el, wrapperId) {
  el.on('change', ({ complete, valid, error }) => {
    const wrap = document.getElementById(wrapperId);
    wrap.classList.toggle('oz-complete', complete && valid);
    wrap.classList.toggle('oz-invalid',  !valid && error != null);
  });
  el.on('focus', () => document.getElementById(wrapperId).classList.add('oz-focused'));
  el.on('blur',  () => document.getElementById(wrapperId).classList.remove('oz-focused'));
}

watchField(cardNumber, 'card-number-wrap');
watchField(expiry,     'expiry-wrap');
watchField(cvv,        'cvv-wrap');
.oz-field-wrap {
  border: 1px solid #e5e7eb;
  border-radius: 8px;
  transition: border-color 0.15s;
}

.oz-field-wrap.oz-focused  { border-color: #6366f1; }
.oz-field-wrap.oz-complete { border-color: #22c55e; }
.oz-field-wrap.oz-invalid  { border-color: #ef4444; }

Next Steps