Building complex interfaces with Stripe Elements

It all started with a Tweet by Muhammed Erdem where he showcased a proof of concept credit card form he had designed.

I was using the standard Stripe Elements input (pictured below) and challenged myself to implement the above design into a real application.

Default input for Stripe Elements

I started by copying the styles for the card and moving the Vue code to a single file component (Card.vue). After getting the original code working on Sitesauce I noticed the first problem: the code was using regular inputs to capture the credit card details and show them in the card while I needed to use Stripe Elements to be able to process payments to that card.

After digging through Stripe's documentation I found that just as there was a Card element that encapsulated the card number, expiry date, and CVC code there were individual CardNumber, CardExpiry and CardCvc elements that I could use.

My solution consisted of adding the inputs directly on the card. This involved updating the styling both on the card and on the elements (which you can do with the style & class options when creating it).

const cardNumber = elements.create('cardNumber', {
    classes: {
        base: 'card-item**number',
        focus: 'card-item**focus',
    style: {
        base: {
            color: '#ffffff',
            lineHeight: '1',
            fontFamily: '"Source Code Pro", monospace',
            fontSmoothing: 'antialiased',
            fontSize: '27px',
            fontWeight: '500',
            '::placeholder': {
                color: '#cbd5e0',
        invalid: {
            color: '#fa755a',
            iconColor: '#fa755a',
A video of the interface I ended up with