Skip to main content
Align the checkout form with your brand and design system. Consistent styling improves user trust, reduces friction, and keeps the experience accessible across devices. The PayNext SDK supports two complementary approaches:
  • CSS-in-JS: Apply React CSSProperties directly for precise control
  • CSS classes: Use custom classes for state styling, animations, and responsive design

CSS-in-JS Styling

Direct React CSS properties for precise control over form elements.

CSS Class Names

Custom classes for advanced styling with pseudo-selectors and responsive design.

Implement Brand Styles

Integrate the checkout form with your design system using CSS custom properties:
const brandStyles: StylesConfig = {
  Input: {
    field: {
      styles: {
        fontFamily: 'var(--font-primary)',
        backgroundColor: 'var(--surface-primary)',
        borderColor: 'var(--border-default)',
        borderRadius: 'var(--radius-md)'
      }
    }
  },
  SubmitButton: {
    styles: {
      backgroundColor: 'var(--color-primary)',
      borderRadius: 'var(--radius-md)'
    }
  }
}
Prefer CSS custom properties (var(...)) to keep styles consistent with your design system, enable easy theming, and minimize code changes.
CSS custom properties enable dynamic theming without JavaScript and generally perform better than heavy inline style changes.

Configure StylesConfig

The StylesConfig interface provides styling options for all checkout form elements.
Define your StylesConfig objects and pass them into the styles property when calling checkout.mount('element-id', { ...config, styles }), following the pattern in Mount the Checkout.

Core Elements

Input
InputStyles
Configure card number, expiry, CVC, cardholder name, etc.
SubmitButton
ISubmitButtonStyles
Styles for the payment submit button.

Digital Wallet Buttons

ApplePayButton
IApplePayButtonStyles
Apple Pay button styling following Apple’s guidelines.
PayPalButton
IPayPalButtonStyles
PayPal button styling following PayPal specifications.
GooglePayButton
IGooglePayButtonStyles
Google Pay button styling.
CashAppButton
HTMLStyles
Cash App Pay button styling (Stripe wallets only).
Match the default 40px height when possible so the button aligns with other wallet controls. Increase padding for better tap targets on mobile.
WalletButton
HTMLStyles
Styles for generic wallet buttons (e.g., custom wallet implementations).
BraintreeButton
HTMLStyles
Styles for Braintree payment buttons.
BackButton
HTMLStyles
Styles for the back button wrapper that sits above the card form (hidden when the default variant hides the control). Defaults include a 30x30px flex container with centered content, a #f4f4f5 background, and 8px border radius.
cssVariables
CSSVariablesConfig
Override the SDK design tokens directly from styles without adding external stylesheets. Values apply to the checkout root element and merge with the active theme.
Leave any variable undefined to keep the theme default. See Theme Support › CSS Variables for the complete token list and defaults.
css-variables.constant.ts
import { PayNextCheckout, type StylesConfig, type CSSVariablesConfig } from '@paynext/sdk'

const brandTokens: StylesConfig = {
  cssVariables: {
    '--paynext-sdk-bg': '#0b1220',
    '--paynext-sdk-text': '#e2e8f0',
    '--paynext-sdk-button-bg': 'linear-gradient(135deg, #06b6d4, #2563eb)',
    '--paynext-sdk-border-radius': '14px',
    '--paynext-sdk-input-focus-shadow': 'none' // Disable default focus ring
  }
}

const checkout = new PayNextCheckout()
await checkout.mount('checkout-container', {
  ...config,
  styles: brandTokens,
})
Use cssVariables for theme-level changes and component-level styles for fine-grained control. They work together—component styles take precedence over CSS variables.
Element-level styling properties support both styles (React CSSProperties) and className, while cssVariables overrides global tokens for the entire checkout.
Wallet button styling must also follow each processor’s brand guidelines (Apple, PayPal, Google) to remain compliant.

Target Elements with External CSS

