Styling & Customization

Customize the Inflow card payment form with two recommended APIs:

  • appearance — theme tokens (colors, radii, fonts). Defaults are light; you drive dark (or any theme) by passing the variables you want.
  • options — layout, width, card / wallet button labels and wallet button color (wallets.buttonTheme), placeholders, and success UI

Legacy style and top-level copy props still work, but prefer appearance and options for new integrations.

Quick example

appearance: {
  // fonts is optional. When set, cssSrc must be a Google Fonts URL
  // (fonts.googleapis.com / fonts.google.com). Built-in fonts like Inter
  // load from fontFamily alone — no fonts entry needed.
  fonts: [
    {
      cssSrc:
        'https://fonts.googleapis.com/css2?family=Lato:wght@400;700&display=swap',
    },
  ],
  variables: {
    fontFamily: 'Lato, system-ui, sans-serif',
    primaryColor: '#0070F3',
    buttonBackgroundColor: '#0070F3',
    buttonTextColor: '#FFFFFF',
    buttonBorderRadius: '8px',
  },
},
options: {
  paymentMethodLayout: 'horizontalSelector',
  paymentMethodOrder: ['apple_pay', 'google_pay', 'card'],
  cardFieldLayout: 'compact',
  fillParent: true,
  buttonText: 'Pay €49.99',
  wallets: {
    buttonText: {
      applePay: 'Pay with Apple Pay',
      googlePay: 'Pay with Google Pay',
    },
    // buttonTheme: 'white', // default is black — set 'white' for dark surfaces
  },
  cardForm: {
    placeholders: {
      cardNumber: 'Card number',
      expiry: 'MM / YY',
      cvc: 'CVC',
    },
  },
  showDefaultSuccessUI: true,
}

Precedence

  • Theme: if appearance is set, it is used; otherwise legacy style is applied.
  • Width: options.fillParent if set; otherwise style.fillParent.
  • Copy / success UI: values under options win over deprecated top-level fields.

Appearance

Use appearance to theme the checkout form. Variables map to CSS custom properties inside the iframe.

appearance: {
  // fonts is optional. When set, cssSrc must be a Google Fonts URL
  // (fonts.googleapis.com / fonts.google.com). Built-in fonts like Inter
  // load from fontFamily alone — no fonts entry needed.
  fonts: [
    {
      cssSrc:
        'https://fonts.googleapis.com/css2?family=Lato:wght@400;700&display=swap',
    },
  ],
  variables: {
    fontFamily: 'Lato, system-ui, sans-serif',
    formBackgroundColor: 'transparent',
    backgroundColor: '#ffffff',
    textColor: '#111111',
    textSecondaryColor: '#6b7280',
    placeholderColor: '#9ca3af',
    primaryColor: '#111111',
    primaryTextColor: '#ffffff',
    layoutBorderColor: '#d8d8d8',
    inputBorderColor: '#e5e5e5',
    inputFocusBorderColor: '#111111',
    layoutBorderRadius: '12px',
    inputBorderRadius: '8px',
    buttonBorderRadius: '8px',
    dangerColor: '#ef4444',
    dangerBackgroundColor: '#fee2e2',
    successColor: '#ffffff',
    successBackgroundColor: '#22c55e',
    buttonBackgroundColor: '#111111',
    buttonTextColor: '#ffffff',
    loaderColor: '#e8e8e8',
    // Special-case only — see table below:
    // iframeBackgroundColor: '#ffffff',
  },
}

appearance.variables

VariablePurpose
fontFamilyCSS font stack for the form, including wallet button labels. Known Google Fonts in the primary slot are auto-loaded
formBackgroundColorCheckout form box background. Default is transparent so the parent page shows through
iframeBackgroundColorSpecial case. Overrides the iframe document (html / body) background. Omit by default; use only when the iframe background does not match the page and formBackgroundColor alone is not enough
backgroundColorInput / panel surface background
textColorPrimary text
textSecondaryColorSecondary / muted text (labels, disclaimer, helpers)
placeholderColorInput placeholders
primaryColorBrand / selection accent
primaryTextColorText and icons on primary-filled surfaces
layoutBorderColorPayment-method layout and divider borders
inputBorderColorCard input borders
inputFocusBorderColorFocused input borders
layoutBorderRadiusLayout chrome radius
inputBorderRadiusInput radius
buttonBorderRadiusPay / wallet button radius (shared; see Wallet buttons)
dangerColorError text / field errors
dangerBackgroundColorError banner background
successColorSuccess accent
successBackgroundColorSuccess fill surfaces
buttonBackgroundColorCard pay button background (falls back to primaryColor when omitted). Does not apply to wallet buttons
buttonTextColorCard pay button label color. Does not apply to wallet buttons
loaderColorSkeleton loader shimmer base color on the parent page while the iframe loads. Any CSS color (hex, rgb, named like red, hsl, …). Default light grey; the highlight stop is lightened from this

