Docs
API 2026-05-27.dahlia Dashboard

Payments

The payment form's themes and variables.

The payment form is a frame of Fluveo's, so the CSS of your page does not reach it. Its look is set in code, with the appearance option of fluveo.elements(): a theme, the variables that each change one value of it, where the labels go, how the fields join and whether the form animates. Every part is optional. Payment Element explains the form itself.

The payment form three times, side by side, with a test card typed in: the fluveo theme, light with bordered fields; the night theme, dark; and the flat theme, with filled fields and no border.
The three themes

Themes#

A theme is a whole look with a name: every color, corner, border and shadow of the form at once. theme takes three names, and the form has "fluveo" when you pass none. Pick the theme that suits the background of your page, then change single values with variables.

Each photograph on this page was taken with a test key, so it shows the test mode line under the fields.

fluveo

The default, for a light page: light fields with a thin border and a soft shadow.

checkout.js
const fluveo = Fluveo("pk_test_...");
const elements = fluveo.elements({
  clientSecret,
  appearance: { theme: "fluveo" },
});
const paymentElement = elements.create("payment");
paymentElement.mount("#payment-element");
The payment form in the fluveo theme, with a test card typed in: light fields, each with a thin border.
The fluveo theme

night

For a dark page: dark fields with light text. The photograph shows it on a dark background.

checkout.js
const fluveo = Fluveo("pk_test_...");
const elements = fluveo.elements({
  clientSecret,
  appearance: { theme: "night" },
});
const paymentElement = elements.create("payment");
paymentElement.mount("#payment-element");
The payment form in the night theme on a dark background, with a test card typed in: dark fields with light text.
The night theme

flat

Filled fields with no border and no shadow, taller and with rounder corners.

checkout.js
const fluveo = Fluveo("pk_test_...");
const elements = fluveo.elements({
  clientSecret,
  appearance: { theme: "flat" },
});
const paymentElement = elements.create("payment");
paymentElement.mount("#payment-element");
The payment form in the flat theme, with a test card typed in: filled fields with round corners and no border.
The flat theme

Variables#

A variable changes one value of the theme, and every part of the form that uses that value follows it. A variable you leave out keeps the theme's value. Each value is a text, written as CSS writes it, of the variable's kind: a color, a length or a font family. The reference lists each variable's kind.

  • colorPrimary: the outline and the ring of the field in focus, the selected tab, and the open row of an accordion with its radio button.
  • colorBackground: the surface of the fields, the tabs and the accordion rows. The labels and the error lines sit on your own page.
  • colorText: what the buyer types, and a label above its field.
  • colorTextSecondary: a tab that is not selected, a floating label and the icons inside the fields.
  • colorTextPlaceholder: the placeholders.
  • colorDanger: an error line, and the outline of the field it is about.
  • fontFamily: the font of the form's labels, tabs, fields and messages.
  • fontSizeBase: the size that the labels, the tabs and the error lines are worked out from.
  • spacingUnit: the padding inside the fields and the tabs, and the gaps between them.
  • borderRadius: the corners of the fields, the tabs and the accordion rows.
checkout.js
const fluveo = Fluveo("pk_test_...");
const elements = fluveo.elements({
  clientSecret,
  appearance: {
    variables: {
      colorPrimary: "#0f766e",
      colorBackground: "#e0f2f1",
      spacingUnit: "4px",
      borderRadius: "10px",
    },
  },
});
const paymentElement = elements.create("payment");
paymentElement.mount("#payment-element");
The empty payment form with four variables set: the Card tab in a store's own main color, tinted fields, more room inside each field and rounder corners.
Four variables on the default theme

The default of each variable in each theme:

Variable"fluveo""night""flat"
colorPrimary#2961b2#6494db#2961b2
colorBackground#ffffff#1c1917#f2f2ee
colorText#1c1917#f4f2eb#1c1917
colorTextSecondary#57534d#d6d3d1#57534d
colorTextPlaceholder#79716b#a6a09b#57534d
colorDanger#c03f34#de8d87#c03f34
fontFamilysystem-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serifsystem-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serifsystem-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif
fontSizeBase16px16px16px
spacingUnit2px2px2px
borderRadius5px5px12px

Labels#

