atelier/svg

PHP library for SVG manipulation, optimization, and morphing: parsing, building, styling, transforms, validation, and sanitization

Maintainers

Package info

github.com/ateliersvg/svg

pkg:composer/atelier/svg

Fund package maintenance!

smnandre

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

dev-main 2026-04-06 02:25 UTC

This package is not auto-updated.

Last update: 2026-04-07 00:45:33 UTC


README

CI License: MIT PHP 8.3+

Designed precisely. Built to scale.

A PHP library for SVG manipulation, optimization, and morphing. Parse, build, style, transform, validate, sanitize, and animate SVG graphics with a type-safe, fluent API.

Quick Start | Features | Use Cases | Documentation

Installation

composer require atelier/svg

Requires PHP 8.3+.

Quick Start

use Atelier\Svg\Svg;

Svg::create(300, 200)
    ->rect(0, 0, 300, 200, ['fill' => '#1e293b'])
    ->circle(150, 100, 60, ['fill' => '#3b82f6'])
    ->text(150, 180, 'Atelier SVG', ['text-anchor' => 'middle', 'fill' => '#fff'])
    ->optimize()
    ->save('output.svg');

Load, query, modify, save:

$svg = Svg::load('input.svg');

$svg->getDocument()
    ->querySelectorAll('circle')
    ->fill('#3b82f6')
    ->stroke('#000')
    ->strokeWidth(2);

$svg->optimize()->save('output.svg');

Features

Elements

Full SVG 1.1 element support: shapes, text, groups, symbols, markers, gradients, filters, clipping, masking, and animation: all as typed PHP classes.

$text = TextElement::create(10, 30, 'Hello');

$builder = new TspanBuilder($text);
$builder->add('Bold', 0, ['font-weight' => 'bold'])
    ->add('and italic', 10, ['font-style' => 'italic']);
$symbol = SymbolBuilder::createSymbol($document, 'icon-star', '0 0 24 24');
SymbolBuilder::useSymbol($document, 'icon-star', 10, 10);

$marker = MarkerBuilder::arrow($document, 'arrow-end', '#000', 10);
AnimationBuilder::fadeIn($element, '1s');
AnimationBuilder::rotate($element, 0, 360, '2s');

Elements documentation: Shapes, text, structural elements, selectors, accessibility

Filters & Effects

26+ filter primitives, linear and radial gradients, patterns, clipping, and masking: with fluent builders.

FilterBuilder::createDropShadow($document, 'shadow', 2, 2, 4, '#000', 0.3);

FilterBuilder::create($document, 'glow')
    ->gaussianBlur(3, 'SourceAlpha', 'blur')
    ->flood('#3b82f6', 0.8, 'color')
    ->composite('in', 'color', 'blur', 'glow')
    ->blend('normal', 'SourceGraphic', 'glow')
    ->addToDefs();
GradientBuilder::horizontal($document, 'sunset', '#ff6b6b', '#feca57');

GradientBuilder::createLinear($document, 'custom')
    ->from(0, 0)->to(100, 100)
    ->addStop(0, '#3b82f6')
    ->addStop(50, '#8b5cf6', 0.8)
    ->addStop(100, '#ec4899')
    ->addToDefs();

Filters documentation: Gradients: Clipping & Masking

Paths

Type-safe path building, geometric analysis, distance metrics, and simplification.

$data = PathBuilder::startAt(10, 10)
    ->lineTo(50, 50)
    ->curveTo(250, 50, 300, 50, 350, 100)
    ->arcTo(50, 50, 0, false, true, 500, 100)
    ->closePath()
    ->toData();

$analyzer = new PathAnalyzer($data);
$length = $analyzer->getLength();
$bbox = $analyzer->getBoundingBox();
$inside = $analyzer->containsPoint(new Point(25, 25));

Path documentation: Building, analysis, transforms, simplification

Optimization

A configurable pipeline with 40+ passes, inspired by SVGO. Four presets, or build your own.

Svg::load('input.svg')->optimize()->save('output.svg');

Before:

<svg width="100.00000" height="100.00000" viewBox="0.00 0.00 100.00 100.00">
  <rect x="10.00000" y="20.00000" width="80.00000" height="60.00000"
        fill="black" stroke="none" opacity="1.0" />
</svg>

After:

<svg width="100" height="100" viewBox="0 0 100 100">
  <rect x="10" y="20" width="80" height="60" fill="#000"/>
