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:

css
/* 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 NameWhat It Targets
survey-containerThe outer wrapper. Set fonts, background colour, and padding here.
headingPrimary headings and titles
buttonAll button elements
next-buttonNext and Submit buttons specifically
back-buttonBack and Previous buttons
inputText input fields
form-fieldForm field containers
form-labelForm labels
error-messageValidation error messages
button-containerContainer 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:

css
/* 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:

css
/* 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:

css
/* 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:

css
/* 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:

css
/* 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:

css
/* 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:

css
/* 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-primary once 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, and forced-colors so 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, or flexon 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:

BrowserVersionNotes
Chrome73+Full support
Firefox72+Full support
Safari13.1+Full support
Edge79+Full support

Your browser must also meet the minimum version in the relevant survey component reference. SenseFolks does not support IE11.

Continue from Here