labels says where the label of each field goes.

  • "above": over its field.
  • "floating": inside its field. The label rests where the placeholder would be, so the form draws no placeholder, and it moves to the top of the field when the field takes the focus or holds a value.
  • "auto", the default: floating with condensed inputs, above with spaced ones.
checkout.js
const fluveo = Fluveo("pk_test_...");
const elements = fluveo.elements({
  clientSecret,
  appearance: { labels: "floating" },
});
const paymentElement = elements.create("payment");
paymentElement.mount("#payment-element");
The payment form with floating labels and a test card typed in: each label sits small at the top of its field, above the value.
Floating labels, once the fields hold a value

Inputs#

inputs says how the fields sit together. With "spaced", the default, each field is a box of its own. With "condensed" the fields are joined in one block, with one line between two of them in the themes that draw a border, and the lines that say what is wrong show under the block, as Errors describes. Labels left at "auto" float in a condensed block.

checkout.js
const fluveo = Fluveo("pk_test_...");
const elements = fluveo.elements({
  clientSecret,
  appearance: { inputs: "condensed" },
});
const paymentElement = elements.create("payment");
paymentElement.mount("#payment-element");
The empty payment form with condensed inputs: the five fields joined in one block, each label inside its field.
Condensed inputs, empty

Animations#

The form moves a little: a field changes state over a short moment, a floating label slides to its place, the loading placeholder shimmers and the form fades in over it. disableAnimations: true stops all of it. The form also stops by itself for a buyer whose device asks for reduced motion, so set this only when your own page never animates.

checkout.js
const fluveo = Fluveo("pk_test_...");
const elements = fluveo.elements({
  clientSecret,
  appearance: { disableAnimations: true },
});
const paymentElement = elements.create("payment");
paymentElement.mount("#payment-element");

The text inside the card fields#

The card number, the expiration date and the security code are each a frame of their own inside the form, so the form's style does not reach them either. The form hands them four values of its look when it mounts, and again after each elements.update(): the font family, the text size, the text color and the placeholder color. So fontFamily, fontSizeBase, colorText and colorTextPlaceholder reach what the buyer types.

Two things to know. fontFamily names fonts the buyer's device has: the form loads no font file. And what the buyer types is never drawn smaller than the default fontSizeBase, so that a phone does not zoom the page in when a field takes the focus: a smaller base shrinks the labels, the tabs and the error lines only.

checkout.js
const fluveo = Fluveo("pk_test_...");
const elements = fluveo.elements({
  clientSecret,
  appearance: {
    variables: {
      fontFamily: "Georgia, serif",
      fontSizeBase: "18px",
      colorText: "#1e3a8a",
    },
  },
});
const paymentElement = elements.create("payment");
paymentElement.mount("#payment-element");
The payment form with a test card typed in a serif font, larger and in a store's own text color, in the card fields as in the ZIP code.
The card fields follow the font, the size and the text color

Change it live#

elements.update() changes the look of a form that is already on the page, with no reload: for a switch between a light and a dark page, or a preview of your own. Each call replaces the appearance whole, and a part the new object leaves out goes back to its default, so build the whole object each time.

checkout.js
const fluveo = Fluveo("pk_test_...");
const dark = window.matchMedia("(prefers-color-scheme: dark)");
const look = () => ({
  theme: dark.matches ? "night" : "fluveo",
  labels: "floating",
});
const elements = fluveo.elements({ clientSecret, appearance: look() });
const paymentElement = elements.create("payment");
paymentElement.mount("#payment-element");
dark.addEventListener("change", () => {
  elements.update({ appearance: look() });
});

What is refused#

Nothing is ignored in silence. A name or a value that appearance does not take throws a FluveoIntegrationError at the call, in fluveo.elements() and in elements.update() alike, and its message names what you passed.

You passIt throws
An appearance that is not an object, or a name in it that the script does not know, such as colorsoption_not_supported
A theme, a labels or an inputs outside its list, or a disableAnimations that is not true or falseoption_not_supported
A name in variables other than the ten aboveoption_not_supported
A variable's value that is not a text, such as the number 4appearance_value_invalid
A color that CSS does not have, or var(), url(), inherit or currentColor in its placeappearance_value_invalid
A length with no unit, other than "0", in a unit other than px, rem or em, or with more than three digits or two decimalsappearance_value_invalid
A font family with a url() in it, or longer than 200 charactersappearance_value_invalid
appearance in element.update()option_not_supported: it goes to elements.update()