The Unified Registration Page is coming soon, stay tuned for updates!
CSS and Javascript for the New Unified Registration Page
These are the CSS classes and element IDs you can use when creating Custom CSS and Javascript for the new Unified Registration Page.
Applies to: the events with the unified registration form enabled. Events on the classic flow use different class names, so this list does not apply to them.
Covers: the attendee checkout, host / staff checkout, embedded and widget checkout, and the order-form preview. All of these render the same form.
Scope your rules: start every selector with
.registration-formso it can't affect other parts of the page.
.registration-form .registration-field__label { font-weight: 600; }
Form structure
The form contains one section per person: the buyer, each attendee, and each add-on. Every section is an .attendee-form with its own header and body.
Class | Element |
| Outer wrapper of the whole form |
| Form header |
| Parts of the form header |
| "Sign in" prompt, shown to buyers who aren't logged in |
| Sign-in prompt text and button |
| One section (buyer, attendee or add-on) |
| The buyer's section |
| A section that can be collapsed |
| A section that is currently collapsed |
| Section header |
| Section title and right-hand area |
| Expand / collapse control |
| Toggle icon while the section is open |
| Section body that holds the questions |
| "Attendees" heading |
| "Copy from" selector on attendee sections |
| "Registering for" picker |
| Not-attending notice |
| Attendee visibility checkbox |
| VAT / "Invoice to" block |
Layout grid
The questions in each section sit in a grid. Every question is full width except First Name and Last Name, which share a row.
Class | Element |
| Grid that holds a section's questions |
| One grid cell (one question) |
| Full-width cell: every question except First Name and Last Name |
Field wrapper
Every question is wrapped in .registration-field. The wrapper also gets a class for the question type and an error class while the answer is invalid.
Class | Element |
| Wrapper around every question |
| Question type (values below) |
| The question currently shows a validation error |
| Question label |
| The required-field asterisk (*) |
| Error message under the question |
| Icon in the error message |
Type values for {type}:
Modifier class | Question type |
| Short text |
| |
| Number |
| Phone number with country code |
| Long text |
| CC email |
| Dropdown (one choice) |
| Multiple choice |
| Single checkbox |
| Date |
| File upload |
| Image upload |
| Address, country or state |
| Conditional question (radio options that reveal follow-up questions) |
| Interest tags |
| Text block (display only, no answer) |
| VAT ID / company (inside the VAT block) |
.registration-form .registration-field--error .registration-field__label { color: #b42318; }
Inside specific question types
Some question types contain their own inner elements. Several of these classes are also used outside the registration form, so always scope them under .registration-form.
Question type | Classes | Notes |
Single checkbox |
|
|
Dropdown and multiple choice |
| The menu also gets |
Conditional question |
|
|
Date |
| Adds |
Phone |
| Country-code picker and number input |
Image upload |
| Upload area and preview |
Interest tags |
| Inner tag container adds |
Text block |
| The admin's rich-text content |
Long text |
| Added to the text area on error |
Targeting one specific question
Questions don't have their own class, so you target one by its ID. Each question's input ID, and its label's for attribute, follow the pattern {section}-{Question Name}. The question name appears exactly as you entered it, spaces included. Each section has the ID form-{section}.
Because the ID contains spaces, use an attribute selector that matches the end of the ID rather than a #id selector.
CSS: style one question in every section
/* The input for the "Company" question */ .registration-form [id$="-Company"] { text-transform: uppercase; } /* The whole wrapper of the "Job Title" question, label included */ .registration-form .registration-field:has([id$="-Job Title"]) { background: #f6f7f9; padding: 12px; border-radius: 8px; }JavaScript: read or react to one question
document.querySelectorAll('.registration-form [id$="-Company"]').forEach((input) => { input.addEventListener('blur', () => { console.log('Company entered:', input.value); }); });The form appears after the page loads and re-renders as buyers add attendees or open sections. Code that runs once on page load may find no fields. Use a MutationObserver on .registration-form, or delegated listeners on document, so your code also reaches fields that appear later.
document.addEventListener('focusout', (event) => { if (event.target.matches('.registration-form [id$="-Company"]')) { console.log('Company entered:', event.target.value); } });
Best practices
Stick to the classes in this document. The
registration-*,attendee-form*andcheck-button*names are meant for styling. Short utility classes you may see in the page, such asm-b-0,d-flex,font-w500orw-fit, are layout helpers and can change without notice.Always scope under
.registration-form. Shared classes like.attribute-dropdown-root,.multiple-option-attribute-fieldand.dateTime-dropdown-popupalso appear elsewhere on the page.Renaming a question breaks ID selectors. A rule that targets
[id$="-Company"]stops matching if the question is renamed. Update your custom code whenever you rename a question.Questions with the same ending can collide.
[id$="-Name"]also matches "First Name" and "Last Name". Make the end of the selector specific enough to match only the question you want.Don't hide required questions with CSS. The question stays required, so the buyer can't continue and can't see why.
Test on the live checkout and on a phone. Custom CSS shows in the admin preview, but saved Custom JS doesn't run there. On mobile, checkout scrolls inside its own container, so fixed or sticky positioning can behave differently.