The SDK adds data-paynext-* attributes to key elements, enabling CSS targeting from external stylesheets without modifying JavaScript:
AttributeElement
data-paynext-component="checkout"Main checkout container
data-paynext-version="1.0"SDK version attribute
data-paynext-element="card-number-wrapper"Card number field outer wrapper
data-paynext-element="card-number-container"Card number input container (receives focus styles)
data-paynext-element="card-number-input"Card number input field
data-paynext-element="card-number-label"Card number label
data-paynext-element="card-number-error-label"Card number validation error
data-paynext-element="card-name-wrapper"Cardholder name field outer wrapper
data-paynext-element="card-name-container"Cardholder name input container (receives focus styles)
data-paynext-element="card-name-input"Cardholder name input field
data-paynext-element="card-name-label"Cardholder name label
data-paynext-element="card-name-error-label"Cardholder name validation error
data-paynext-element="submit-button"Submit/Pay button
external-styles.css
/* Target the checkout container for CSS variable overrides */
[data-paynext-component="checkout"] {
  --paynext-sdk-border: #e5e7eb;
  --paynext-sdk-border-focus: #6366f1;
  --paynext-sdk-input-focus-shadow: 0 0 0 3px rgba(99, 102, 241, 0.15);
}

/* Target specific input containers */
[data-paynext-element="card-number-container"],
[data-paynext-element="card-name-container"] {
  transition: border-color 0.2s ease;
}

/* Style the submit button */
[data-paynext-element="submit-button"] {
  transition: transform 0.1s ease;
}

[data-paynext-element="submit-button"]:hover {
  transform: translateY(-1px);
}
Combine external CSS with cssVariables for maximum flexibility. Use external CSS for media queries and pseudo-states, and cssVariables for brand tokens.

Use Advanced Styling Patterns

These examples demonstrate real-world styling patterns used by production applications. Each example includes performance optimizations and accessibility considerations.
All examples below show only the StylesConfig object. Pass it to checkout.mount('element-id', { ...config, styles }) as shown in Mount the Checkout.
css-variables-only.constant.ts
import { type StylesConfig, type CSSVariablesConfig } from '@paynext/sdk'

// Theme-level customization using only CSS variables
const cssVariablesStyles: StylesConfig = {
  cssVariables: {
    '--paynext-sdk-input-focus-shadow': 'none',
    '--paynext-sdk-border': '#e5e7eb',
    '--paynext-sdk-border-focus': '#6366f1',
    '--paynext-sdk-input-bg': '#f9fafb',
    '--paynext-sdk-input-text': '#1f2937',
    '--paynext-sdk-button-bg': '#6366f1',
    '--paynext-sdk-button-text': '#ffffff',
    '--paynext-sdk-button-hover-opacity': '0.9',
    '--paynext-sdk-border-radius': '8px'
  }
}

CSS variables are the simplest way to customize the checkout. Use them for theme-level changes without touching component styles.

Review Complete Styling Example

Here’s a comprehensive example that demonstrates styling all available components. This configuration is production-ready and includes:
  • Accessibility compliance: standards
  • Performance optimization: Hardware-accelerated transitions
  • Cross-browser compatibility: Tested across major browsers
  • Mobile responsiveness: Touch-friendly targets and spacing
complete-styling.constant.ts
import { type PayNextConfig, type StylesConfig, type CSSVariablesConfig } from '@paynext/sdk'

