Sass Theme Guide
# SASS Theme Development Guide This guide covers how to develop FearlessCMS themes that use SASS (Syntactically Awesome Style Sheets) for CSS preprocessing. This is useful for complex themes that benefit from SASS features like variables, mixins, and nested rules. ## When to Use SASS Consider using SASS for your theme if you need: - **Complex styling** with many variables and calculations - **Reusable components** that benefit from mixins - **Organized CSS structure** with partials and imports - **Advanced features** like functions and loops - **Better maintainability** for large stylesheets ## SASS Setup ### 1. Install SASS You'll need to install SASS on your development machine: ```bash # Using npm (recommended) npm install -g sass # Using Ruby (if you have Ruby installed) gem install sass # Using Homebrew (macOS) brew install sass/sass/sass ``` ### 2. Theme Structure with SASS Organize your SASS files in a logical structure: ``` themes/your-sass-theme/ ├── templates/ │ ├── home.html │ ├── page.html │ ├── blog.html │ └── 404.html ├── assets/ │ ├── sass/ │ │ ├── main.scss # Main SASS file │ │ ├── _variables.scss # Variables │ │ ├── _mixins.scss # Mixins │ │ ├── _base.scss # Base styles │ │ ├── _layout.scss # Layout styles │ │ ├── _components.scss # Component styles │ │ └── _utilities.scss # Utility classes │ ├── style.css # Compiled CSS (generated) │ ├── images/ │ └── js/ ├── theme.json ├── config.json └── README.md ``` ### 3. SASS File Organization #### main.scss (Main Entry Point) ```scss // Import all SASS files @import 'variables'; @import 'mixins'; @import 'base'; @import 'layout'; @import 'components'; @import 'utilities'; ``` #### _variables.scss (Variables) ```scss // Colors $primary-color: #007bff; $secondary-color: #6c757d; $success-color: #28a745; $danger-color: #dc3545; $warning-color: #ffc107; $info-color: #17a2b8; // Typography $font-family-base: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; $font-size-base: 1rem; $line-height-base: 1.6; // Spacing $spacing-unit: 1rem; $container-max-width: 1200px; // Breakpoints $breakpoint-sm: 576px; $breakpoint-md: 768px; $breakpoint-lg: 992px; $breakpoint-xl: 1200px; // Theme options integration $theme-colors: ( 'blue': #007bff, 'green': #28a745, 'purple': #6f42c1, 'orange': #fd7e14 ); ``` #### _mixins.scss (Reusable Mixins) ```scss // Responsive breakpoint mixin @mixin respond-to($breakpoint) { @if $breakpoint == sm { @media (min-width: $breakpoint-sm) { @content; } } @else if $breakpoint == md { @media (min-width: $breakpoint-md) { @content; } } @else if $breakpoint == lg { @media (min-width: $breakpoint-lg) { @content; } } @else if $breakpoint == xl { @media (min-width: $breakpoint-xl) { @content; } } } // Button mixin @mixin button($bg-color: $primary-color, $text-color: white) { background-color: $bg-color; color: $text-color; padding: 0.5rem 1rem; border: none; border-radius: 4px; cursor: pointer; transition: background-color 0.2s ease; &:hover { background-color: darken($bg-color, 10%); } } // Card mixin @mixin card($bg-color: white, $border-color: #e9ecef) { background-color: $bg-color; border: 1px solid $border-color; border-radius: 8px; padding: $spacing-unit; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); } ``` #### _base.scss (Base Styles) ```scss // Reset and base styles * { margin: 0; padding: 0; box-sizing: border-box; } html { font-size: 16px; } body { font-family: $font-family-base; font-size: $font-size-base; line-height: $line-height-base; color: $text-color; background-color: $bg-color; } // Typography h1, h2, h3, h4, h5, h6 { margin-bottom: $spacing-unit; font-weight: 600; line-height: 1.2; } h1 { font-size: 2.5rem; } h2 { font-size: 2rem; } h3 { font-size: 1.75rem; } h4 { font-size: 1.5rem; } h5 { font-size: 1.25rem; } h6 { font-size: 1rem; } p { margin-bottom: $spacing-unit; } a { color: $primary-color; text-decoration: none; &:hover { text-decoration: underline; } } ``` #### _layout.scss (Layout Styles) ```scss // Container .container { max-width: $container-max-width; margin: 0 auto; padding: 0 $spacing-unit; @include respond-to(md) { padding: 0 ($spacing-unit * 2); } } // Grid system .grid { display: grid; gap: $spacing-unit; &--2-cols { grid-template-columns: 1fr; @include respond-to(md) { grid-template-columns: 1fr 1fr; } } &--3-cols { grid-template-columns: 1fr; @include respond-to(md) { grid-template-columns: repeat(3, 1fr); } } } // Header .header { background-color: $header-bg; padding: $spacing-unit 0; border-bottom: 1px solid $border-color; } // Main content .main { padding: ($spacing-unit * 2) 0; min-height: 60vh; } // Footer .footer { background-color: $footer-bg; color: $footer-text-color; padding: ($spacing-unit * 2) 0; margin-top: auto; } ``` #### _components.scss (Component Styles) ```scss // Buttons .btn { @include button; &--secondary { @include button($secondary-color); } &--success { @include button($success-color); } &--danger { @include button($danger-color); } } // Cards .card { @include card; &--featured { @include card($primary-color, $primary-color); color: white; } } // Navigation .nav { display: flex; align-items: center; &__list { display: flex; list-style: none; gap: $spacing-unit; } &__link { color: $nav-link-color; text-decoration: none; padding: 0.5rem; &:hover { color: $nav-link-hover-color; } } } // Blog posts .blog-post { margin-bottom: ($spacing-unit * 2); padding-bottom: ($spacing-unit * 2); border-bottom: 1px solid $border-color; &:last-child { border-bottom: none; } &__title { margin-bottom: $spacing-unit; a { color: $text-color; text-decoration: none; &:hover { color: $primary-color; } } } &__meta { color: $text-muted; font-size: 0.9rem; margin-bottom: $spacing-unit; } &__excerpt { color: $text-muted; margin-bottom: $spacing-unit; } } ``` ## Development Workflow with SASS ### 1. Watch Mode Use SASS watch mode during development: ```bash # Watch for changes and compile automatically sass --watch assets/sass/main.scss:assets/style.css # Or with compressed output sass --watch assets/sass/main.scss:assets/style.css --style compressed ``` ### 2. Build Process For production builds: ```bash # Compile once with compressed output sass assets/sass/main.scss:assets/style.css --style compressed # Or create a build script in package.json ``` ### 3. Package.json Scripts Create a `package.json` file in your theme directory: ```json { "name": "your-sass-theme", "version": "1.0.0", "scripts": { "sass:watch": "sass --watch assets/sass/main.scss:assets/style.css", "sass:build": "sass assets/sass/main.scss:assets/style.css --style compressed", "sass:dev": "sass assets/sass/main.scss:assets/style.css --style expanded" }, "devDependencies": { "sass": "^1.32.0" } } ``` Then use: ```bash npm run sass:watch # Development npm run sass:build # Production npm run sass:dev # Development with expanded output ``` ## Theme Options Integration ### CSS Custom Properties with SASS Use SASS to generate CSS custom properties for theme options: ```scss // _variables.scss $theme-colors: ( 'blue': #007bff, 'green': #28a745, 'purple': #6f42c1, 'orange': #fd7e14 ); // Generate CSS custom properties :root { @each $name, $color in $theme-colors { --color-#{$name}: #{$color}; } --primary-color: var(--color-blue); --secondary-color: var(--color-gray); } // Theme-specific classes @each $name, $color in $theme-colors { .theme-#{$name} { --primary-color: var(--color-#{$name}); } } ``` ### Dynamic Theme Options Create SASS functions to handle theme options: ```scss // _functions.scss @function theme-color($color-name) { @return var(--color-#{$color-name}); } @function theme-option($option-name) { @return var(--theme-#{$option-name}); } // Usage .button { background-color: theme-color('primary'); color: white; } .sidebar { @if theme-option('show-sidebar') { display: block; } @else { display: none; } } ``` ## Example: Complete SASS Theme ### Theme Structure ``` themes/sass-example/ ├── templates/ │ ├── home.html │ ├── page.html │ ├── blog.html │ └── 404.html ├── assets/ │ ├── sass/ │ │ ├── main.scss │ │ ├── _variables.scss │ │ ├── _mixins.scss │ │ ├── _base.scss │ │ ├── _layout.scss │ │ ├── _components.scss │ │ └── _utilities.scss │ ├── style.css │ └── images/ ├── theme.json ├── config.json ├── package.json └── README.md ``` ### main.scss ```scss // Import all SASS files @import 'variables'; @import 'mixins'; @import 'base'; @import 'layout'; @import 'components'; @import 'utilities'; // Theme-specific overrides @import 'theme-overrides'; ``` ### Template Usage ```html
{{#if themeOptions.logo}}
{{else}}