appearance option, how to change their labels and placeholders, and how to load custom fonts. It assumes you have already initialized the SDK and hold a
payrails client instance - seethe setup guide if you have not.
1. The base stylesheet
The pre-built components (drop-in, card form, buttons, card list) ship a base stylesheet. It is injected automatically when the SDK loads - no manual import is needed. Everything below customizes on top of these base styles.2. The appearance option
Every element the SDK draws accepts an appearance object. Its rules field is CSS-like key/value: selectors on the outside, CSS declarations on the inside:
.payrails-input, .payrails-button, .payrails-dropdown, .payrails-label, .payrails-tile, .payrails-container, .payrails-row, .payrails-cell, .payrails-icon, .payrails-checkbox, .payrails-error, .payrails-text.
State variants use BEM modifiers on those classes:
Any selector a browser supports is valid inside
rules — pseudo-classes and pseudo-elements (:hover, :focus, :focus-visible, ::placeholder, ::selection), media queries (@media), and feature queries (@supports).
The --invalid and --valid classes clear while a field is focused, so a field being corrected does not show the error state. For a persistent invalid look on touched fields, key off --dirty:
@layer payrails-defaults; your rules land in
@layer payrails-appearance, which always wins over the defaults.
3. Style the card form
payrails.cardForm(options) accepts a CardFormAppearance — root rules for the form itself plus one slot per nested widget (installments dropdown, address selector, brand selector):
payrails.paymentButton({ appearance }) directly, or to the cardPaymentButton slot of the drop-in’s appearance.
4. Style the drop-in
The drop-in’s appearance is keyed by its building blocks; each slot takes the same shape as the standalone element:5. Provider-drawn wallet buttons keep their own options
Google Pay and PayPal draw their own chrome (a native SDK button, a hosted iframe), so CSSrules can’t reach them. They take structured appearance.settings instead:
6. Change labels, placeholders, and error messages
Text on the card form is controlled throughtranslations:
placeholdersandlabelsare keyed by field type (CARD_NUMBER,CARDHOLDER_NAME,CVV,EXPIRATION_MONTH,EXPIRATION_YEAR,EXPIRATION_DATE).labels.storeInstrumentrenames the save-card checkbox label.error.defaultsets the default validation error message per field type.
translations.label on payrails.paymentButton(...).
7. Load custom fonts
The secure fields render inside iframes, so fonts from your page are not automatically available there. Pass font descriptors viafonts — either a CSS source or an explicit font-face definition:
family, src, style, weight, unicodeRange, display, or a cssSrc URL. The same fonts option is accepted by payrails.collectContainer(...).
8. Style individual collect elements
When you build your own form with a collect container (see How to collect card data with secure fields), each element accepts its ownappearance; the rules are applied inside that field’s secure iframe:
rules are forwarded to the iframe — secure fields have no nested widget slots.
9. Update appearance and texts after mounting
The card form can be restyled and re-labeled at runtime without remounting:appearance merges over the current rules, leaving other selectors and nested widget slots (installments, address, brandSelector) intact. To clear a declaration, pass its key with an empty value; clearing a whole selector requires a remount.
The card payment button supports paymentButton.update({ translations }) for its label — its appearance cannot be changed after mounting.