> ## Documentation Index
> Fetch the complete documentation index at: https://primer.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Card form

> Container for secure card payment inputs with validation and submission handling.

## \<primer-card-form>

Container for card payment inputs. Provides context to child components, handles validation, and manages form submission. Uses secure iframes for PCI compliance.

## Quick reference

|                 |                                            |
| --------------- | ------------------------------------------ |
| **Parent**      | `<primer-checkout>`                        |
| **Properties**  | `disabled`, `hide-labels`                  |
| **Slot**        | `card-form-content`                        |
| **Emits**       | `primer:card-success`, `primer:card-error` |
| **Listens for** | `primer:card-submit`                       |

***

## Examples

### Default layout

Renders all card inputs automatically:

```html theme={"dark"}
<primer-card-form></primer-card-form>
```

**Renders:** Card number, expiry, CVV, cardholder name, and submit button.

### Disabled state

```html theme={"dark"}
<primer-card-form disabled></primer-card-form>
```

### Hidden labels

```html theme={"dark"}
<primer-card-form hide-labels></primer-card-form>
```

### Custom layout

```html theme={"dark"}
<primer-card-form>
  <div slot="card-form-content">
    <primer-input-card-number></primer-input-card-number>
    <div style="display: flex; gap: 8px;">
      <primer-input-card-expiry></primer-input-card-expiry>
      <primer-input-cvv></primer-input-cvv>
    </div>
    <primer-input-card-holder-name></primer-input-card-holder-name>
    <button type="submit">Pay Now</button>
  </div>
</primer-card-form>
```

### With error container

```html theme={"dark"}
<primer-card-form>
  <div slot="card-form-content">
    <primer-input-card-number></primer-input-card-number>
    <primer-input-card-expiry></primer-input-card-expiry>
    <primer-input-cvv></primer-input-cvv>
    <primer-error-message-container></primer-error-message-container>
    <primer-card-form-submit></primer-card-form-submit>
  </div>
</primer-card-form>
```

***

## Properties

| Property     | Attribute     | Type      | Default | Description                |
| ------------ | ------------- | --------- | ------- | -------------------------- |
| `disabled`   | `disabled`    | `boolean` | `false` | Prevents form submission   |
| `hideLabels` | `hide-labels` | `boolean` | `false` | Hides labels on all inputs |

***

## Events

### Emitted events

| Event                 | Description                 | Payload                         |
| --------------------- | --------------------------- | ------------------------------- |
| `primer:card-success` | Form submitted successfully | `{ result: unknown }`           |
| `primer:card-error`   | Validation errors occurred  | `{ errors: ValidationError[] }` |

### Listened events

| Event                | Description              |
| -------------------- | ------------------------ |
| `primer:card-submit` | Triggers form submission |

**External submit example:**

```javascript theme={"dark"}
document.getElementById('my-button').addEventListener('click', () => {
  document.dispatchEvent(
    new CustomEvent('primer:card-submit', {
      bubbles: true,
      composed: true
    })
  );
});
```

> **Note:** `bubbles: true` and `composed: true` are required for shadow DOM traversal.

***

## Slots

| Slot                | Description                                                    |
| ------------------- | -------------------------------------------------------------- |
| `card-form-content` | Custom layout for card inputs. Replaces default when provided. |

***

## Methods

| Method     | Description                      |
| ---------- | -------------------------------- |
| `submit()` | Programmatically submit the form |

```javascript theme={"dark"}
const cardForm = document.querySelector('primer-card-form');
await cardForm.submit();
```

***

## CSS properties

| Property                | Description                 | Default |
| ----------------------- | --------------------------- | ------- |
| `--primer-space-small`  | Gap between inline elements | `8px`   |
| `--primer-space-medium` | Gap between block elements  | `16px`  |

***

## Dependencies

Internally uses:

| Component                                                                                                           | Purpose               |
| ------------------------------------------------------------------------------------------------------------------- | --------------------- |
| [primer-input-card-number](/sdk/primer-checkout-web/components/primer-card-form/primer-input-card-number)           | Card number input     |
| [primer-input-card-expiry](/sdk/primer-checkout-web/components/primer-card-form/primer-input-card-expiry)           | Expiry date input     |
| [primer-input-cvv](/sdk/primer-checkout-web/components/primer-card-form/primer-input-cvv)                           | CVV input             |
| [primer-input-card-holder-name](/sdk/primer-checkout-web/components/primer-card-form/primer-input-card-holder-name) | Cardholder name input |
| [primer-card-form-submit](/sdk/primer-checkout-web/components/primer-card-form/primer-card-form-submit)             | Submit button         |

***

## Cardholder name configuration

```javascript theme={"dark"}
checkout.options = {
  card: {
    cardholderName: {
      visible: true,       // Show field (default: true)
      required: true,      // Make required (default: true)
      defaultValue: ''     // Pre-fill value
    }
  }
};
```

***

## Co-branded card schemes

Supports co-branded cards like Cartes Bancaires (CB). Network switcher displays automatically when detected. No configuration needed.

***

## Submit options

| Method                          | Example             |
| ------------------------------- | ------------------- |
| `<primer-card-form-submit>`     | Built-in, localized |
| `<button type="submit">`        | Standard HTML       |
| `<primer-button type="submit">` | Primer button       |
| `data-submit` attribute         | Any element         |
| `primer:card-submit` event      | Programmatic        |

***

## Validation

1. Validates all inputs on submission
2. If invalid, dispatches `primer:card-error`
3. Child inputs display error messages
4. If valid, proceeds with payment

***

## States

| State          | Description                   | Visual Change                         |
| -------------- | ----------------------------- | ------------------------------------- |
| **Ready**      | Form ready for input          | All inputs enabled                    |
| **Validating** | Validation in progress        | Inputs may show loading               |
| **Valid**      | All inputs pass validation    | Submit button enabled                 |
| **Invalid**    | One or more validation errors | Error states on inputs                |
| **Submitting** | Payment being processed       | Inputs disabled, button loading       |
| **Disabled**   | `disabled` attribute set      | All inputs disabled, muted appearance |

***

## Usage guidelines

### Do

* Place all card inputs inside `<primer-card-form>`
* Include `<primer-error-message-container>` for payment failures
* Use `primer:card-submit` event for external submit buttons
* Configure cardholder name via SDK options

### Don't

* Don't use alongside `<primer-payment-method type="PAYMENT_CARD">` (causes duplicates)
* Don't place card inputs outside the form
* Don't use multiple card forms on one page

<Warning>
  Using both `<primer-card-form>` and `<primer-payment-method type="PAYMENT_CARD">` in the same layout creates duplicate card forms. Choose one approach.
</Warning>

***

## Content guidelines

### Submit button text

| Do                 | Don't    |
| ------------------ | -------- |
| "Pay now"          | "Submit" |
| "Complete payment" | "Pay"    |
| "Pay \$49.99"      | "OK"     |

### Error messages

| Do                       | Don't           |
| ------------------------ | --------------- |
| "Card number is invalid" | "Error"         |
| "Card has expired"       | "Invalid input" |

***

## See also

<CardGroup cols={2}>
  <Card title="Build custom card form" icon="credit-card" href="/checkout/primer-checkout/guides-and-recipes/build-custom-card-form">
    Step-by-step guide
  </Card>

  <Card title="Troubleshooting" icon="wrench" href="/checkout/primer-checkout/troubleshooting">
    Common issues and solutions
  </Card>

  <Card title="Events guide" icon="bolt" href="/checkout/primer-checkout/configuration/events">
    Event handling
  </Card>
</CardGroup>
