Styling & Customization

Customize the Inflow card payment form with two recommended APIs:

  • appearance — theme tokens (colors, radii, fonts)
  • options — layout, width, card / wallet button labels, 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',
    },
  },
  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',
    // 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

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

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

To support dark mode, detect it in your app however you prefer (system preference, class toggle, theme provider, etc.), then pass the matching appearance.variables (and remount or update the element when the theme changes).

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

appearance: {
  variables: isDark
    ? {
        backgroundColor: '#1A1A1A',
        textColor: '#FFFFFF',
        placeholderColor: '#959499',
        primaryColor: '#0066CC',
        buttonBackgroundColor: '#0066CC',
        buttonTextColor: '#FFFFFF',
        layoutBorderColor: '#333333',
        inputBorderColor: '#333333',
      }
    : {
        backgroundColor: '#FFFFFF',
        textColor: '#1A1A1A',
        primaryColor: '#0070F3',
        buttonBackgroundColor: '#0070F3',
        buttonTextColor: '#FFFFFF',
      },
}

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',
    },
  },
  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"auto"Rare override — leave unset / "auto" unless you must lock wallets to a single color; 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 mainly under options.wallets. Appearance does not fully theme wallet buttons.

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.
buttonThemeRare override only. Leave unset (default "auto") so wallets follow the system light/dark theme. Set "black" or "white" only if you must keep one fixed wallet color (for example, always black even in dark mode). Most integrations should not set this.

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: omit — keep default "auto"
  },
},
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 dark mode in your app and pass matching appearance.variables
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?