Search by

jdz / cssmaker

jdz

Build minified css file from less sources

1.0.4 2026-10-11 23:47 UTC

This package is auto-updated.

Last update: 2026-10-11 23:47:27 UTC


README

A modern PHP library for building optimized CSS files from LESS sources with advanced preprocessing, autoprefixing, and minification capabilities.

Features

  • ๐ŸŽจ LESS Compilation: Process LESS files with variables, mixins, and nesting
  • ๐Ÿš€ PostCSS Integration: Automatic vendor prefix addition and CSS optimization
  • ๐Ÿงน CSS Optimization: Comment removal, whitespace cleaning, and minification
  • ๐Ÿ“ Modular Organization: Structured approach with categorized file types
  • ๐Ÿ”ง Font Management: Built-in font loading and @font-face generation
  • โšก Performance: Efficient temporary file handling and process pipeline
  • ๐Ÿงช Fully Tested: Comprehensive test suite with modular test architecture
  • ๐Ÿ”„ Fluent Interface: Method chaining for clean, readable code

Installation

composer require jdz/cssmaker

Node.js Dependencies

CssMaker requires Node.js tools for CSS processing. Install them automatically:

composer npm:local
composer npm:global

Dependencies

jdz/data is required for data handling and processing. jdz/output is required for output handling and logging. jdz/fontmanager is optional (suggested): the bundled example uses it to manage local fonts before handing them to addFont(); the @font-face generation itself is built in.

Quick Start

<?php

use JDZ\CssMaker\CssMaker;

// Initialize with optional custom output handler
$cssMaker = new CssMaker();

// Set build paths (creates directory structure automatically)
$cssMaker->setBuildPaths('/path/to/project', 'build');

// Add LESS files by category
$cssMaker->addLessFiles([
    'variables' => ['config/variables.yml'],
    'mixins' => ['src/mixins.less'],
    'normalize' => ['src/normalize.less'],
    'structure' => ['src/layout.less', 'src/components.less'],
    'mobile' => ['src/mobile.less'],
    'print' => ['src/print.less']
]);

// Add fonts (optional)
// see jdz/fontmanager for more infos
$fontData = (object) [
    'id' => 'roboto',
    'family' => 'Roboto',
    'display' => 'swap',
    'style' => 'normal',
    'weight' => '400',
    'files' => ['fonts/roboto.woff2', 'fonts/roboto.woff']
];
$cssMaker->addFont($fontData);

// Process and build CSS (creates: theme.less, theme.css, theme.min.css)
$cssMaker->process('theme');

File Categories

CssMaker organizes LESS files into logical categories processed in order. You can extend the CssMaker class and add your own categories as needed.

Core Categories

  • variables: LESS/YAML variables and configuration
  • mixins: Reusable LESS mixins and functions
  • normalize: CSS reset and normalization rules
  • animations: CSS animations and keyframes
  • fonts: Font declarations and @font-face rules

Layout Categories

  • structure: Main layout and component styles
  • icons: Icon fonts and SVG styles

Responsive Categories

  • mobile: Mobile-first styles (wrapped in @media(max-width: @screen-breakpoint - 1px))
  • screen: Desktop styles (wrapped in @media(min-width: @screen-breakpoint))
  • queries: Custom media queries
  • print: Print-specific styles (wrapped in @media print)

PostCSS

process() runs postcss on the compiled CSS with two plugins, autoprefixer and postcss-discard-comments, reading it with postcss-safe-parser. No configuration file is involved: the plugins are passed on the command line, and the safe parser goes through resources/postcss-safe-syntax.cjs (postcss-cli 11 cannot load it as --parser).

The autoprefixer target is a list of browserslist queries, handed to postcss in the BROWSERSLIST environment variable, which takes precedence over any .browserslistrc or package.json key:

$cssMaker->getBrowserslist(); // ['> .5%', 'last 2 versions', 'not dead'] (default)

$cssMaker->setBrowserslist(['defaults']);
$cssMaker->setBrowserslist(['> .1%', 'not dead']);

Advanced Features

Variable Management

use JDZ\CssMaker\Variables;

// Variables support YAML files
$variables = new Variables();
$variables->set('primary-color', '#3498db');
$variables->set('screen-breakpoint', '768px');

