CSS Patterns

Best practices for styling WildflowerJS components without build tools or framework overhead.

Philosophy: WildflowerJS is CSS-agnostic. There is no build step and no framework-specific CSS processing. Your CSS skills transfer directly.

Component-Scoped CSS with :where()

Since every WildflowerJS component has a data-component attribute, you can use native CSS attribute selectors to scope styles without any framework code:

/* Scoped to kanban-column component */
:where([data-component="kanban-column"]) {
    .header {
        font-weight: bold;
        padding: 1rem;
    }

    .card {
        border-radius: 4px;
        margin-bottom: 0.5rem;
    }

    .card-list {
        min-height: 100px;
    }
}

Why :where()?

The :where() pseudo-class has zero specificity, which provides important benefits:

  • Easy overrides: Global themes and utility classes can still override component styles
  • No specificity wars: Avoids the escalating specificity problems common in large stylesheets
  • Native browser support: Works in all modern browsers without compilation
Zero Framework Overhead: This pattern requires no JavaScript processing. The browser handles everything natively.

Alternative: Higher Specificity with :is()

If you need your component styles to have higher specificity (to override external libraries), use :is() instead:

/* Higher specificity - harder to override */
:is([data-component="kanban-column"]) {
    .header {
        font-weight: bold;
    }
}

Native CSS Nesting

Modern browsers support CSS nesting natively. Combined with attribute selectors, you get SCSS-like organization without any build step:

[data-component="task-card"] {
    background: white;
    border-radius: 8px;
    padding: 1rem;

    .title {
        font-size: 1.1rem;
        font-weight: 600;
    }

    .description {
        color: #666;
        margin-top: 0.5rem;
    }

    .priority {
        display: inline-block;
        padding: 0.25rem 0.5rem;
        border-radius: 4px;
        font-size: 0.75rem;

        &.high { background: #fee2e2; color: #dc2626; }
        &.medium { background: #fef3c7; color: #d97706; }
        &.low { background: #d1fae5; color: #059669; }
    }
}

Combining with data-bind-style

WildflowerJS's reactive style bindings work with scoped CSS. Use CSS for static structure, and data-bind-style for dynamic values:

<!-- CSS handles structure, data-bind-style handles dynamic color -->
<div data-component="kanban-column">
    <div class="header" data-bind-style="{ backgroundColor: currentColor }">
        <span data-bind="column.name"></span>
    </div>
</div>
:where([data-component="kanban-column"]) {
    .header {
        /* Static styles */
        padding: 1rem;
        font-weight: bold;
        border-radius: 8px 8px 0 0;
        /* backgroundColor comes from data-bind-style */
    }
}

Computed Styles from State

For complex dynamic styling (like calculating text color based on background luminance), use computed properties:

wildflower.component('kanban-column', {
    state: {
        currentColor: '#ebecf0'
    },

    computed: {
        textColor() {
            // Calculate luminance for contrast
            const hex = this.currentColor.replace('#', '');
            const r = parseInt(hex.substr(0, 2), 16);
            const g = parseInt(hex.substr(2, 2), 16);
            const b = parseInt(hex.substr(4, 2), 16);
            const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
            return luminance > 0.5 ? '#000000' : '#ffffff';
        }
    }
});
<div class="header"
     data-bind-style="{ backgroundColor: currentColor, color: textColor }">
    ...
</div>

Recommended Patterns

Use Case Approach
Component-scoped styles :where([data-component="name"]) { ... }
Dynamic colors/sizes data-bind-style with state/computed
Conditional classes data-bind-class
Theming CSS custom properties (--var-name)
Utility-first Tailwind, Bootstrap, or similar (fully compatible)

What We Don't Do

WildflowerJS intentionally avoids:

  • Runtime CSS parsing: No JavaScript cycles spent processing <style> tags
  • Auto-prefixed class names: Would cause Flash of Unstyled Content (FOUC)
  • CSS-in-JS: Adds complexity and bundle size
  • Build-time hashing: Requires compilation step
The "Wildflower Way": Explicit but automated. Use native browser capabilities. Keep the learning curve flat. Your CSS knowledge is your CSS knowledge.

Browser Support

The patterns on this page work in all modern browsers:

  • :where() - Chrome 88+, Firefox 78+, Safari 14+
  • :is() - Chrome 88+, Firefox 78+, Safari 14+
  • CSS Nesting - Chrome 120+, Firefox 117+, Safari 17.2+

For older browser support, use a PostCSS build step or stick with non-nested selectors.