</svg>
$optimizer = new Optimizer(OptimizerPresets::default());      // Balanced
$optimizer = new Optimizer(OptimizerPresets::aggressive());   // Maximum reduction
$optimizer = new Optimizer(OptimizerPresets::safe());         // Conservative
$optimizer = new Optimizer(OptimizerPresets::accessible());   // Keeps a11y metadata

Optimization documentation: Passes, presets, custom pipelines

Security & Validation

Sanitize untrusted SVGs, validate against the spec, check accessibility.

Sanitizer::strict()->sanitize($document);   // Remove scripts, event handlers, JS URLs
Sanitizer::default()->sanitize($document);  // Balanced security
$validator = new Validator(ValidationProfile::strict());
$result = $validator->validate($document);

$broken = DocumentValidator::findBrokenReferences($document);
DocumentValidator::autoFix($document);
$issues = Accessibility::checkAccessibility($document);
Accessibility::setTitle($document, 'Sales Chart Q1 2025');
Accessibility::improveAccessibility($document);

Validation documentation: Sanitization: Accessibility

Morphing

Interpolate between SVG shapes with easing. Export to SMIL, CSS keyframes, or JavaScript.

$midPath = Morph::between($startPath, $endPath, 0.5);

$frames = Morph::create()
    ->from($startPath)
    ->to($endPath)
    ->withDuration(2000, 60)
    ->withEasing('ease-in-out')
    ->generate();

$doc = AnimationExporter::toAnimatedSVG($frames, ['duration' => 3]);
$css = AnimationExporter::toCSSKeyframes($frames, 'my-morph');

Morphing documentation: Interpolation, easing, exporting

Use Cases

Sanitize user-uploaded SVGs

Accept SVGs from users without risking XSS. Strip scripts and dangerous content, validate structure, optimize, and serve.

$svg = Svg::load($uploadedFile);
$document = $svg->getDocument();

Sanitizer::strict()->sanitize($document);
DocumentValidator::autoFix($document);

$svg->optimize()->save($outputPath);

Generate icon sprite sheets

Consolidate individual icon files into a single SVG sprite for fewer HTTP requests.

$icons = array_map(fn ($file) => Svg::load($file)->getDocument(), glob('icons/*.svg'));

$sprite = Document::merge($icons, ['strategy' => MergeStrategy::SYMBOLS]);
<svg><use href="sprite.svg#icon-home"/></svg>

Batch-process SVG assets

Optimize an entire directory of SVGs in a CI pipeline or build step.

$optimizer = new Optimizer(OptimizerPresets::aggressive());

foreach (glob('assets/svg/*.svg') as $file) {
    $document = (new DomLoader())->loadFromFile($file);
    $optimizer->optimize($document);
    (new CompactXmlDumper())->dumpToFile($document, $file);
}

Build charts and dashboards

Compose SVG documents programmatically: generate charts, combine them into layouts, add accessible metadata.

$chart = Svg::create(400, 300);

foreach ($data as $i => $value) {
    $height = $value * 2;
    $chart->rect($i * 50 + 10, 300 - $height, 40, $height, ['fill' => '#3b82f6']);
}

Accessibility::setTitle($chart->getDocument(), 'Monthly Revenue');
Accessibility::setDescription($chart->getDocument(), 'Bar chart showing revenue by month');

$chart->save('chart.svg');

Animate shape transitions

Morph between two SVG shapes and export as a self-contained animated SVG.

$star = Svg::load('star.svg')->getDocument()->querySelector('path');
$circle = Svg::load('circle.svg')->getDocument()->querySelector('path');

$frames = Morph::frames(
    Path::parse($star->getAttribute('d'))->getData(),
    Path::parse($circle->getAttribute('d'))->getData(),
    60,
    'ease-in-out',
);

$animated = AnimationExporter::toAnimatedSVG($frames, [
    'duration' => 2,
    'repeatCount' => 'indefinite',
]);

Documentation

  • Getting Started: Installation and quick start
  • Document Handling: Creating, loading, exporting, sanitization, validation
  • Elements: Shapes, text, animation, selectors, gradients, filters, clipping
  • Path Operations: Building, analysis, transforms, geometry, simplification
  • Styling: Layout, transforms, and values
  • Optimization: Passes and presets
  • Morphing: Interpolation, easing, exporting
  • Guides: Sanitization, batch processing, charts, animation

Contributing

Contributions are welcome! See CONTRIBUTING.md for guidelines.

License

Atelier SVG is open-source software licensed under the MIT License.