// YAML format (variables.yml):
# primary_color: "#3498db"
# screen_breakpoint: "768px"
# font_sizes:
#   small: "12px"
#   medium: "16px"
#   large: "24px"

Custom Output Handler

use JDZ\Output\Output;

$output = new Output();
$output->setVerbosity(32); // all: Output::VERBOSITY_ALL on jdz/output 1.x, Verbosity::ALL on 2.x

$cssMaker = new CssMaker($output);
// Now you'll see detailed processing information

Processing Pipeline

The CssMaker follows a structured build pipeline:

  1. ๐Ÿ”ง Preparation

    • Load variables from YAML/LESS files
    • Validate directory structure
    • Initialize temporary file management
  2. ๐Ÿ“ Content Merging

    • Merge variables into LESS format
    • Combine mixins and normalize files
    • Add font @font-face declarations
    • Process files by category with media query wrapping
  3. โš™๏ธ LESS Compilation

    • Compile merged LESS to CSS using lessc
    • Handle variables, mixins, nesting, and functions
    • Generate source CSS file
  4. ๐ŸŽฏ PostCSS Processing

    • Apply autoprefixer for vendor prefixes, for the setBrowserslist() target
    • Drop comments with postcss-discard-comments
    • Read the CSS with postcss-safe-parser
  5. ๐Ÿงน Optimization

    • Remove CSS comments and unnecessary whitespace
    • Clean and normalize formatting
    • Apply minification
  6. ๐Ÿ“ฆ Output Generation

    • Generate final CSS file
    • Create minified version (.min.css)
    • Clean up temporary files

Directory Structure

project/
โ””โ”€โ”€ build/                 # Output directory
    โ”œโ”€โ”€ css/               # Generated CSS files
    โ”‚   โ”œโ”€โ”€ theme.less       # Merged LESS
    โ”‚   โ”œโ”€โ”€ theme.css        # Compiled CSS
    โ”‚   โ””โ”€โ”€ theme.min.css    # Minified CSS
    โ””โ”€โ”€ fonts/             # Copied font files
    โ””โ”€โ”€ images/            # Copied image files
โ”œโ”€โ”€ fonts/                 # Font source files (optional, used by the font manager)
โ”œโ”€โ”€ less/                  # LESS source files
โ”‚   โ”œโ”€โ”€ variables.yml        # LESS variables
โ”‚   โ”œโ”€โ”€ mixins.less          # LESS mixins
โ”‚   โ”œโ”€โ”€ normalize.less       # CSS normalization
โ”‚   โ”œโ”€โ”€ structure.less       # Main styles
โ”‚   โ”œโ”€โ”€ mobile.less          # Mobile styles
โ”‚   โ””โ”€โ”€ print.less           # Print styles
โ”œโ”€โ”€ tmp/                   # Temporary files (auto-created)

Error Handling

CssMaker provides comprehensive error handling:

use JDZ\CssMaker\Exception\LessMakerException;

try {
    $cssMaker->process('theme');
} catch (LessMakerException $e) {
    // Handle CssMaker-specific errors
    echo "CSS Build Error: " . $e->getMessage();
} catch (\Exception $e) {
    // Handle general errors
    echo "General Error: " . $e->getMessage();
}

Common Error Scenarios:

  • Missing required directories
  • Invalid LESS syntax
  • Missing Node.js dependencies (lessc, postcss, minify)
  • A font file that addFont() cannot find or copy (Font file not found: โ€ฆ, Font file not copied: โ€ฆ to โ€ฆ)
  • File permission issues
  • Malformed configuration files

Testing

CssMaker includes a comprehensive test suite. The tests that run lessc, postcss and minify need the Node.js tools (composer npm:local or npm:global).

# Run all tests
composer test

# Run specific test classes
composer test:cssmaker
composer test:cleaner  
composer test:variables
composer test:merger

Example Usage

See the complete working example:

composer example

The example demonstrates:

  • Full project setup with directory structure
  • Extended CssMaker class
  • Configuration file usage
  • Font integration
  • Multiple file type processing
  • Error handling

Browser Support

The default target, > .5%, last 2 versions, not dead:

  • Modern Browsers: Chrome, Firefox, Safari, Edge (last 2 versions)
  • Market Share: Browsers with > 0.5% usage
  • Security: Excludes browsers without security updates
  • Mobile: iOS Safari, Chrome Mobile

