WWooshPayment docs
Checkout

Custom checkout CSS

Extend the checkout with custom CSS. Automatic sanitization to block XSS, MITM and payment flow bypass.

2 min read

TLDR: from the dashboard you can inject custom CSS into the checkout to align it pixel-perfectly to your brand. Below: common selectors, what our sanitizer blocks, and ready-to-use snippets.

Where

Dashboard โ†’ Checkout โ†’ Custom CSS (editor at the bottom of the page). Available to all merchants, no plan gating.

What you can do

Work with the standard selectors of the classes we expose in the checkout markup. Examples:

Change font

body {
  font-family: 'Helvetica Neue', -apple-system, sans-serif;
}

External @font-face declarations are blocked by the sanitizer (see below). Use system fonts, or load the font on your store and declare it via @import on a domain you control โ€” it'll still be stripped. For now: stick to system fonts.

Rounded Pay button

button[type="submit"] {
  border-radius: 999px;
  font-weight: 700;
}

Flat cards

.card, .section {
  border: none;
  box-shadow: 0 1px 2px rgba(0,0,0,0.06);
  background-color: #FAFAFA;
}

Apple-style inputs

input {
  border: 1px solid #D1D5DB;
  border-radius: 12px;
}
input:focus {
  border-color: #000;
  box-shadow: 0 0 0 4px rgba(0,0,0,0.04);
}

Hide elements on mobile

@media (max-width: 640px) {
  .trust-badges { display: none; }
}

What the sanitizer blocks

Our sanitizeCustomCss strips these patterns at runtime (for security, no errors on save):

PatternBehavior
url(...) of any kindReplaced with url("about:blank") โ€” closes off data:/file:/extension/font-face vectors
@import, @charset, @font-face, @namespace, @document, @supports url()Completely removed
expression(...)Blocked (legacy IE XSS)
[attr=...] selectorsBlocked (including aria-/data-* set by autofill)
:has(), :is(), :where()Blocked (can synthesize indirect matches on attributes)
CSS variables that cascade url() (--x: url(...))Blocked
javascript: schemeStripped

This is a runtime blacklist: CSS is saved as-is but the client sanitizes it before injecting it into the checkout's <style>.

Best practices

  • Never override the submit button or the Whop iframe: you risk breaking the payment flow
  • !important everywhere makes CSS hard to maintain. Use proper specificity
  • Always test on 375px mobile (iPhone SE): the checkout is mobile-first
  • infinite animations drain mobile battery

Test

  1. Edit the CSS in Dashboard โ†’ Checkout โ†’ Custom CSS โ†’ Save
  2. Open your test checkout in incognito (e.g. via onboarding "Preview" or by clicking a product in your store)
  3. DevTools โ†’ Toggle device toolbar โ†’ iPhone SE to validate mobile
  4. Verify that:
    • Payment button โ‰ฅ 44px tall (touch target)
    • Inputs aren't pushed outside the viewport
    • Order summary is readable

Rollback

If you break the checkout (e.g. CSS that hides the Pay button):

  • Dashboard โ†’ Checkout โ†’ empty the custom CSS field โ†’ Save