CSS Parts
Surveys run in Shadow DOM, so regular page CSS cannot reach internal elements. CSS Parts provide the supported way to style those elements.
SenseFolks components expose named parts. Target them with
::part() to style buttons, headings, inputs, and containers.
The Problem
SenseFolks surveys use Shadow DOM to prevent style conflicts with your page.
The trade-off is that global selectors like
button { background: red } do not affect internal survey
elements.
CSS Parts are the official override path: we expose styleable elements, and you target those names from outside.
The ::part() Selector
The syntax is straightforward. Use the component tag plus
::part(name), where name is an exposed part:
/* Target a specific part by name */
sf-fastpoll::part(button) {
background: #007bff;
color: white;
}
/* Target multiple parts with the same styles */
sf-fastpoll::part(heading),
sf-fastpoll::part(subheading) {
font-family: 'Georgia', serif;
}
/* Combine with pseudo-classes */
sf-fastpoll::part(button):hover {
background: #0056b3;
}
sf-fastpoll::part(button):focus-visible {
outline: 2px solid #007bff;
outline-offset: 2px;
}
/* Combine with pseudo-elements (limited support) */
sf-fastpoll::part(input)::placeholder {
color: #6c757d;
}
You can combine ::part() with pseudo-classes like :hover,
:focus, and :focus-visible. Support for
pseudo-elements like ::placeholder varies by browser.
Parts Available on Every Survey Component
All SenseFolks survey components share these common parts. Style them once to keep visual consistency across surveys:
| Part Name | What It Targets |
|---|---|
survey-container | The outer wrapper. Set fonts, background colour, and padding here. |
heading | Primary headings and titles |
button | All button elements |
next-button | Next and Submit buttons specifically |
back-button | Back and Previous buttons |
input | Text input fields |
form-field | Form field containers |
form-label | Form labels |
error-message | Validation error messages |
button-container | Container wrapping navigation buttons |
Each survey type also exposes component-specific parts. Check the component references for the full list.
Styling Recipes
Match Your Brand Colours
Define CSS custom properties once, then apply them across every survey component on your site:
/* Define your brand variables */
:root {
--brand-primary: #6366f1;
--brand-primary-dark: #4f46e5;
--brand-primary-light: #eef2ff;
--brand-text: #1e293b;
--brand-border: #e2e8f0;
}
/* Apply to all SenseFolks components */
sf-fastpoll::part(button),
sf-pricepoint::part(button),
sf-userchoice::part(button) {
background: var(--brand-primary);
border: none;
border-radius: 8px;
color: white;
font-weight: 600;
padding: 12px 24px;
cursor: pointer;
transition: background 0.2s;
}
sf-fastpoll::part(button):hover,
sf-pricepoint::part(button):hover,
sf-userchoice::part(button):hover {
background: var(--brand-primary-dark);
} Custom Typography
Swap in your own font stack so surveys read like the rest of your content:
/* Custom typography system */
sf-userchoice::part(survey-container) {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
font-size: 16px;
line-height: 1.5;
color: var(--brand-text);
}
sf-userchoice::part(heading) {
font-size: 1.5rem;
font-weight: 700;
letter-spacing: -0.02em;
margin-bottom: 1rem;
}
sf-userchoice::part(choice-label) {
font-size: 1rem;
font-weight: 500;
} Dark Mode
Detect the user's system preference, or wire it up to your own dark mode toggle:
/* Dark mode with system preference detection */
@media (prefers-color-scheme: dark) {
sf-pricepoint::part(survey-container) {
background: #1a1a2e;
color: #e2e8f0;
}
sf-pricepoint::part(text-input) {
background: #16213e;
border-color: #374151;
color: #f1f5f9;
}
sf-pricepoint::part(button) {
background: #6366f1;
}
sf-pricepoint::part(button):hover {
background: #818cf8;
}
sf-pricepoint::part(validation-message) {
background: #7f1d1d;
color: #fecaca;
}
}
/* Manual dark mode toggle */
.dark sf-pricepoint::part(survey-container) {
background: #1a1a2e;
color: #e2e8f0;
} Accessible Focus States
Keyboard users need visible focus indicators. Here's how to style them without cluttering mouse interactions:
/* Accessible focus indicators */
sf-openfeedback::part(input):focus,
sf-openfeedback::part(textarea):focus {
outline: none;
border-color: var(--brand-primary);
box-shadow: 0 0 0 3px var(--brand-primary-light);
}
/* Focus-visible for keyboard users only */
sf-openfeedback::part(button):focus-visible {
outline: 2px solid var(--brand-primary);
outline-offset: 2px;
}
/* High contrast mode support */
@media (forced-colors: active) {
sf-openfeedback::part(button) {
border: 2px solid currentColor;
}
} Animations and Transitions
Add subtle motion to interactions, and respect users who prefer reduced motion:
/* Smooth transitions */
sf-fastpoll::part(choice-option) {
transition:
border-color 0.2s ease,
background-color 0.2s ease,
transform 0.1s ease;
}
sf-fastpoll::part(choice-option):hover {
border-color: var(--brand-primary);
background: var(--brand-primary-light);
}
sf-fastpoll::part(choice-option):active {
transform: scale(0.98);
}
/* Respect reduced motion preference */
@media (prefers-reduced-motion: reduce) {
sf-fastpoll::part(choice-option) {
transition: none;
}
} Responsive Sizing
Surveys should feel right on phones, tablets, and desktops:
/* Mobile-first responsive styling */
sf-featurepriority::part(survey-container) {
padding: 1rem;
font-size: 14px;
}
sf-featurepriority::part(kano-option) {
padding: 12px;
margin-bottom: 8px;
}
/* Tablet and up */
@media (min-width: 768px) {
sf-featurepriority::part(survey-container) {
padding: 2rem;
font-size: 16px;
}
sf-featurepriority::part(kano-option) {
padding: 16px;
margin-bottom: 12px;
}
}
/* Desktop */
@media (min-width: 1024px) {
sf-featurepriority::part(survey-container) {
max-width: 600px;
margin: 0 auto;
}
} Full Theme Starter
Use this as a starting point and adjust variables to match your brand:
/* Complete theme example */
:root {
--sf-primary: #6366f1;
--sf-primary-hover: #4f46e5;
--sf-bg: #ffffff;
--sf-bg-secondary: #f8fafc;
--sf-text: #1e293b;
--sf-text-muted: #64748b;
--sf-border: #e2e8f0;
--sf-error: #ef4444;
--sf-success: #22c55e;
--sf-radius: 8px;
}
/* Container */
sf-fastpoll::part(survey-container) {
background: var(--sf-bg);
color: var(--sf-text);
font-family: system-ui, sans-serif;
border-radius: var(--sf-radius);
padding: 1.5rem;
}
/* Headings */
sf-fastpoll::part(heading) {
font-size: 1.25rem;
font-weight: 600;
margin-bottom: 1rem;
}
/* Choices */
sf-fastpoll::part(choice-option) {
display: flex;
align-items: center;
gap: 0.75rem;
padding: 1rem;
border: 2px solid var(--sf-border);
border-radius: var(--sf-radius);
margin-bottom: 0.5rem;
cursor: pointer;
transition: all 0.2s;
}
sf-fastpoll::part(choice-option):hover {
border-color: var(--sf-primary);
background: var(--sf-bg-secondary);
}
/* Buttons */
sf-fastpoll::part(button) {
background: var(--sf-primary);
color: white;
border: none;
border-radius: var(--sf-radius);
padding: 0.75rem 1.5rem;
font-weight: 600;
cursor: pointer;
}
sf-fastpoll::part(button):hover {
background: var(--sf-primary-hover);
}
sf-fastpoll::part(button):disabled {
opacity: 0.5;
cursor: not-allowed;
}
/* Error states */
sf-fastpoll::part(error-message) {
color: var(--sf-error);
font-size: 0.875rem;
margin-top: 0.5rem;
} Things to Keep in Mind
-
Use CSS custom properties for theming
Define variables like
--brand-primaryonce and reuse them across all survey components. Changing your brand colour becomes a one-line edit. -
Keep accessibility intact
Maintain sufficient colour contrast (4.5:1 for text, 3:1 for UI elements) and always provide visible focus states for keyboard navigation.
-
Respect user preferences
Support
prefers-color-scheme,prefers-reduced-motion, andforced-colorsso your surveys work well for everyone. -
Test across browsers
CSS Parts work in all modern browsers, but always verify your custom styles render correctly.
-
Don't override layout properties
Changing
display,position, orflexon internal parts can break how the component arranges its elements. -
Stick to exposed parts only
Internal DOM structure may change between versions. Parts are the stable API for styling.
Browser Support
CSS Parts work in every modern browser:
| Browser | Version | Notes |
|---|---|---|
| Chrome | 73+ | Full support |
| Firefox | 72+ | Full support |
| Safari | 13.1+ | Full support |
| Edge | 79+ | Full support |
On older browsers, surveys fall back to their default styling. Nothing breaks, it just won't pick up your custom theme.