Customize with setBrowserslist():

// browserslist's own defaults
$cssMaker->setBrowserslist(['defaults']);

// Conservative approach
$cssMaker->setBrowserslist(['> 1%', 'last 3 versions', 'not dead']);

// Modern approach
$cssMaker->setBrowserslist(['> 0.25%', 'last 2 versions', 'not dead']);

Requirements

  • PHP: >= 8.2
  • Composer: For dependency management
  • Node.js + npm: for the lessc, postcss (postcss-cli, autoprefixer, postcss-safe-parser, postcss-discard-comments) and minify command line tools โ€” composer npm:local or composer npm:global installs them. If they are not on the PATH, pass their directory (with a trailing slash) as the second constructor argument: new CssMaker($output, '/path/to/node_modules/.bin/').

PHP Dependencies

  • jdz/output: ^1.0 || ^2.0 (Output handling)
  • jdz/data: ^2.0 (Data processing)
  • symfony/yaml: ^7.4 (YAML parsing)
  • symfony/process: ^7.4 (External process execution)
  • jdz/fontmanager (Font management - optional, suggested)

Performance Tips

  1. Use file caching - Only rebuild when source files change
  2. Minimize file count - Combine related LESS files
  3. Optimize images - Use appropriate formats and compression
  4. Monitor build time - Profile with verbose output
  5. Cache font files - Reuse font declarations across builds

Troubleshooting

Common Issues

"lessc command not found"

npm install -g less

"postcss command not found"

npm install -g postcss postcss-cli autoprefixer postcss-safe-parser postcss-discard-comments

"minify command not found"

npm install -g minify

"Permission denied" errors

chmod 755 /path/to/build/directory

"LESS compilation failed"

  • Check LESS syntax in source files
  • Verify variable names and references
  • Ensure all imported files exist

Debug Mode

Enable verbose output for troubleshooting:

use JDZ\Output\Output;

$output = new Output();
$output->setVerbosity(32); // all: Output::VERBOSITY_ALL on jdz/output 1.x, Verbosity::ALL on 2.x

$cssMaker = new CssMaker($output);
// Detailed processing information will be displayed

License

MIT License - see LICENSE file for details.

Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Add tests for new functionality
  4. Ensure all tests pass (composer test)
  5. Follow PSR-12 coding standards
  6. Update documentation as needed
  7. Commit changes (git commit -m 'Add amazing feature')
  8. Push to branch (git push origin feature/amazing-feature)
  9. Open a Pull Request

Changelog

  • 1.0.4 โ€” postcss() applies its plugins: the arguments were out of order (--config swallowed --no-map, postcss.json was read as a second input) and postcss-cli 8+ never reads a postcss.json, so autoprefixer and postcss-discard-comments never ran. The plugins are now passed on the command line, postcss-safe-parser through a syntax wrapper (resources/postcss-safe-syntax.cjs), and the autoprefixer target is setBrowserslist() (default > .5%, last 2 versions, not dead), passed in BROWSERSLIST; postcss.json and .browserslistrc are gone. The unminified CSS loses its comments and the spaces before { and after :. A font file that addFont() cannot find or copy throws a LessMakerException with its path (it was logged and skipped, leaving an @font-face pointing at nothing). jdz/output ^1.0 || ^2.0.

  • 1.0.3 โ€” The cleaner no longer strips // "comments": lessc already removes them, and the pattern cut every URL (url(https://โ€ฆ), SVG data URIs) to the end of its line. Each /* */ comment ends at its own close (/**/ used to swallow the next rule); no-break spaces and non-UTF-8 bytes survive (removeSpaces() was a TypeError on Latin-1). @font-face lists woff2 before ttf. A second process() on one maker merges the font themes once; minify writes through a build path with spaces; a font without an id throws its own error. trim() replaces mb_trim() (PHP 8.4 only, under php >=8.2).

  • 1.0.2 โ€” PHP >= 8.2, jdz/data ^2.0, Symfony ^7.4, PHPUnit 11; the cleaner also strips // single-line comments, and removes comments before collapsing whitespace.

  • 1.0.1 โ€” Output goes through jdz/output (the bundled Output class is gone); test suite split per feature.

  • 1.0.0 โ€” Initial release.

Support