Skip to main content

Styling your forms with custom CSS

G
Written by Gavin Zuchlinski

Use the assistant to write CSS

Describe what you want in plain words — "make the appointment type blocks square instead of wide", "change font to Poppins and make the buttons dark green" — and it writes the CSS, checks which elements each rule would land on, and saves it to the form.

It is usually faster than writing the CSS by hand, and it knows the selectors on this page. If something it does isn't quite right, tell it what looks wrong and it will adjust.

The rest of this guide is for when you want to write the CSS yourself, or read and tweak what the Assistant produced.

Custom CSS lets you change anything about how your form looks that the Styles panel doesn't already cover: the shape and spacing of blocks, how times are laid out, a different font, a card treatment on class listings. It applies to the public form your clients see.

Where to put it

Open your form, then Styles → Advanced → Custom CSS.

The box highlights CSS as you type and saves on its own a moment after you stop. What you type is kept exactly as written; a checked copy is what gets served to clients. If anything was removed for safety it is listed underneath the box, so nothing disappears without telling you.

The Design tab beside the editor shows your CSS applied as you type, so you can work against a live preview. A few things don't appear there because they only exist on the real form: the Next and Submit buttons, the thank-you step, and anything that depends on a client moving through the form step by step. Everything else previews as it will look.

There is a 32,000 character limit.

Target the stable selectors

If you inspect a Breely form you will see class names like mb-4, text-gray-700 or choose-block. Don't style those. They are internal, they change whenever we touch that part of the product, and your CSS will quietly stop working one day.

Instead, target the data-breely-* attributes. These are a published contract: once one ships, we keep emitting it. Everything listed in this guide is one of them.

A rule looks like this:

.breely-form [data-breely-part='submit'] {     border-radius: 4px; }

There are four kinds of hook, and you combine them to say how broadly a rule should apply:

Hook

Picks out

[data-breely-part='...']

A named piece of the form — a label, an input, a block, a button

[data-breely-question-type='...']

Every question of one type, e.g. email, radio, scheduling

[data-breely-question='...']

One specific question, by its id

[data-breely-section='...']

One section of the form, by its id

So the same part can be styled everywhere, or in one place only:

/* Every selection block on the form */ .breely-form [data-breely-part='selection-block'] { }  /* Only the ones in scheduling questions */ .breely-form [data-breely-question-type='scheduling'] [data-breely-part='selection-block'] { }  /* Only the ones in one particular question */ .breely-form [data-breely-question='4821'] [data-breely-part='selection-block'] { }

This matters more than it looks. A part like selection-block is shared by appointment types, staff, add-ons, packages and gift certificates — so if you only want to change one of them, you have to name the question type or the question.

Selector reference

All of these are used as [data-breely-part='name'].

The page

Part

What it is

header

The band across the top holding the logo. Only present when a logo, header image or header colour is set

logo

The logo image inside that band

container

The centred column the whole form sits in. Style this for form width, padding or a card background

form-title

The form's name. Rendered twice, once for mobile and once for wider screens

progress

The "Step 2 of 4" row and progress circle

back

The Back link to the previous step

next

The Next button

submit

The final button — Submit, Pay or Confirm depending on the form

form-error

The error shown beside the submit button when submitting fails

Inside any question

Part

What it is

label

The question's label

required-marker

The red asterisk on a required question

description

Body text of a display question, or the terms text on an agree-to-terms question

control

The wrapper around the whole answer area. Style this for spacing or a border around the answer

input

The text box, textarea, dropdown or date field

option

One choice on a radio, checkbox, yes/no, dropdown or terms question

option-input

The radio button or checkbox itself

option-label

The text beside it

error

The validation message under the question

Questions also carry data-breely-required, data-breely-answered and data-breely-error while that state applies, and option carries data-breely-selected when picked.

Choosing what is being booked

Shared by appointment types, staff, add-ons, packages and gift certificates — name the question type to reach just one.

Part

What it is

selection-list

The container holding all the blocks

selection-block

One clickable block. This is the bordered box, so style it for shape, border, radius, padding and hover

selection-title

The name inside a block

selection-subtitle

The line under the name, holding an appointment type's duration

selection-price

The price. Rendered twice per block, one for narrow and one for wide screens, so setting display on it shows both

selection-description

The description inside a block

selection-image

The image inside a block

selection-action

The Add / Added button, on questions where several things can be picked

selection-group-heading

A category heading above a group of blocks

selection-selected

The collapsed block shown after a choice is made

selection-change

The button that reopens a collapsed block — Change, or Edit on the date and time

Dates and times

Part

What it is

availability

The white card holding the calendar and the times

calendar

The month grid

time-panel

The column beside the calendar

time-panel-heading

The chosen date, above the list of times