const completeStyles: StylesConfig = {
  // Theme-level tokens (optional, for global consistency)
  cssVariables: {
    '--paynext-sdk-border': '#e5e7eb',
    '--paynext-sdk-border-focus': '#3b82f6',
    '--paynext-sdk-input-focus-shadow': '0 0 0 3px rgba(59, 130, 246, 0.15)',
    '--paynext-sdk-border-radius': '8px'
  },

  // Input field styling
  Input: {
    field: {
      styles: {
        backgroundColor: '#ffffff',
        border: '2px solid #e5e7eb',
        borderRadius: '8px',
        padding: '12px 16px',
        fontSize: '16px',
        fontFamily: 'system-ui, sans-serif',
        transition: 'border-color 0.2s ease'
      },
      className: 'focus:border-blue-500 focus:outline-none'
    },
    label: {
      styles: {
        color: '#374151',
        fontSize: '14px',
        fontWeight: '600',
        marginBottom: '6px',
        display: 'block'
      }
    },
    error: {
      styles: {
        color: '#ef4444',
        fontSize: '13px',
        marginTop: '4px'
      },
      className: 'flex items-center gap-1'
    },
    container: {
      styles: { marginBottom: '16px' },
      focus: 'ring-2 ring-blue-500 ring-opacity-20'
    },
    placeholder: {
      styles: {
        color: '#9ca3af',
        fontSize: '16px'
      }
    }
  },

  // Submit button styling
  SubmitButton: {
    styles: {
      backgroundColor: '#3b82f6',
      color: 'white',
      border: 'none',
      borderRadius: '8px',
      padding: '16px 24px',
      fontSize: '16px',
      fontWeight: '600',
      width: '100%',
      cursor: 'pointer',
      transition: 'all 0.2s ease'
    },
    className: 'hover:bg-blue-700 active:scale-98 disabled:opacity-50'
  },

  // Apple Pay button styling
  ApplePayButton: {
    styles: {
      type: 'buy',
      style: 'black',
      borderRadius: 8,
      size: 'medium'
    }
  },

  // PayPal button styling
  PayPalButton: {
    styles: {
      layout: 'horizontal',
      color: 'gold',
      shape: 'rect',
      label: 'checkout',
      height: 48
    }
  },

  // Google Pay button styling
  GooglePayButton: {
    styles: {
      type: 'buy',
      color: 'default',
      borderRadius: 8,
      size: 'medium'
    }
  },

  // Generic wallet button styling
  WalletButton: {
    styles: {
      backgroundColor: '#f9fafb',
      color: '#374151',
      border: '1px solid #d1d5db',
      borderRadius: '8px',
      padding: '12px 16px',
      fontSize: '14px',
      fontWeight: '500',
      cursor: 'pointer',
      transition: 'all 0.2s ease'
    },
    className: 'hover:bg-gray-50 hover:border-gray-400'
  },

  // Braintree button styling
  BraintreeButton: {
    styles: {
      backgroundColor: '#6366f1',
      color: 'white',
      border: 'none',
      borderRadius: '8px',
      padding: '14px 20px',
      fontSize: '15px',
      fontWeight: '600',
      cursor: 'pointer'
    },
    className: 'hover:bg-indigo-700 focus:ring-4 focus:ring-indigo-100'
  },

  // Cash App Pay button styling
  CashAppButton: {
    styles: {
      backgroundColor: '#14d13a',
      color: '#ffffff',
      border: 'none',
      borderRadius: '12px',
      fontSize: '16px',
      fontWeight: '600',
      height: '40px',
      cursor: 'pointer',
      transition: 'background-color 0.2s ease'
    },
    className: 'hover:bg-[#0ead2e] focus:ring-4 focus:ring-green-100'
  },

  // Back button styling
  BackButton: {
    styles: {
      width: '30px',
      height: '30px',
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      backgroundColor: '#f4f4f5',
      borderRadius: '8px'
    },
    className: 'text-gray-700'
  }
}

const completeConfig: PayNextConfig = {
  clientToken: 'your-client-token',
  environment: 'sandbox',
  apiVersion: 'v1',
  styles: completeStyles,
  /* other options */
}

// When mounting (see Getting Started "Mount the Checkout" section):
const checkout = new PayNextCheckout()
await checkout.mount('checkout-container', completeConfig)
This production-ready example includes compliance: 16px min text, 44px touch targets, ≥4.5:1 contrast, and visible focus states.

Apply Best Practices

Use CSS custom properties for design system integration, enabling centralized management, easy theme switching, and team collaboration. For theme-level tokens, prefer cssVariables over inline styles.
For older browsers, provide fallback values: backgroundColor: 'var(--color-primary, #3b82f6)'

Follow Common Styling Patterns

Responsive Design

