Skip to Content

SVG

WebF provides comprehensive support for Scalable Vector Graphics (SVG), allowing you to create resolution-independent graphics that scale perfectly on any device. SVG can be used in multiple ways: inline elements, images, and backgrounds.

Using Inline SVG Elements

Inline SVG gives you full control and interactivity through the DOM.

Basic SVG Example

function Logo() { return ( <svg width="100" height="100" viewBox="0 0 100 100"> <circle cx="50" cy="50" r="40" fill="#4F46E5" /> <text x="50" y="55" textAnchor="middle" fill="white" fontSize="20"> SVG </text> </svg> ); }

Common SVG Shapes

function Shapes() { return ( <svg width="400" height="200" viewBox="0 0 400 200"> {/* Rectangle */} <rect x="10" y="10" width="80" height="60" fill="#EF4444" rx="5" /> {/* Circle */} <circle cx="150" cy="40" r="30" fill="#10B981" /> {/* Ellipse */} <ellipse cx="250" cy="40" rx="40" ry="25" fill="#F59E0B" /> {/* Line */} <line x1="320" y1="10" x2="380" y2="70" stroke="#8B5CF6" strokeWidth="3" /> {/* Polygon (Triangle) */} <polygon points="50,120 80,180 20,180" fill="#EC4899" /> {/* Polyline */} <polyline points="120,120 140,160 160,140 180,180" fill="none" stroke="#06B6D4" strokeWidth="3" /> {/* Path */} <path d="M 250 120 Q 280 140 250 180 Q 220 140 250 120" fill="#A855F7" /> </svg> ); }

Using SVG with <img /> Tag

Load SVG files as images for simple, non-interactive graphics:

function SVGImage() { return ( <div> {/* Local SVG file */} <img src="/icons/logo.svg" alt="Logo" width="100" height="100" /> {/* Remote SVG file */} <img src="https://example.com/icon.svg" alt="Icon" width="50" height="50" /> {/* With lazy loading */} <img src="/images/illustration.svg" alt="Illustration" loading="lazy" width="400" height="300" /> </div> ); }

Benefits of SVG as <img />

  • Simple to use
  • Cacheable like other images
  • No DOM overhead
  • Supports lazy loading
  • Works with responsive images

Limitations

  • No JavaScript interaction with SVG content
  • Cannot style internal SVG elements with CSS
  • Cannot animate internal SVG elements

Using SVG as CSS Background

SVG can be used in CSS backgrounds for patterns, icons, and decorative elements:

Background Image

/* External SVG file */ .icon { width: 50px; height: 50px; background-image: url('/icons/star.svg'); background-size: contain; background-repeat: no-repeat; } /* With positioning */ .decorated { background-image: url('/patterns/dots.svg'); background-position: center; background-size: cover; }

Inline SVG in CSS (Data URI)

