Practical guide to MintyFlask's five-layer CSS system - patterns, scenarios, and best practices

CSS Architecture User Guide

Overview

This guide covers practical applications of MintyFlask's five-layer CSS architecture. It assumes you've read the Quick Start and understand the basic layer concepts.

What you'll learn:

  • Working with all five layers in depth
  • Common development scenarios with complete examples
  • CSS custom properties and theming patterns
  • Dark mode implementation
  • Troubleshooting layer issues
  • Best practices for maintainable styles

Understanding Layer Precedence

How Layers Work

CSS layers create an explicit hierarchy that's independent of specificity:

@layer components {
  /* This has LOWER priority... */
  div.container section.blog article.post {
    background: blue;
  }
}

@layer theme {
  /* ...than this simple selector */
  .post {
    background: red; /* WINS! */
  }
}

/* Result: background is red */

The layer order determines precedence. No need for specificity hacks.

Layer Declaration

Layers are declared in your main CSS file (input.css):

/* themes/blog/static/css/src/input.css */

/* Import Tailwind */
@import "tailwindcss";

/* Declare layer order (lowest to highest priority) */
@layer reset {
  /* Browser resets */
}

@layer base {
  /* Foundation styles */
  @import "foundations/tokens.css";
  @import "foundations/typography.css";
}

@layer components {
  /* Core components */
  @import "components/buttons.css";
  @import "components/cards.css";

  /* Mixin components */
  @import "../../../mixins/blog/static/css/blog.css";
}

@layer theme {
  /* Theme customisations */
  @import "custom/overrides.css";
  @import "custom/components.css";
}

@layer utilities {
  /* High-priority helpers */
  @import "utilities/accessibility.css";
}

The Five Layers in Detail

Layer 1: Reset (Minimal Usage)

Purpose: Browser normalisation beyond what Tailwind provides

When to use:

  • Custom resets needed for your project
  • Normalising legacy browser behaviour
  • Resetting third-party widget styles

Example:

/* themes/_core/static/css/foundations/reset.css */

@layer reset {
  /* Custom form element reset */
  input[type="search"]::-webkit-search-cancel-button {
    -webkit-appearance: none;
  }

  /* Fix for specific browser quirk */
  button {
    -webkit-appearance: button;
  }
}

Best practices:

  • Keep it minimal—Tailwind handles most resets
  • Document why each reset is needed
  • Consider if you really need it

Layer 2: Base (Foundation)

Purpose: Design tokens, typography, default element styles

When to use:

  • Defining design tokens (colours, spacing, typography)
  • Setting default HTML element styles
  • Establishing typography scale
  • Creating dark mode token variations

Example - Design Tokens:

/* themes/blog/static/css/foundations/tokens.css */

@layer base {
  :root {
    /* Colour tokens */
    --color-primary: oklch(60% 0.15 250);
    --color-secondary: oklch(65% 0.12 180);
    --color-surface: oklch(98% 0 0);
    --color-surface-dark: oklch(20% 0 0);
    --color-border: oklch(85% 0 0);
    --color-border-dark: oklch(30% 0 0);

    /* Text colours */
    --color-text-primary: oklch(20% 0 0);
    --color-text-secondary: oklch(40% 0 0);
    --color-text-tertiary: oklch(60% 0 0);

    /* Spacing scale */
    --spacing-xs: 0.25rem;
    --spacing-sm: 0.5rem;
    --spacing-md: 1rem;
    --spacing-lg: 1.5rem;
    --spacing-xl: 2rem;
    --spacing-2xl: 3rem;

    /* Typography scale */
    --text-xs: 0.75rem;
    --text-sm: 0.875rem;
    --text-base: 1rem;
    --text-lg: 1.125rem;
    --text-xl: 1.25rem;
    --text-2xl: 1.5rem;
    --text-3xl: 1.875rem;

    /* Border radius */
    --radius-sm: 0.25rem;
    --radius-md: 0.375rem;
    --radius-lg: 0.5rem;
    --radius-xl: 0.75rem;
  }
}

Example - Typography:

/* themes/_core/static/css/foundations/typography.css */