Design your checkout form with mobile users in mind first, then enhance for larger screens:
mobile-first.constant.ts
const responsiveStyles: StylesConfig = {
  Input: {
    field: {
      styles: {
        fontSize: '16px', // Prevents zoom on iOS
        padding: '14px 16px', // Larger touch targets
        borderRadius: '8px'
      },
      className: 'w-full sm:max-w-md' // Full width on mobile, constrained on desktop
    }
  },
  SubmitButton: {
    styles: {
      padding: '16px 24px', // Generous padding for touch
      fontSize: '16px',
      width: '100%'
    },
    className: 'sm:w-auto sm:min-w-[200px]' // Full width on mobile, auto on desktop
  }
}
Ensure your styling meets accessibility standards:
accessible.constant.ts
const accessibleStyles: StylesConfig = {
  Input: {
    field: {
      styles: {
        fontSize: '16px', // Minimum readable size
        padding: '12px 16px',
        border: '2px solid #d1d5db', // Visible border
        backgroundColor: '#ffffff' // High contrast
      },
      className: 'focus:ring-4 focus:ring-blue-500 focus:ring-opacity-50' // Clear focus indicator
    },
    error: {
      styles: {
        color: '#dc2626', // High contrast red
        fontSize: '14px'
      },
      className: 'flex items-center gap-2' // Space for error icon
    },
    placeholder: {
      styles: {
        color: '#6b7280', // Sufficient contrast ratio
        fontSize: '16px' // Same size as input text
      }
    }
  },
  SubmitButton: {
    styles: {
      minHeight: '44px', // Minimum touch target size
      fontSize: '16px',
      fontWeight: '600'
    },
    className: 'focus:ring-4 focus:ring-offset-2' // Clear focus ring
  }
}
quick checks: 16px min text, ≥4.5:1 contrast, visible focus ring, 44px touch targets, no color-only semantics.
Optimize your styles for better performance:
optimized.constant.ts
const optimizedStyles: StylesConfig = {
  Input: {
    field: {
      styles: {
        // Use CSS custom properties for dynamic theming
        backgroundColor: 'var(--input-bg, #ffffff)',
        borderColor: 'var(--input-border, #d1d5db)',
        // Prefer transform over changing layout properties
        transition: 'border-color 0.2s ease, box-shadow 0.2s ease'
      }
    }
  },
  SubmitButton: {
    styles: {
      // Use will-change for animations
      willChange: 'transform',
      transition: 'transform 0.1s ease'
    },
    className: 'hover:scale-105 active:scale-95' // Hardware-accelerated transforms
  }
}

Brand Integration

Color Consistency

Use your brand colors consistently across all payment elements to maintain visual cohesion.

Typography Matching

Match your website’s typography by using the same font families and weights in the checkout form.

Border Radius

Maintain consistent border radius values that match your site’s design language.

Animation Timing

Use consistent transition durations (typically 0.2s-0.3s) for a cohesive user experience.

Common Styling Patterns

dark-mode.constant.ts
import { type StylesConfig } from '@paynext/sdk'

// Option 1: Use built-in dark theme with CSS variable overrides
const darkModeWithVariables: StylesConfig = {
  cssVariables: {
    '--paynext-sdk-bg': '#1a1a1a',
    '--paynext-sdk-text': '#ffffff',
    '--paynext-sdk-border': '#404040',
    '--paynext-sdk-border-focus': '#8b5cf6',
    '--paynext-sdk-input-bg': '#2d2d2d',
    '--paynext-sdk-input-text': '#f5f5f5',
    '--paynext-sdk-input-focus-shadow': '0 0 0 2px rgba(139, 92, 246, 0.3)',
    '--paynext-sdk-button-bg': '#8b5cf6',
    '--paynext-sdk-button-hover-opacity': '0.85'
  }
}

// Option 2: Component-level dark styling
const darkModeStyles: StylesConfig = {
  Input: {
    field: {
      styles: {
        backgroundColor: '#1f2937',
        borderColor: '#374151',
        color: '#f9fafb'
      },
      className: 'focus:border-blue-400 focus:ring-blue-400'
    },
    label: {
      styles: { color: '#e5e7eb' }
    },
    error: {
      styles: { color: '#f87171' }
    }
  },
  SubmitButton: {
    styles: {
      backgroundColor: '#3b82f6',
      color: '#ffffff'
    },
    className: 'hover:bg-blue-600'
  }
}
Prefer cssVariables for dark mode. See Theme Support for more presets.