Styles and Scripts
Deodar provides a powerful asset management system that handles SCSS compilation, JavaScript bundling, and proper enqueuing for both frontend and backend. This guide will show you how to add and manage styles and scripts in your Deodar project.
Overview
Deodar's asset management system offers:
- SCSS Compilation: Automatic compilation with source maps
- JavaScript Bundling: Modern ES6+ support with bundling
- Conditional Loading: Load assets on frontend, backend, or both
- Dependency Management: Handle script dependencies properly
- Development & Production: Different builds for different environments
- Watch Mode: Real-time compilation during development
Configuration
Styles and scripts are configured in your main project file using the deodar filter:
add_filter('deodar', function($data) {
return [
'path' => get_template_directory(), // or plugin_dir_path(__FILE__)
'url' => get_template_directory_uri(), // or plugin_dir_url(__FILE__)
'production' => false,
'styles' => [
// Your styles configuration
],
'scripts' => [
// Your scripts configuration
]
];
});
Styles Configuration
Basic Style Configuration
'styles' => [
[
'handle' => 'main-style',
'file' => '/build/index.build.scss',
'frontend' => true,
'backend' => false
]
]
Style Configuration Options
| Option | Type | Required | Description |
|---|---|---|---|
handle | string | ✅ | Unique identifier for the style |
file | string | ⚠️ | Path to the SCSS file (relative to project root) |
url | string | ⚠️ | External URL for the style |
frontend | bool | ❌ | Load on frontend (default: true) |
backend | bool | ❌ | Load on backend/admin (default: false) |
template | string/array | ❌ | Specific template(s) to load this style on |
dependencies | array | ❌ | Array of style handles this depends on |
version | string | ❌ | Version string for cache busting |
media | string | ❌ | CSS media type (default: 'all') |
⚠️ Either
fileorurlis required (not both)
Advanced Style Configuration
'styles' => [
[
'handle' => 'google-fonts',
'url' => 'https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;700&display=swap',
'frontend' => true,
'backend' => false
],
[
'handle' => 'main-style',
'file' => '/source/index.scss',
'dependencies' => ['google-fonts'],
'version' => '1.0.0',
'media' => 'all',
'frontend' => true,
'backend' => false
],
[
'handle' => 'admin-style',
'file' => '/source/admin.scss',
'frontend' => false,
'backend' => true
]
]
Scripts Configuration
Basic Script Configuration
'scripts' => [
[
'handle' => 'main-script',
'file' => '/source/index.js',
'frontend' => true,
'backend' => false
]
]
Script Configuration Options
| Option | Type | Required | Description |
|---|---|---|---|
handle | string | ✅ | Unique identifier for the script |
file | string | ⚠️ | Path to the JavaScript file (relative to project root) |
url | string | ⚠️ | External URL for the script |
frontend | bool | ❌ | Load on frontend (default: true) |
backend | bool | ❌ | Load on backend/admin (default: false) |
template | string/array | ❌ | Specific template(s) to load this script on |
dependencies | array | ❌ | Array of script handles this depends on |
version | string | ❌ | Version string for cache busting |
args | bool | ❌ | Load in footer (default: false) |
⚠️ Either
fileorurlis required (not both)
Advanced Script Configuration
'scripts' => [
[
'handle' => 'jquery',
'url' => 'https://code.jquery.com/jquery-3.6.0.min.js',
'frontend' => true,
'backend' => true
],
[
'handle' => 'main-script',
'file' => '/source/index.js',
'dependencies' => ['jquery'],
'version' => '1.0.0',
'args' => true, // Load in footer
'frontend' => true,
'backend' => false
],
[
'handle' => 'admin-script',
'file' => '/source/admin.js',
'dependencies' => ['jquery'],
'frontend' => false,
'backend' => true
]
]
File Structure
Recommended Structure
your-project/
├── source/ # Source files
│ ├── index.scss # Global styles
│ ├── index.js # Global scripts
│ ├── admin.scss # Admin-only styles
│ └── admin.js # Admin-only scripts
├── build/ # Compiled assets (auto-generated)
│ ├── index.build.css
│ ├── index.build.css.map
│ ├── index.build.js
│ └── index.build.js.map
└── ... # Other files
Template-Specific Loading
Template Key Usage
The template key allows you to load assets only on specific templates, improving performance by loading only what's needed:
'styles' => [
[
'handle' => 'homepage-style',
'file' => '/build/homepage.build.css',
'template' => 'front-page.php',
'frontend' => true,
'backend' => false
],
[
'handle' => 'blog-style',
'file' => '/build/blog.build.css',
'template' => ['index.php', 'single.php', 'archive.php'],
'frontend' => true,
'backend' => false
]
]
Common Template Patterns
A common pattern is to have global assets that are always loaded, plus template-specific assets. The global index.scss and index.js files import header styles and scripts:
'styles' => [
// Always loaded global styles (includes header via @use)
[
'handle' => 'main-style',
'file' => '/build/index.build.css',
'frontend' => true,
'backend' => false
],
// Template-specific styles
[
'handle' => 'homepage-style',
'file' => '/build/homepage.build.css',
'template' => 'front-page.php',
'frontend' => true,
'backend' => false
],
[
'handle' => 'contact-style',
'file' => '/build/contact.build.css',
'template' => 'page-contact.php',
'frontend' => true,
'backend' => false
]
],
'scripts' => [
// Always loaded global scripts (includes header via import)
[
'handle' => 'main-script',
'file' => '/build/index.build.js',
'frontend' => true,
'backend' => false
],
// Template-specific scripts
[
'handle' => 'homepage-script',
'file' => '/build/homepage.build.js',
'template' => 'front-page.php',
'frontend' => true,
'backend' => false
]
]
File Organization for Template-Specific Assets
your-project/
├── source/
│ ├── index.scss # Global styles (imports header.scss)
│ ├── index.js # Global scripts (imports header.js)
│ ├── homepage.scss # Homepage-specific styles
│ ├── homepage.js # Homepage-specific scripts
│ ├── contact.scss # Contact page styles
│ └── contact.js # Contact page scripts
├── template-parts/
│ ├── header/
│ │ ├── header.scss # Header styles (imported by index.scss)
│ │ └── header.js # Header scripts (imported by index.js)
│ └── footer/
│ ├── footer.scss # Footer styles (imported by index.scss)
│ └── footer.js # Footer scripts (imported by index.js)
└── build/ # Compiled assets
├── index.build.css
├── homepage.build.css
└── contact.build.css
Import Patterns
In source/index.scss:
// Template part styles
@use '../template-parts/header/header.scss';
@use '../template-parts/footer/footer.scss';
// Global styles
body {
font-family: 'Roboto', sans-serif;
}
In source/index.js:
// Import template part scripts
import Header from '../template-parts/header/header.js';
import Footer from '../template-parts/footer/footer.js';
// Global JavaScript
$(document).ready(function() {
console.log('Global script loaded');
});
External Dependencies
CDN Resources
You can include external resources from CDNs:
'styles' => [
[
'handle' => 'bootstrap',
'url' => 'https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css',
'frontend' => true,
'backend' => false
]
],
'scripts' => [
[
'handle' => 'bootstrap',
'url' => 'https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js',
'dependencies' => ['jquery'],
'frontend' => true,
'backend' => false
]
]
WordPress Dependencies
Use WordPress core dependencies:
'scripts' => [
[
'handle' => 'custom-script',
'file' => '/source/index.js',
'dependencies' => ['jquery', 'wp-api'],
'frontend' => true,
'backend' => false
]
]
Build Configuration
deodar.json Configuration
Create a deodar.json file in your project root to customize the build process:
{
"externals": {
"jquery": "jQuery",
"lodash": "_",
"gsap": "gsap"
},
"skip": [
"node_modules/**",
"dist/**",
".git/**"
]
}
Configuration Options
| Option | Type | Description |
|---|---|---|
externals | object | External dependencies to exclude from bundling |
skip | array | File patterns to skip during compilation |
Development Workflow
1. Create Source Files
Create your SCSS and JavaScript files in the source/ directory:
// source/index.scss
$primary-color: #007cba;
$secondary-color: #f0f0f0;
body {
font-family: 'Roboto', sans-serif;
color: $primary-color;
}
.button {
background-color: $primary-color;
color: white;
padding: 10px 20px;
border: none;
border-radius: 4px;
&:hover {
background-color: darken($primary-color, 10%);
}
}
// source/index.js
import $ from 'jquery';
$(document).ready(function() {
console.log('Deodar project loaded!');
// Your JavaScript code here
$('.button').on('click', function() {
console.log('Button clicked!');
});
});
2. Configure in Main File
Add the styles and scripts to your Deodar configuration:
add_filter('deodar', function($data) {
return [
'path' => get_template_directory(),
'url' => get_template_directory_uri(),
'production' => false,
'styles' => [
[
'handle' => 'main-style',
'file' => '/build/index.build.scss',
'frontend' => true,
'backend' => false
]
],
'scripts' => [
[
'handle' => 'main-script',
'file' => '/build/index.build.js',
'dependencies' => ['jquery'],
'frontend' => true,
'backend' => false
]
]
];
});
3. Build Assets
Use the Deodar CLI to build your assets:
# Development build
deodar development
# Production build
deodar production
# Watch mode for development
deodar watch
Best Practices
Performance Optimization
- Minimize Dependencies: Only include what you need
- Use CDNs Wisely: Balance performance vs. reliability
- Conditional Loading: Load assets only where needed
- Version Control: Use version strings for cache busting
Code Organization
- Modular SCSS: Break styles into logical components
- ES6 Modules: Use modern JavaScript features
- Consistent Naming: Use consistent naming conventions
- Documentation: Document complex configurations
Development Workflow
- Use Watch Mode: For real-time development
- Test Both Environments: Test frontend and backend loading
- Version Control: Track source files, not build files
- Error Handling: Handle missing files gracefully
Troubleshooting
Common Issues
Styles Not Loading
- Check file paths in configuration
- Verify SCSS compilation
- Check browser console for errors
Scripts Not Working
- Verify JavaScript file paths
- Check for JavaScript errors in console
- Ensure dependencies are loaded
Build Errors
- Check SCSS syntax
- Verify JavaScript syntax
- Check deodar.json configuration
Debug Mode
Enable debug mode to see detailed information:
'production' => false, // Set to false for development
Examples
Complete Configuration Example
add_filter('deodar', function($data) {
return [
'path' => get_template_directory(),
'url' => get_template_directory_uri(),
'production' => false,
'styles' => [
// External dependencies
[
'handle' => 'google-fonts',
'url' => 'https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;700&display=swap',
'frontend' => true,
'backend' => false
],
// Global styles (includes header via @use in source/index.scss)
[
'handle' => 'main-style',
'file' => '/build/index.build.css',
'version' => '1.0.0',
'frontend' => true,
'backend' => false
],
// Template-specific styles
[
'handle' => 'homepage-style',
'file' => '/build/homepage.build.css',
'template' => 'front-page.php',
'frontend' => true,
'backend' => false
],
[
'handle' => 'blog-style',
'file' => '/build/blog.build.css',
'template' => ['index.php', 'single.php', 'archive.php'],
'frontend' => true,
'backend' => false
],
// Admin styles
[
'handle' => 'admin-style',
'file' => '/build/admin.build.css',
'frontend' => false,
'backend' => true
]
],
'scripts' => [
// Global scripts (includes header via import in source/index.js)
[
'handle' => 'main-script',
'file' => '/build/index.build.js',
'dependencies' => ['jquery'],
'version' => '1.0.0',
'args' => true,
'frontend' => true,
'backend' => false
],
// Template-specific scripts
[
'handle' => 'homepage-script',
'file' => '/build/homepage.build.js',
'template' => 'front-page.php',
'dependencies' => ['jquery'],
'frontend' => true,
'backend' => false
],
// Admin scripts
[
'handle' => 'admin-script',
'file' => '/build/admin.build.js',
'dependencies' => ['jquery'],
'frontend' => false,
'backend' => true
]
]
];
});
Next Steps
Now that you understand how to manage styles and scripts:
- Create your first ACF block
- Learn about the CLI tool
- Explore block variations
- Learn about Production Builds
Ready to build something amazing? Let's create your first custom block!