appearance.fonts

Optional Google Fonts stylesheets for fonts outside the SDK auto-load list.

These are auto-loaded from fontFamily alone (no fonts entry needed):
DM Sans, Inter, Poppins, Nunito, Work Sans, Manrope, Rubik, Karla, Figtree, Outfit, Space Grotesk, Urbanist.

For any other Google Font, pass a stylesheet URL. Only https://fonts.googleapis.com and https://fonts.google.com HTTPS URLs are accepted.

appearance: {
  fonts: [
    {
      cssSrc:
        'https://fonts.googleapis.com/css2?family=Lato:wght@400;700&display=swap',
    },
  ],
  variables: {
    fontFamily: 'Lato, system-ui, sans-serif',
  },
}

Dark mode

Current SDK builds keep light CSS token defaults in the iframe. There is no automatic OS dark-mode flip when you use appearanceappearance.variables is the single source of truth.

appearance also has no built-in dark block (unlike legacy style.dark).

To support dark mode (or any custom theme), detect it in your app however you prefer (system preference, class toggle, theme provider, etc.), then provide the matching appearance.variables based on your dark mode flag and set options.wallets.buttonTheme so wallet buttons match the surface (e.g. "white" on dark backgrounds).

const isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;

appearance: {
  variables: isDark
    ? {
        backgroundColor: '#1A1A1A',
        textColor: '#FFFFFF',
        textSecondaryColor: '#959499',
        placeholderColor: '#959499',
        primaryColor: '#FFFFFF',
        primaryTextColor: '#111111',
        buttonBackgroundColor: '#FFFFFF',
        buttonTextColor: '#111111',
        layoutBorderColor: '#333333',
        inputBorderColor: '#333333',
        loaderColor: '#2d2d2d',
      }
    : {
        backgroundColor: '#FFFFFF',
        textColor: '#1A1A1A',
        primaryColor: '#0070F3',
        buttonBackgroundColor: '#0070F3',
        buttonTextColor: '#FFFFFF',
        loaderColor: '#e8e8e8',
      },
},
options: {
  wallets: {
    // Match the checkout surface — white wallets on dark, black on light
    buttonTheme: isDark ? 'white' : 'black',
  },
},

Options

Use options for layout and non-theme configuration.

options: {
  paymentMethodLayout: 'stacked', // 'stacked' | 'verticalSelector' | 'horizontalSelector'
  paymentMethodOrder: ['apple_pay', 'google_pay', 'card'],
  cardFieldLayout: 'compact', // 'compact' | 'split'
  fillParent: true,
  buttonText: 'Pay now',
  wallets: {
    buttonText: {
      applePay: 'Pay with Apple Pay',
      googlePay: 'Pay with Google Pay',
    },
    // buttonTheme: 'white', // default is black — set 'white' for dark surfaces
  },
  cardForm: {
    placeholders: {
      cardNumber: 'Card number',
      expiry: 'MM / YY',
      cvc: 'CVC',
    },
  },
  showDefaultSuccessUI: true,
}
OptionDefaultDescription
paymentMethodLayoutstackedstacked (wallets on top, card always visible), verticalSelector (vertical selectable list), or horizontalSelector (horizontal selectable tabs)
paymentMethodOrdercard, then walletsDisplay order and default selection for verticalSelector and horizontalSelector only. Values: card, apple_pay, google_pay. First available method is shown first and selected; unavailable entries are skipped. Does not change stacked layout behavior
cardFieldLayoutcompactcompact (grouped fields) or split (number alone; expiry + CVC on a second row)
fillParentfalseWhen true, host iframe and form use 100% width
buttonText"Complete Payment"Card pay button label (does not apply to wallet buttons)
wallets.buttonText.applePaylocale "Pay"Apple Pay button label (translated when omitted; overrides are used as-is)
wallets.buttonText.googlePaylocale "Pay"Google Pay button label (translated when omitted; overrides are used as-is)
wallets.buttonTheme"black"Wallet button color — "black" or "white" to match your checkout surface. Defaults to black when unset; see Wallet buttons
cardForm.placeholdersCard number / expiry / CVC placeholders
showDefaultSuccessUItrueShow the built-in success screen after payment

Wallet buttons