.checkmark { width: 24px; height: 24px; background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="%234F46E5" d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>'); background-size: contain; }

Tailwind CSS with SVG Backgrounds

function BackgroundExample() { return ( <div className="w-full h-64 bg-cover bg-center" style={{ backgroundImage: "url('/patterns/waves.svg')" }} > <div className="p-6 text-white"> Content over SVG background </div> </div> ); }

SVG Gradients and Filters

Linear Gradients

function GradientExample() { return ( <svg width="300" height="200" viewBox="0 0 300 200"> <defs> <linearGradient id="gradient1" x1="0%" y1="0%" x2="100%" y2="0%"> <stop offset="0%" stopColor="#4F46E5" /> <stop offset="100%" stopColor="#EC4899" /> </linearGradient> </defs> <rect x="10" y="10" width="280" height="180" fill="url(#gradient1)" rx="10" /> </svg> ); }

Radial Gradients

function RadialGradientExample() { return ( <svg width="200" height="200" viewBox="0 0 200 200"> <defs> <radialGradient id="radial1"> <stop offset="0%" stopColor="#FBBF24" /> <stop offset="100%" stopColor="#F59E0B" /> </radialGradient> </defs> <circle cx="100" cy="100" r="80" fill="url(#radial1)" /> </svg> ); }

Filters and Effects

function FilterExample() { return ( <svg width="300" height="200" viewBox="0 0 300 200"> <defs> {/* Drop shadow */} <filter id="shadow"> <feDropShadow dx="2" dy="2" stdDeviation="3" floodOpacity="0.3" /> </filter> {/* Blur effect */} <filter id="blur"> <feGaussianBlur stdDeviation="2" /> </filter> </defs> <circle cx="80" cy="100" r="40" fill="#4F46E5" filter="url(#shadow)" /> <circle cx="220" cy="100" r="40" fill="#EF4444" filter="url(#blur)" /> </svg> ); }

SVG Icons

Icon Component System

// Icon component function Icon({ name, size = 24, color = 'currentColor', ...props }) { const icons = { heart: ( <path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z" /> ), star: ( <path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z" /> ), menu: ( <path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z" /> ), }; return ( <svg width={size} height={size} viewBox="0 0 24 24" fill={color} {...props} > {icons[name]} </svg> ); } // Usage function App() { return ( <div> <Icon name="heart" size={32} color="#EF4444" /> <Icon name="star" size={24} color="#FBBF24" /> <Icon name="menu" size={28} /> </div> ); }

SVG Animations

CSS Animations on SVG

function AnimatedSVG() { return ( <svg width="200" height="200" viewBox="0 0 200 200"> <style>{` @keyframes rotate { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } .spinner { transform-origin: center; animation: rotate 2s linear infinite; } `}</style> <circle className="spinner" cx="100" cy="100" r="40" fill="none" stroke="#4F46E5" strokeWidth="8" strokeDasharray="60 200" /> </svg> ); }

React-Controlled Animations

import { useState, useEffect } from 'react'; function ProgressCircle({ progress = 0 }) { const radius = 40; const circumference = 2 * Math.PI * radius; const offset = circumference - (progress / 100) * circumference; return ( <svg width="100" height="100" viewBox="0 0 100 100"> {/* Background circle */} <circle cx="50" cy="50" r={radius} fill="none" stroke="#E5E7EB" strokeWidth="8" /> {/* Progress circle */} <circle cx="50" cy="50" r={radius} fill="none" stroke="#4F46E5" strokeWidth="8" strokeDasharray={circumference} strokeDashoffset={offset} transform="rotate(-90 50 50)" style={{ transition: 'stroke-dashoffset 0.3s ease' }} /> {/* Text */} <text x="50" y="55" textAnchor="middle" fontSize="16" fill="#111"> {progress}% </text> </svg> ); }

SVG Patterns

Creating Reusable Patterns

function PatternExample() { return ( <svg width="400" height="300" viewBox="0 0 400 300"> <defs> {/* Dot pattern */} <pattern id="dots" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse"> <circle cx="10" cy="10" r="2" fill="#94A3B8" /> </pattern> {/* Stripe pattern */} <pattern id="stripes" x="0" y="0" width="10" height="10" patternUnits="userSpaceOnUse"> <rect x="0" y="0" width="5" height="10" fill="#E0E7FF" /> <rect x="5" y="0" width="5" height="10" fill="#C7D2FE" /> </pattern> </defs> <rect x="10" y="10" width="180" height="280" fill="url(#dots)" /> <rect x="210" y="10" width="180" height="280" fill="url(#stripes)" /> </svg> ); }

Responsive SVG

Using viewBox for Scalability

function ResponsiveSVG() { return ( <div className="w-full max-w-md"> {/* SVG scales to container width while maintaining aspect ratio */} <svg viewBox="0 0 400 300" className="w-full h-auto" > <rect x="10" y="10" width="380" height="280" fill="#4F46E5" rx="10" /> <text x="200" y="160" textAnchor="middle" fill="white" fontSize="32"> Responsive SVG </text> </svg> </div> ); }

Preserving Aspect Ratio

function AspectRatioSVG() { return ( <svg viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet" className="w-32 h-32" > <circle cx="50" cy="50" r="40" fill="#EF4444" /> </svg> ); }

SVG vs Canvas

Choose the right tool for your use case:

Use SVG when:

  • You need scalable, resolution-independent graphics
  • You want DOM-based interactivity (hover, click on individual elements)
  • You need accessibility features (screen readers can access SVG content)
  • You have a moderate number of elements (up to hundreds)
  • You need styling with CSS
  • You want to animate individual elements

Use Canvas when:

  • You need to render many elements (thousands of objects)
  • You’re creating pixel-based graphics or effects
  • You need high-performance real-time rendering
  • You’re building games or complex data visualizations
  • You need to manipulate pixels directly

Best Practices

1. Optimize SVG Files

# Use SVGO to optimize SVG files npm install -g svgo svgo input.svg -o output.svg

2. Use Semantic Naming

// ✅ Good - clear naming <svg aria-labelledby="chart-title"> <title id="chart-title">Monthly Sales Chart</title> <rect ... /> </svg> // ❌ Bad - no context <svg> <rect ... /> </svg>

3. Keep ViewBox Simple

// ✅ Good - simple viewBox <svg viewBox="0 0 100 100"> // ❌ Avoid - complex viewBox makes scaling harder <svg viewBox="47.3 83.2 234.8 156.4">

4. Use CSS for Styling

// ✅ Good - CSS for reusable styles <svg className="icon-primary"> <circle className="fill-current" /> </svg> // ❌ Less flexible - inline styles <svg> <circle fill="#4F46E5" /> </svg>

Accessibility

Make SVG accessible for all users:

function AccessibleSVG() { return ( <svg role="img" aria-labelledby="logo-title logo-desc" viewBox="0 0 100 100" > <title id="logo-title">Company Logo</title> <desc id="logo-desc">A blue circle with white text</desc> <circle cx="50" cy="50" r="40" fill="#4F46E5" /> <text x="50" y="55" textAnchor="middle" fill="white">Logo</text> </svg> ); } // For decorative SVG function DecorativeSVG() { return ( <svg aria-hidden="true" viewBox="0 0 100 100"> <circle cx="50" cy="50" r="40" fill="#E5E7EB" /> </svg> ); }

Next Steps