@layer base {
  body {
    font-family:
      system-ui,
      -apple-system,
      sans-serif;
    font-size: var(--text-base);
    line-height: 1.5;
    color: var(--color-text-primary);
    background: var(--color-surface);
  }

  h1,
  h2,
  h3,
  h4,
  h5,
  h6 {
    font-weight: 600;
    line-height: 1.2;
    margin-bottom: var(--spacing-md);
    color: var(--color-text-primary);
  }

  h1 {
    font-size: var(--text-3xl);
  }
  h2 {
    font-size: var(--text-2xl);
  }
  h3 {
    font-size: var(--text-xl);
  }
  h4 {
    font-size: var(--text-lg);
  }

  p {
    margin-bottom: var(--spacing-md);
  }

  a {
    color: var(--color-primary);
    text-decoration: none;
  }

  a:hover {
    text-decoration: underline;
  }
}

Best practices:

  • Use CSS custom properties for all values
  • Create semantic token names
  • Keep element styles minimal
  • Document token purpose

Layer 3: Components (Mixin Development)

Purpose: Reusable components from mixins and core

When to use:

  • Building mixin features
  • Creating reusable components
  • Developing core component library
  • Any style that might be used across themes

Example - Blog Mixin Component:

/* mixins/blog/static/css/blog.css */

@layer components {
  /* Blog Navigation */
  .blog-navigation {
    display: flex;
    gap: var(--spacing-md);
    padding: var(--spacing-lg) 0;
    border-bottom: 1px solid var(--color-border);
  }

  .blog-navigation-link {
    color: var(--color-text-secondary);
    font-weight: 500;
    padding: var(--spacing-sm) var(--spacing-md);
    border-radius: var(--radius-sm);
    transition: all 0.2s ease;
  }

  .blog-navigation-link:hover {
    background: var(--color-surface-hover);
    color: var(--color-text-primary);
  }

  .blog-navigation-link--active {
    background: var(--color-primary);
    color: white;
  }

  /* Post Card Component */
  .blog-post-card {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    padding: var(--spacing-lg);
    transition:
      transform 0.2s ease,
      box-shadow 0.2s ease;
  }

  .blog-post-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  }

  .blog-post-card--featured {
    border-width: 2px;
    border-color: var(--color-primary);
  }

  .blog-post-title {
    font-size: var(--text-xl);
    font-weight: 600;
    margin-bottom: var(--spacing-sm);
    color: var(--color-text-primary);
  }

  .blog-post-excerpt {
    color: var(--color-text-secondary);
    line-height: 1.6;
    margin-bottom: var(--spacing-md);
  }

  .blog-post-meta {
    display: flex;
    gap: var(--spacing-md);
    font-size: var(--text-sm);
    color: var(--color-text-tertiary);
  }

  /* Dark mode variants */
  .dark .blog-navigation {
    border-color: var(--color-border-dark);
  }

  .dark .blog-post-card {
    background: var(--color-surface-dark);
    border-color: var(--color-border-dark);
  }

  .dark .blog-post-card:hover {
    box-shadow: 0 4px 12px rgba(255, 255, 255, 0.1);
  }
}

Component variants with BEM:

@layer components {
  /* Base component */
  .blog-button {
    padding: var(--spacing-sm) var(--spacing-lg);
    border-radius: var(--radius-md);
    font-weight: 500;
    cursor: pointer;
    transition: all 0.2s ease;
  }

  /* Size modifiers */
  .blog-button--small {
    padding: var(--spacing-xs) var(--spacing-md);
    font-size: var(--text-sm);
  }

  .blog-button--large {
    padding: var(--spacing-md) var(--spacing-xl);
    font-size: var(--text-lg);
  }

  /* Intent modifiers */
  .blog-button--primary {
    background: var(--color-primary);
    color: white;
  }

  .blog-button--secondary {
    background: transparent;
    border: 1px solid var(--color-border);
    color: var(--color-text-primary);
  }

  /* State modifiers */
  .blog-button:hover {
    transform: translateY(-1px);
  }

  .blog-button:disabled {
    opacity: 0.5;
    cursor: not-allowed;
  }
}

Best practices:

  • Use mixin-specific prefix (.blog-, .portfolio-)
  • Employ BEM modifiers for variants
  • Always include dark mode styles
  • Use custom properties, never hardcode
  • Keep components focused and single-purpose

Layer 4: Theme (Customisation)

Purpose: Site-specific customisations and overrides

When to use:

  • Customising mixin components for your theme
  • Adding theme-specific components
  • Overriding design tokens
  • Creating unique branded elements

