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 |
| A named piece of the form — a label, an input, a block, a button |
| Every question of one type, e.g. |
| One specific question, by its id |
| 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 |
| The band across the top holding the logo. Only present when a logo, header image or header colour is set |
| The logo image inside that band |
| The centred column the whole form sits in. Style this for form width, padding or a card background |
| The form's name. Rendered twice, once for mobile and once for wider screens |
| The "Step 2 of 4" row and progress circle |
| The Back link to the previous step |
| The Next button |
| The final button — Submit, Pay or Confirm depending on the form |
| The error shown beside the submit button when submitting fails |
Inside any question
Part | What it is |
| The question's label |
| The red asterisk on a required question |
| Body text of a display question, or the terms text on an agree-to-terms question |
| The wrapper around the whole answer area. Style this for spacing or a border around the answer |
| The text box, textarea, dropdown or date field |
| One choice on a radio, checkbox, yes/no, dropdown or terms question |
| The radio button or checkbox itself |
| The text beside it |
| 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 |
| The container holding all the blocks |
| One clickable block. This is the bordered box, so style it for shape, border, radius, padding and hover |
| The name inside a block |
| The line under the name, holding an appointment type's duration |
| The price. Rendered twice per block, one for narrow and one for wide screens, so setting |
| The description inside a block |
| The image inside a block |
| The Add / Added button, on questions where several things can be picked |
| A category heading above a group of blocks |
| The collapsed block shown after a choice is made |
| The button that reopens a collapsed block — Change, or Edit on the date and time |
Dates and times
Part | What it is |
| The white card holding the calendar and the times |
| The month grid |
| The column beside the calendar |
| The chosen date, above the list of times |
| The container holding the time buttons. Style this to lay times out in columns |
| One bookable time. Carries |
| The "Times shown in…" line |
| The "No availability this month" message |
| The previous / next arrows |
| The minus / number / plus control for attendee or add-on quantity, with |
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 |
| Every date |
| The chosen date |
| A date with nothing bookable |
| Today |
Classes
Part | What it is |
| The grid or list of classes on offer |
| One class. Carries |
| The class name |
| Its date and start time |
| How long it runs, e.g. "1 hr". Absent if durations are turned off |
| Who or what is running it. Absent if that is turned off |
| "3 spots left" or "This is full" |
| The picture at the top of a class card |
| The Book / Selected / Join Waitlist button |
| One dated square in the month view. Carries |
| The date in the corner of a square |
| The Mon–Sun headings above the month grid |
| One day column header in the weekly view |
Client accounts and the thank-you step
Part | What it is |
| A heading such as "Register or Log in" |
| The text under it, and the "Logged in as" line |
| Register / Log in / Skip / Log out / My Account |
| The circled tick above the thank-you message |
| The thank-you heading |
| The message under it |
| 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 |
| Buttons, links, focus rings, selected states |
| Button hover |
| Light button fills, selected date backgrounds |
| Base body size |
| 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 |
|
|
| which step the client is on, starting at 1 |
| present when the form is embedded in your own site |
| 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 |
| Loads a stylesheet from another server |
| Use a Google Fonts |
| External URLs are removed |
| External URLs are removed |
| Legacy ways of running scripts from CSS |
| 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.
