Skip to main content
This tutorial walks you through building a custom card form with Primer Checkout. You’ll learn how to customize the layout, style the inputs, handle events, and avoid common pitfalls.

Prerequisites

Before starting, make sure you have:

Understanding the card form architecture

The <primer-card-form> component provides a customizable card payment interface with PCI-compliant hosted inputs. Here’s how the components relate to each other:
Security by designThe card input components (primer-input-card-number, primer-input-card-expiry, primer-input-cvv) render secure iframes that isolate sensitive card data. This means:
  • Card data never touches your page’s DOM
  • Your integration remains PCI-compliant
  • Styling is applied through CSS variables that are passed to the iframe

Key components

Step 1: Create the card form

Start by creating a custom card form using the card-form-content slot:
Component hierarchy mattersAll card input components must be nested inside <primer-card-form>. Placing them outside breaks the context connection and the form won’t work.

Step 2: Customize the layout

Vertical layout (default)

Stack inputs vertically for a clean, mobile-friendly form:

Grouped layout

Place expiry and CVV side by side:

Responsive layout

Adapt the layout based on screen size:

Step 3: Style the inputs

Style card inputs using CSS variables. These properties are passed through to the secure iframes:
For a complete list of CSS variables, see the Styling guide.

Adding custom labels

Wrap inputs with labels for better accessibility:

Step 4: Handle events and submission

Listen for events to provide feedback and handle the payment flow:
For comprehensive event handling patterns, see the Events guide.

Programmatic submission

You can submit the card form programmatically instead of using the built-in submit button:

Setting cardholder name programmatically

If you collect the cardholder name elsewhere (e.g., from a shipping form), you can set it programmatically:
When using setCardholderName(), you don’t need to include the <primer-input-card-holder-name> component in your form.

Step 5: Handle payment completion

Listen for the checkout state to handle successful payments:

Common mistakes to avoid

Don’t include both <primer-card-form> and <primer-payment-method type="PAYMENT_CARD"> in your layout. The payment method component already renders a card form internally.
Card input components must be descendants of <primer-card-form>. They won’t work if placed outside.
When rendering card forms dynamically, ensure the parent <primer-card-form> exists before adding input children:
When customizing the card form layout, always use the card-form-content slot:

Complete example

Here’s a complete example combining all the concepts:

See also

Styling guide

Customize colors, fonts, and spacing

Events guide

Handle checkout events across platforms

Error handling

Display and handle payment errors

Android SDK Reference

Android SDK API documentation

iOS SDK Reference

iOS SDK API documentation