Example - Theme Overrides:

/* themes/agency/static/css/custom/overrides.css */

@layer theme {
  /* Override blog card for agency theme */
  .blog-post-card {
    border-radius: 0; /* Square corners */
    border-width: 2px;
    border-color: var(--color-accent);
  }

  .blog-post-card:hover {
    border-color: var(--color-primary);
    transform: scale(1.02); /* Different hover */
  }

  /* Override navigation for agency theme */
  .blog-navigation {
    background: var(--color-surface-elevated);
    padding: var(--spacing-md) var(--spacing-lg);
    border-radius: var(--radius-lg);
    border: none;
  }

  .blog-navigation-link {
    text-transform: uppercase;
    font-size: var(--text-sm);
    letter-spacing: 0.05em;
  }
}

Example - Theme Components:

/* themes/agency/static/css/custom/components.css */

@layer theme {
  /* Hero section unique to agency theme */
  .agency-hero {
    background: linear-gradient(
      135deg,
      var(--color-primary),
      var(--color-secondary)
    );
    colour: white;
    padding: var(--spacing-2xl) var(--spacing-lg);
    text-align: centre;
    position: relative;
    overflow: hidden;
  }

  .agency-hero::before {
    content: "";
    position: absolute;
    inset: 0;
    background: radial-gradient(
      circle at top right,
      rgba(255, 255, 255, 0.1),
      transparent
    );
  }

  .agency-hero-title {
    font-size: var(--text-3xl);
    font-weight: 700;
    margin-bottom: var(--spacing-md);
    position: relative;
    z-index: 1;
  }

  .agency-hero-subtitle {
    font-size: var(--text-xl);
    opacity: 0.9;
    position: relative;
    z-index: 1;
  }

  /* Client logo grid */
  .agency-clients {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: var(--spacing-lg);
    padding: var(--spacing-xl) 0;
  }

  .agency-client-logo {
    display: flex;
    align-items: centre;
    justify-content: centre;
    padding: var(--spacing-md);
    opacity: 0.6;
    transition: opacity 0.2s ease;
  }

  .agency-client-logo:hover {
    opacity: 1;
  }
}

Example - Token Overrides:

/* themes/agency/static/css/foundations/tokens.css */

@layer theme {
  :root {
    /* Override spacing for more generous layout */
    --spacing-md: 1.25rem;
    --spacing-lg: 2rem;
    --spacing-xl: 3rem;

    /* Override typography for larger text */
    --text-base: 1.125rem;
    --text-lg: 1.25rem;
    --text-xl: 1.5rem;

    /* Agency-specific tokens */
    --color-accent: oklch(65% 0.18 45);
    --color-surface-elevated: oklch(99% 0 0);
  }
}

Best practices:

  • Override only what you need
  • Maintain accessibility
  • Don't break component functionality
  • Document major overrides
  • Test with multiple mixins

Layer 5: Utilities (High Priority)

Purpose: Accessibility helpers, debugging, emergency overrides

When to use:

  • Screen reader only content
  • Print styles
  • Debugging tools
  • Truly exceptional overrides

Example - Accessibility:

/* themes/_core/static/css/utilities/accessibility.css */

@layer utilities {
  /* Screen reader only */
  .sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border-width: 0;
  }

  /* Focus visible for keyboard navigation */
  .focus-visible:focus {
    outline: 2px solid var(--color-primary);
    outline-offset: 2px;
  }

  /* Skip to content link */
  .skip-to-content {
    position: absolute;
    top: -40px;
    left: 0;
    background: var(--color-primary);
    color: white;
    padding: var(--spacing-md);
    z-index: 1000;
  }

  .skip-to-content:focus {
    top: 0;
  }
}

Example - Print Styles:

/* themes/_core/static/css/utilities/print.css */

@layer utilities {
  @media print {
    .no-print {
      display: none !important;
    }

    .page-break-before {
      page-break-before: always;
    }

    .page-break-after {
      page-break-after: always;
    }

    /* Optimize for print */
    body {
      font-size: 12pt;
      line-height: 1.4;
    }

    a {
      text-decoration: underline;
    }

    a[href]::after {
      content: " (" attr(href) ")";
      font-size: 90%;
    }
  }
}

Example - Development Debugging:

/* themes/_core/static/css/utilities/debug.css */