time-options

The container holding the time buttons. Style this to lay times out in columns

time-option

One bookable time. Carries data-breely-selected when chosen

timezone

The "Times shown in…" line

no-availability

The "No availability this month" message

date-navigation

The previous / next arrows

stepper

The minus / number / plus control for attendee or add-on quantity, with stepper-decrease, stepper-value and stepper-increase

The dates inside the calendar are the one exception to the attribute rule — the calendar only accepts class names, so dates use classes:

Class

Applies to

.breely-date

Every date

.breely-date-selected

The chosen date

.breely-date-unavailable

A date with nothing bookable

.breely-date-today

Today

Classes

Part

What it is

class-list

The grid or list of classes on offer

class-block

One class. Carries data-breely-selected when booked and data-breely-full when there are no spots

class-title

The class name

class-time

Its date and start time

class-duration

How long it runs, e.g. "1 hr". Absent if durations are turned off

class-resource

Who or what is running it. Absent if that is turned off

class-spots

"3 spots left" or "This is full"

class-image

The picture at the top of a class card

class-book

The Book / Selected / Join Waitlist button

class-calendar-day

One dated square in the month view. Carries data-breely-today and data-breely-unavailable

class-calendar-day-number

The date in the corner of a square

class-calendar-weekday

The Mon–Sun headings above the month grid

day-heading

One day column header in the weekly view

Client accounts and the thank-you step

Part

What it is

account-title

A heading such as "Register or Log in"

account-description

The text under it, and the "Logged in as" line

account-button

Register / Log in / Skip / Log out / My Account

thank-you-icon

The circled tick above the thank-you message

thank-you-title

The thank-you heading

thank-you-description

The message under it

thank-you-button

A button on the confirmation, such as Reschedule or Cancel

Finding the selector by pointing at it

You usually don't need the table above. While the Custom CSS box is open, hovering anything in the Design tab outlines it and shows the selector that reaches it.

Pick an element goes further: click it, then click anything on the form, and an empty rule for that thing is dropped in at your cursor, ready to fill in. The panel slides out of the way while you pick so you can see the whole form, and comes back with the new rule in place. Press Escape to stop without adding anything.

Above the box it also lists every selector that reaches what you picked — usually three:

[data-breely-part='selection-block']                                           every one on the form [data-breely-question-type='scheduling'] [data-breely-part='selection-block']  in this question type [data-breely-question='4821'] [data-breely-part='selection-block']             in this question

The broad one is what gets inserted. Copy one of the narrower ones instead if the rule is catching more than you meant.

Change the color in one place

Before you start overriding individual rules, try the theme variables. Most restyling is a colour or a size, and those are set once on the form root:

.breely-form {     --breely-color: #7a5af8;     --breely-color-light: #9b82fa;     --breely-color-lightest: #e7e0ff;     --breely-font-size: 17px;     --breely-font-size-sm: 13px; }

Variable

What it drives

--breely-color

Buttons, links, focus rings, selected states

--breely-color-light

Button hover

--breely-color-lightest

Light button fills, selected date backgrounds

--breely-font-size

Base body size

--breely-font-size-sm

Labels and small print

Overriding one of these replaces just that value and leaves everything derived from it consistent, which is much less work than chasing each element. You can also use them in your own rules — border-color: var(--breely-color) keeps a custom border in step with the rest of the theme.

Custom fonts: Google Fonts only

You can use any font on Google Fonts. Import it, then use it:

@import url('https://fonts.googleapis.com/css2?family=Inter&display=swap');  .breely-form {     font-family: Inter, sans-serif; }

fonts.googleapis.com is the only address an @import may point at, and it has to be https. An import pointing anywhere else is removed.

You don't need to put the @import at the top — it is moved there for you, so it works wherever you paste it.

@font-face does not work. Self-hosted and third-party font files are not allowed, so a font you have licensed and uploaded elsewhere can't be used here. Use the Google Fonts import instead, and always name a fallback (sans-serif, serif) after your font so text still renders if the font fails to load.

Your CSS only ever touches your form

Every rule you write is automatically rewritten to sit inside the form, under a wrapper called .breely-form. You don't have to do anything to make that happen — write selectors however you like.

So this:

body { font-size: 18px; }

is served as this:

.breely-form { font-size: 18px; }

Two consequences worth knowing:

  • The page background behind the form is not reachable. It sits outside the wrapper. Set it from the Styles panel instead.

  • The "Powered by Breely" mark cannot be hidden or moved. It deliberately sits outside the wrapper, so no selector reaches it.

The wrapper itself carries attributes you can style against:

Attribute

Values

data-breely-state

filling, payment, thank-you

data-breely-step

which step the client is on, starting at 1

data-breely-embedded

present when the form is embedded in your own site

data-breely-object

the form's id

/* Strip the padding when the form is embedded in our website */ .breely-form[data-breely-embedded] [data-breely-part='container'] {     padding: 0; }

What gets removed, and why

Your CSS is checked before it is served and for security reasons some rules may be removed. Anything removed is listed under the editor. The rest of your CSS still applies.

Removed

Why

@import from anywhere but Google Fonts

Loads a stylesheet from another server

@font-face

Use a Google Fonts @import instead

url(...) pointing outside Breely

External URLs are removed

image-set(), element(), cross-fade()

External URLs are removed

expression(), behavior, -moz-binding

Legacy ways of running scripts from CSS

@charset, @namespace

No effect once your CSS is scoped to the form

Nesting with &

Can't be scoped reliably

Two at-rules deserve their own warning. @layer, @container and @scope are not supported, and including one means none of your CSS is applied — not just that rule. If your styling suddenly does nothing at all, check for one of these first.

@media, @supports and @keyframes all work normally.

Background images do work

They just have to be hosted by us. Upload the image to the form first, then point at the /view-image/... address it is given:

.breely-form [data-breely-part='container'] {     background-image: url(/view-image/image-abc123); }

A data:image/... URI works too, if you'd rather inline a small image.

Examples to copy

Square appointment-type blocks in a two-column grid

The default blocks are wide rectangles. This makes them square tiles, two across:

.breely-form [data-breely-question-type='scheduling'] [data-breely-part='selection-list'] {     display: grid;     grid-template-columns: 1fr 1fr;     gap: 12px; }  .breely-form [data-breely-question-type='scheduling'] [data-breely-part='selection-block'] {     aspect-ratio: 1;     border-radius: 12px;     padding: 16px; }

Naming the question type matters here — without it, add-ons and packages become squares too.

A squarer, flatter submit button

.breely-form [data-breely-part='submit'] {     border-radius: 4px;     text-transform: uppercase;     letter-spacing: 0.08em;     font-weight: 600; }

Times in two columns instead of one list

.breely-form [data-breely-part='time-options'] {     display: grid;     grid-template-columns: 1fr 1fr;     gap: 8px; }  .breely-form [data-breely-part='time-option'][data-breely-selected] {     background: var(--breely-color-lightest); }

Circle the selected date, dim the unavailable ones

.breely-form .breely-date-selected {     background: var(--breely-color);     color: #fff;     border-radius: 999px; }  .breely-form .breely-date-unavailable {     opacity: 0.35; }

Class listings as cards

.breely-form [data-breely-part='class-block'] {     border: 1px solid #e6e6e6;     border-radius: 12px;     box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);     overflow: hidden; }  .breely-form [data-breely-part='class-block'][data-breely-full] {     opacity: 0.5; }  .breely-form [data-breely-part='class-title'] {     font-weight: 600; }

Bigger tap targets on choice questions

.breely-form [data-breely-part='option'] {     padding: 10px 12px;     border: 1px solid #e0e0e0;     border-radius: 8px;     margin-bottom: 6px; }  .breely-form [data-breely-part='option'][data-breely-selected] {     border-color: var(--breely-color); }

Style one question and nothing else

Use the question id, which the picker gives you:

.breely-form [data-breely-question='4821'] [data-breely-part='label'] {     font-size: 20px;     font-weight: 600; }

A narrower form on wide screens

@media (min-width: 900px) {     .breely-form [data-breely-part='container'] {         max-width: 560px;     } }

When something isn't working

None of my CSS is applying. Check for @layer, @container or @scope. Any one of them stops the whole stylesheet, not just that rule.

One rule isn't applying. Check the list under the editor first — if it was removed for safety it will say so. Otherwise you are probably targeting a class name rather than a data-breely-* hook; use Pick an element to get the right selector.

It works in the preview but not on the real form, or the other way round. A few things only exist on the live form: the Next and Submit buttons, the thank-you step, and anything that depends on which step a client is on. They won't show in the Design tab.

My rule is changing more than I wanted. Several question types share the same parts — selection-block covers appointment types, staff, add-ons, packages and gift certificates. Add [data-breely-question-type='...'] or [data-breely-question='...'] in front of it.

I can't hide the "Powered by Breely" mark. That's deliberate; it sits outside the area your CSS can reach.

I want this on all my forms. Save the form's styles as a theme and apply it to the others. Editing the theme afterwards updates every form using it. Styling an individual form that uses a theme changes only that form, and you are then offered the choice of saving it as a new theme or pushing it back into the one you started from.

Still stuck

Describe what you want to the Assistant and let it write the rule. It can also look at the CSS already on the form and tell you what each rule is landing on, which is often faster than working it out by hand.

Did this answer your question?