Core Concepts

Card Elements

Individual card input fields or combined card element

Card Elements

Card Elements allow you to collect card payment information securely. Vue Stripe provides both a combined CardElement that collects all card details in a single input, and individual elements for more granular control.

CardElement

The CardElement is a flexible single-line input that collects all necessary card details (card number, expiration date, and CVC) in one component.

Basic Usage

<script setup>
import { loadStripe } from '@stripe/stripe-js'
import { CardElement, Elements, useElements, useStripe } from 'vue-stripe'

const stripePromise = loadStripe('pk_test_xxx')
const stripe = useStripe()
const elements = useElements()

async function handleSubmit() {
  if (!stripe.value || !elements.value) {
    return
  }

  const cardElement = elements.value.getElement(CardElement)
  if (!cardElement) {
    return
  }

  const { error, paymentMethod } = await stripe.value.createPaymentMethod({
    type: 'card',
    card: cardElement,
  })

  if (error) {
    console.error(error.message)
  }
  else {
    // Use paymentMethod.id to confirm payment
    console.log('Payment method created:', paymentMethod.id)
  }
}
</script>

<template>
  <Elements :stripe="stripePromise">
    <form @submit.prevent="handleSubmit">
      <CardElement />
      <button type="submit">
        Pay
      </button>
    </form>
  </Elements>
</template>

Individual Card Elements

For more control over the layout, you can use individual card elements:

CardNumberElement

<template>
  <CardNumberElement />
</template>

CardExpiryElement

<template>
  <CardExpiryElement />
</template>

CardCvcElement

<template>
  <CardCvcElement />
</template>

Combined Example

<script setup>
import { loadStripe } from '@stripe/stripe-js'
import {
  CardCvcElement,
  CardExpiryElement,
  CardNumberElement,
  Elements,
  useElements,
  useStripe
} from 'vue-stripe'

const stripePromise = loadStripe('pk_test_xxx')
const stripe = useStripe()
const elements = useElements()

async function handleSubmit() {
  if (!stripe.value || !elements.value) {
    return
  }

  const cardNumber = elements.value.getElement(CardNumberElement)
  const cardExpiry = elements.value.getElement(CardExpiryElement)
  const cardCvc = elements.value.getElement(CardCvcElement)

  if (!cardNumber || !cardExpiry || !cardCvc) {
    return
  }

  const { error, paymentMethod } = await stripe.value.createPaymentMethod({
    type: 'card',
    card: cardNumber,
  })

  if (error) {
    console.error(error.message)
  }
  else {
    console.log('Payment method created:', paymentMethod.id)
  }
}
</script>

<template>
  <Elements :stripe="stripePromise">
    <form @submit.prevent="handleSubmit">
      <div class="card-inputs">
        <CardNumberElement />
        <div class="card-row">
          <CardExpiryElement />
          <CardCvcElement />
        </div>
      </div>
      <button type="submit">
        Pay
      </button>
    </form>
  </Elements>
</template>

<style scoped>
.card-inputs {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.card-row {
  display: flex;
  gap: 1rem;
}
</style>

Props

All card elements accept the same props:

PropTypeDescription
optionsCardElementOptionsConfiguration options for the card element. See available options.

Events

All card elements emit the same events:

EventDescription
@readyTriggered when the Element is fully rendered
@changeTriggered when card data changes (e.g., when there is an error)
@focusTriggered when the Element receives focus
@blurTriggered when the Element loses focus
@escapeTriggered when the escape key is pressed

Example with Validation

<script setup>
import { ref } from 'vue'
import { CardElement, useElements } from 'vue-stripe'

const elements = useElements()
const error = ref(null)

function handleChange(event) {
  if (event.error) {
    error.value = event.error.message
  }
  else {
    error.value = null
  }

  if (event.complete) {
    // All card fields are complete
    console.log('Card details complete')
  }
}
</script>

<template>
  <form>
    <CardElement @change="handleChange" />
    <div v-if="error" class="error">
      {{ error }}
    </div>
    <button type="submit">
      Pay
    </button>
  </form>
</template>

Styling Card Elements

You can customize the appearance of card elements using the options prop:

<template>
  <CardElement
    :options="{
      style: {
        base: {
          'fontSize': '16px',
          'color': '#424770',
          '::placeholder': {
            color: '#aab7c4',
          },
        },
        invalid: {
          color: '#9e2146',
        },
      },
    }"
  />
</template>

When to Use CardElement vs Individual Elements

  • Use CardElement when you want a simple, single-input solution
  • Use Individual Elements when you need more control over layout and styling

For detailed information about Card Elements and their usage, refer to the Stripe Card Element documentation.