@layer utilities {
  /* Outline all elements for debugging */
  .debug-layout * {
    outline: 1px solid rgba(255, 0, 0, 0.3);
  }

  /* Show hidden elements */
  .debug-hidden [hidden],
  .debug-hidden .sr-only {
    position: static !important;
    width: auto !important;
    height: auto !important;
    opacity: 0.5 !important;
    outline: 2px dashed orange !important;
  }

  /* Grid overlay */
  .debug-grid {
    background-image:
      linear-gradient(rgba(0, 0, 255, 0.1) 1px, transparent 1px),
      linear-gradient(90deg, rgba(0, 0, 255, 0.1) 1px, transparent 1px);
    background-size: 20px 20px;
  }
}

Best practices:

  • Use sparingly—utilities should be exceptional
  • Document why !important is needed if used
  • Prefer higher layers over !important
  • Remove debug utilities from production

Common Development Scenarios

Scenario 1: Creating a New Mixin

Goal: Build a portfolio mixin with project cards and filtering.

Step 1: Plan your components

Portfolio mixin needs:
- .portfolio-grid (container)
- .portfolio-project-card (individual projects)
- .portfolio-filter (category filtering)
- .portfolio-project-title
- .portfolio-project-description
- .portfolio-project-tags

Step 2: Create component CSS

/* mixins/portfolio/static/css/portfolio.css */

@layer components {
  /* Portfolio grid container */
  .portfolio-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    gap: var(--spacing-lg);
    padding: var(--spacing-lg) 0;
  }

  /* Project card */
  .portfolio-project-card {
    background: var(--color-surface);
    border-radius: var(--radius-lg);
    overflow: hidden;
    transition:
      transform 0.2s ease,
      box-shadow 0.2s ease;
  }

  .portfolio-project-card:hover {
    transform: translateY(-4px);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
  }

  /* Project image */
  .portfolio-project-image {
    width: 100%;
    aspect-ratio: 16 / 9;
    object-fit: cover;
  }

  /* Project content */
  .portfolio-project-content {
    padding: var(--spacing-lg);
  }

  .portfolio-project-title {
    font-size: var(--text-xl);
    font-weight: 600;
    margin-bottom: var(--spacing-sm);
    color: var(--color-text-primary);
  }

  .portfolio-project-description {
    color: var(--color-text-secondary);
    line-height: 1.6;
    margin-bottom: var(--spacing-md);
  }

  /* Project tags */
  .portfolio-project-tags {
    display: flex;
    flex-wrap: wrap;
    gap: var(--spacing-sm);
  }

  .portfolio-project-tag {
    padding: var(--spacing-xs) var(--spacing-sm);
    background: var(--color-surface-elevated);
    border-radius: var(--radius-sm);
    font-size: var(--text-sm);
    color: var(--color-text-secondary);
  }

  /* Category filter */
  .portfolio-filter {
    display: flex;
    gap: var(--spacing-sm);
    margin-bottom: var(--spacing-lg);
    flex-wrap: wrap;
  }

  .portfolio-filter-button {
    padding: var(--spacing-sm) var(--spacing-md);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: transparent;
    color: var(--color-text-secondary);
    cursor: pointer;
    transition: all 0.2s ease;
  }

  .portfolio-filter-button:hover {
    border-color: var(--color-primary);
    color: var(--color-primary);
  }

  .portfolio-filter-button--active {
    background: var(--color-primary);
    border-color: var(--color-primary);
    color: white;
  }

  /* Dark mode */
  .dark .portfolio-project-card {
    background: var(--color-surface-dark);
  }

  .dark .portfolio-project-tag {
    background: var(--color-border-dark);
  }

  .dark .portfolio-filter-button {
    border-color: var(--color-border-dark);
  }
}

Step 3: Use in template

<!-- Filter -->
<div class="portfolio-filter">
  <button class="portfolio-filter-button portfolio-filter-button--active">
    All
  </button>
  <button class="portfolio-filter-button">Web Design</button>
  <button class="portfolio-filter-button">Branding</button>
</div>

<!-- Grid -->
<div class="portfolio-grid">
  <article class="portfolio-project-card">
    <img src="project.jpg" alt="Project name" class="portfolio-project-image" />
    <div class="portfolio-project-content">
      <h3 class="portfolio-project-title">Project Title</h3>
      <p class="portfolio-project-description">
        Brief description of the project...
      </p>
      <div class="portfolio-project-tags">
        <span class="portfolio-project-tag">Web Design</span>
        <span class="portfolio-project-tag">React</span>
      </div>
    </div>
  </article>
  <!-- More cards... -->