Apple Pay and Google Pay are configured under options.wallets. Appearance color tokens do not theme wallet button fill/label colors — use wallets.buttonTheme for that.

What appearance applies to wallet buttons

Only these Appearance variables affect wallet buttons:

  • appearance.variables.fontFamily — wallet button label font (shared with the rest of the form)
  • appearance.variables.buttonBorderRadius — corner radius (shared with the card pay button)

Every other Appearance property — including colors such as buttonBackgroundColor, buttonTextColor, primaryColor, borders, and the rest of the variables table — does not apply to wallet buttons.

What you configure under options.wallets

FieldPurpose
buttonText.applePay / buttonText.googlePayWallet button labels. If omitted, the iframe uses the localized default for "Pay". Merchant-provided strings are not translated.
buttonThemeWallet button color for your checkout design. Set "black" or "white" to match the surface the buttons sit on (e.g. "white" on dark backgrounds). Defaults to black when unset.
buttonThemeBackgroundText
black (default)BlackWhite
whiteWhiteBlack

Wallet buttons use black or white only; you cannot set custom brand colors on them via Appearance.

options: {
  buttonText: 'Start Trial', // card CTA only
  wallets: {
    buttonText: {
      applePay: 'Pay $0.50 & Start Trial',
      googlePay: 'Pay with Google Pay',
    },
    buttonTheme: 'white',
  },
},
appearance: {
  variables: {
    fontFamily: 'Lato, system-ui, sans-serif', // applies to wallet labels
    buttonBorderRadius: '8px', // applies to card + wallet buttons
    buttonBackgroundColor: '#adffd2', // card pay button only — not wallets
    buttonTextColor: '#000000', // card pay button only — not wallets
  },
},

Payment method order

Applies to selector layouts (verticalSelector / horizontalSelector):

options: {
  paymentMethodLayout: 'horizontalSelector',
  paymentMethodOrder: ['apple_pay', 'google_pay', 'card'],
}

If Apple Pay is unavailable, Google Pay is selected when available; otherwise Card. Remaining enabled methods that were not listed are appended after your order.

Legacy styling (style)

The style object is deprecated but still fully supported when appearance is not provided.

style: {
  fontFamily: 'Inter',
  fillParent: true,
  formBackgroundColor: '#211e19',

  inputContainer: {
    backgroundColor: '#F5F5F5',
    borderRadius: '8px',
    borderEnabled: true,
    borderColor: '#E0E0E0',
  },

  input: {
    textColor: '#1A1A1A',
    placeholderColor: '#999999',
    backgroundColor: 'transparent',
  },

  button: {
    backgroundColor: '#0070F3',
    textColor: '#FFFFFF',
    borderRadius: '8px',
    fontSize: '16px',
    fontWeight: 600,
    hover: {
      backgroundColor: '#0051CC',
    },
    disabled: {
      opacity: 0.5,
    },
  },

  successUI: {
    backgroundColor: '#F5F5F5',
    primaryTextColor: '#1A1A1A',
    secondaryTextColor: '#999999',
  },

  dark: {
    inputContainer: {
      backgroundColor: '#1A1A1A',
      borderColor: '#333333',
    },
    input: {
      textColor: '#FFFFFF',
      placeholderColor: '#959499',
    },
    button: {
      backgroundColor: '#0066CC',
    },
    successUI: {
      backgroundColor: '#1A1A1A',
      primaryTextColor: '#FFFFFF',
      secondaryTextColor: '#959499',
    },
  },
}

Supported legacy style fields: fontFamily, fillParent, formBackgroundColor, inputContainer, input, button (including hover / disabled / loaderColor), successUI, generalError, disclaimerColor, fieldErrorColor, dark.

Legacy → recommended

Legacy fieldRecommended replacement
styleappearance.variables
style.fillParentoptions.fillParent
style.fontFamilyappearance.variables.fontFamily (+ optional appearance.fonts)
style.darkNo appearance.dark — detect theme in your app and pass matching appearance.variables (plus options.wallets.buttonTheme for wallet colors)
top-level buttonTextoptions.buttonText
top-level placeholdersoptions.cardForm.placeholders
top-level showDefaultSuccessUIoptions.showDefaultSuccessUI

Top-level buttonText, placeholders, and showDefaultSuccessUI remain supported for compatibility:

buttonText: 'Pay €49.99',
placeholders: {
  cardNumber: '1234 5678 9012 3456',
  expiry: 'MM/YY',
  cvc: 'CVC',
},

Prefer options.buttonText and options.cardForm.placeholders for new integrations.

The styling API may evolve. Refer to the npm package for the full TypeScript types and all available properties.


Did this page help you?