CSS Parts
SenseFolks surveys use Shadow DOM, so ordinary page selectors do not reach their internal elements. CSS Parts are the public, supported styling API.
Choose a part name from the component reference, then target it with::part(). Your CSS stays outside the component and survives internal markup changes.
Why Ordinary Selectors Do Not Work
SenseFolks surveys use Shadow DOM to prevent style conflicts with your page.
The trade-off is that global selectors likebutton { background: red } do not affect internal survey elements.
CSS Parts solve that boundary deliberately: the component exposes named surfaces and your page styles those names from the outside.
How to Use 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.
Shared Survey Parts
SenseFolks survey components expose a shared group of common parts. Use them as the base theme, then add the component-specific parts you need.
| 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 thecomponent 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: var(--color__grey--450);
}
/* 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: 400;
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: var(--color__grey--450);
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: var(--color__grey--450);
--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: 400;
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;
}Keep the Theme Safe and Accessible
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.
Avoid changing structural layout
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
The ::part() selector is supported in these versions:
| Browser | Version | Notes |
|---|---|---|
| Chrome | 73+ | Full support |
| Firefox | 72+ | Full support |
| Safari | 13.1+ | Full support |
| Edge | 79+ | Full support |
Your browser must also meet the minimum version in the relevant survey component reference. SenseFolks does not support IE11.