</div>

Scenario 2: Customising a Mixin for Your Theme

Goal: Customise the blog mixin for a minimal design aesthetic.

/* themes/minimal/static/css/custom/overrides.css */

@layer theme {
  /* Minimal blog card - remove shadows and borders */
  .blog-post-card {
    border: none;
    border-bottom: 1px solid var(--color-border);
    border-radius: 0;
    padding: var(--spacing-xl) 0;
  }

  .blog-post-card:hover {
    transform: none;
    box-shadow: none;
    background: transparent;
  }

  /* Minimal typography */
  .blog-post-title {
    font-size: var(--text-2xl);
    font-weight: 400; /* Lighter weight */
    letter-spacing: -0.02em;
  }

  .blog-post-excerpt {
    color: var(--color-text-tertiary);
    font-size: var(--text-sm);
  }

  /* Minimal navigation */
  .blog-navigation {
    border: none;
    padding: var(--spacing-md) 0;
  }

  .blog-navigation-link {
    background: transparent;
    border-radius: 0;
    border-bottom: 2px solid transparent;
    padding: var(--spacing-sm) 0;
  }

  .blog-navigation-link:hover {
    background: transparent;
    border-bottom-color: var(--color-text-primary);
  }

  .blog-navigation-link--active {
    background: transparent;
    color: var(--color-text-primary);
    border-bottom-color: var(--color-primary);
  }
}

Scenario 3: Implementing Dark Mode

Goal: Add comprehensive dark mode support to your theme.

Step 1: Define dark mode tokens

/* themes/blog/static/css/foundations/tokens.css */

@layer base {
  :root {
    /* Light mode (default) */
    --color-surface: oklch(98% 0 0);
    --color-text-primary: oklch(20% 0 0);
    --color-border: oklch(85% 0 0);
  }

  /* Dark mode tokens */
  .dark {
    --color-surface: oklch(20% 0 0);
    --color-surface-elevated: oklch(25% 0 0);
    --color-text-primary: oklch(95% 0 0);
    --color-text-secondary: oklch(75% 0 0);
    --color-border: oklch(30% 0 0);
  }
}

Step 2: Add dark variants to components

/* mixins/blog/static/css/blog.css */

@layer components {
  .blog-post-card {
    background: var(--color-surface);
    border-color: var(--color-border);
    color: var(--color-text-primary);
  }

  /* Dark mode - tokens handle it automatically! */
  /* But add specific dark overrides if needed */
  .dark .blog-post-card:hover {
    box-shadow: 0 4px 12px rgba(255, 255, 255, 0.1);
  }
}

Step 3: Theme toggle (JavaScript)

<button id="theme-toggle" class="theme-toggle">
  <span class="light-icon">🌞</span>
  <span class="dark-icon">🌙</span>
</button>

<script>
  const toggle = document.getElementById("theme-toggle");
  const html = document.documentElement;

  toggle.addEventListener("click", () => {
    html.classList.toggle("dark");
    localStorage.setItem(
      "theme",
      html.classList.contains("dark") ? "dark" : "light",
    );
  });

  // Load saved preference
  if (localStorage.getItem("theme") === "dark") {
    html.classList.add("dark");
  }
</script>

Scenario 4: Responsive Design Patterns

Goal: Create responsive components that work on all screen sizes.

/* mixins/portfolio/static/css/portfolio.css */

@layer components {
  /* Mobile-first approach */
  .portfolio-grid {
    display: grid;
    grid-template-columns: 1fr; /* Single column on mobile */
    gap: var(--spacing-md);
  }

  /* Tablet */
  @media (min-width: 640px) {
    .portfolio-grid {
      grid-template-columns: repeat(2, 1fr);
      gap: var(--spacing-lg);
    }
  }

  /* Desktop */
  @media (min-width: 1024px) {
    .portfolio-grid {
      grid-template-columns: repeat(3, 1fr);
      gap: var(--spacing-xl);
    }
  }

  /* Project card responsive */
  .portfolio-project-content {
    padding: var(--spacing-md);
  }

  @media (min-width: 640px) {
    .portfolio-project-content {
      padding: var(--spacing-lg);
    }
  }

  /* Responsive typography */
  .portfolio-project-title {
    font-size: var(--text-lg);
  }

  @media (min-width: 640px) {
    .portfolio-project-title {
      font-size: var(--text-xl);
    }
  }

  @media (min-width: 1024px) {
    .portfolio-project-title {
      font-size: var(--text-2xl);
    }
  }
}

Troubleshooting

Problem: Styles Not Applying

Symptom: Your CSS doesn't seem to work.

Common causes:

  1. Wrong layer priority

    /* Wrong: trying to override theme with components */
    @layer components {
      .blog-post-card {
        background: red; /* Won't work if theme sets it */
      }
    }
    
    /* Right: use higher layer */
    @layer theme {
      .blog-post-card {
        background: red;
      }
    }
    
  2. Unlayered CSS

    /* Wrong: unlayered CSS has unpredictable priority */
    .blog-post-card {
      background: red;
    }
    
    /* Right: always use layers */
    @layer theme {
      .blog-post-card {
        background: red;
      }
    }
    
  3. Import order

    /* Wrong order in input.css */
    @layer theme {
      @import "custom.css";
    }
    @layer components {
      @import "blog.css"; /* Loads after theme! */
    }
    
    /* Right order */
    @layer components {
      @import "blog.css";
    }
    @layer theme {
      @import "custom.css";
    }
    

Problem: Class Name Conflicts

Symptom: Styles from different mixins interfere.

Cause: Generic class names without prefixes.

Solution:

/* Wrong: conflicts between mixins */
@layer components {
  .card {
  } /* blog.css */
  .card {
  } /* portfolio.css - conflict! */
}

/* Right: use prefixes */
@layer components {
  .blog-card {
  }
  .portfolio-card {
  }
}

Problem: Dark Mode Not Working

Symptom: Dark mode styles don't apply.

Common causes:

  1. Wrong selector

    /* Wrong */
    @media (prefers-color-scheme: dark) {
      .card {
        background: black;
      }
    }
    
    /* Right: use .dark class */
    @layer components {
      .dark .card {
        background: black;
      }
    }
    
  2. Missing token definitions

    /* Wrong: no dark mode tokens */
    @layer base {
      :root {
        --color-surface: white;
      }
    }
    
    /* Right: define dark tokens */
    @layer base {
      :root {
        --color-surface: white;
      }
    
      .dark {
        --color-surface: black;
      }
    }
    

Problem: Specificity Issues

Symptom: Need increasingly specific selectors.

Cause: Fighting specificity instead of using layers.

Solution:

/* Wrong: specificity war */
.container .blog .post {
}
.container .blog .post.featured {
}
body .container .blog .post.featured.highlighted {
}

/* Right: use layers and simple selectors */
@layer components {
  .blog-post {
  }
  .blog-post--featured {
  }
}

@layer theme {
  .blog-post--highlighted {
  }
}

Best Practices Summary

Do's ✓

  1. Always use layers for all custom CSS
  2. Use CSS custom properties for all values
  3. Prefix component classes with mixin name
  4. Include dark mode variants
  5. Override minimally in theme layer
  6. Document unusual overrides
  7. Test with multiple mixins active
  8. Keep components focused and reusable

Don'ts ✗

  1. Don't mix layered and unlayered CSS
  2. Don't hardcode values
  3. Don't use overly specific selectors
  4. Don't put component styles in utilities
  5. Don't override component functionality
  6. Don't use !important unless in utilities
  7. Don't duplicate entire components
  8. Don't ignore accessibility

Development Checklist

For every component:

  • Wrapped in appropriate @layer
  • Uses CSS custom properties
  • Has prefixed class names
  • Includes dark mode variant
  • Responsive on all screen sizes
  • Accessible (focus states, ARIA)
  • Documented with comments
  • Tested with other mixins

Next Steps

You now understand how to work with MintyFlask's layer system in practice. For more information:

Summary

Key principles:

  1. Five layers - Each has a specific purpose
  2. Layer priority - Higher layers always win
  3. Use tokens - Never hardcode values
  4. Prefix classes - Avoid naming conflicts
  5. Dark mode first - Always include dark variants
  6. Override minimally - Only change what you need
  7. Test comprehensively - Multiple mixins together

With these practices, you'll build maintainable, conflict-free CSS that works reliably across your entire site.