Skip to content
Ruby SVG Image Builder
Branch: master
Clone or download
Type Name Latest commit message Commit time
Failed to load latest commit information.
assets hello icodi Dec 18, 2018
example_rails typo Dec 13, 2018
lib version bump Dec 15, 2018
spec remove unused spec fixture function May 10, 2019
.rspec initial commit May 27, 2016
.travis.yml update changelog Jul 31, 2018
Gemfile improve templates to avoid style tags if css is empty Dec 15, 2018
LICENSE newlines and bundler date fix Mar 16, 2017
Runfile improve examples readme and generator Aug 25, 2018
config.reek fix some code smalls and add reek todo Mar 10, 2018
victor.gemspec increase min required ruby from 2.0 to 2.3 Apr 23, 2019


Victor - Ruby SVG Image Builder

Gem Version Build Status Code Quality Maintainability

Victor is a direct Ruby-to-SVG builder. All method calls are converted directly to SVG elements.


Table of Contents


$ gem install victor

Or with bundler:

gem 'victor'


require 'victor'

svg = width: 140, height: 100, style: { background: '#ddd' } do 
  rect x: 10, y: 10, width: 120, height: 80, rx: 10, fill: '#666'
  circle cx: 50, cy: 50, r: 30, fill: 'yellow'
  circle cx: 58, cy: 32, r: 4, fill: 'black'
  polygon points: %w[45,50 80,30 80,70], fill: '#666'

  3.times do |i|
    x = 80 + i*18
    circle cx: x, cy: 50, r: 4, fill: 'yellow'
end 'pacman'



See the examples folder for several ruby scripts and their SVG output.


Initialize your SVG image:

require 'victor'
svg =

Any option you provide to will be added as an attribute to the main <svg> element. By default, height and width are set to 100%.

svg = width: '100%', height: '100%'
# same as just

svg = width: '100%', height: '100%', viewBox: "0 0 200 100"

Victor uses a single method (element) to generate all SVG elements:

svg.element :rect, x: 2, y: 2, width: 200, height: 200
# => <rect x="2" y="2" width="200" height="200"/>

But you can omit it. Calls to any other method, will be delegated to the element method, so normal usage looks more like this:

svg.rect x: 2, y: 2, width: 200, height: 200
# => <rect x="2" y="2" width="200" height="200"/>

In other words, these are the same:

svg.element :anything, option: 'value'
svg.anything option: 'value'

You can use the build method, to generate the SVG with a block do 
  rect x: 0, y: 0, width: 100, height: 100, fill: '#ccc'
  rect x: 20, y: 20, width: 60, height: 60, fill: '#f99'

If the value of an attribute is a hash, it will be converted to a style-compatible string:

svg.rect x: 0, y: 0, width: 100, height: 100, style: { stroke: '#ccc', fill: 'red' }
# => <rect x=0 y=0 width=100 height=100 style="stroke:#ccc; fill:red"/>

If the value of an attribute is an array, it will be converted to a space delimited string:

svg.path d: ['M', 150, 0, 'L', 75, 200, 'L', 225, 200, 'Z']
# => <path d="M 159 9 L 75 200 L 225 200 Z"/>

For SVG elements that have an inner content - such as text - simply pass it as the first argument:

svg.text "Victor", x: 40, y: 50
# => <text x="40" y="50">Victor</text>

You can also nest elements with blocks: do
  g font_size: 30, font_family: 'arial', fill: 'white' do
    text "Scalable Victor Graphics", x: 40, y: 50
# => <g font-size="30" font-family="arial" fill="white">
#      <text x="40" y="50">Scalable Victor Graphics</text>
#    </g>

Underscores in attribute names are converted to dashes:

svg.text "Victor", x: 40, y: 50, font_family: 'arial', font_weight: 'bold', font_size: 40
# => <text x="40" y="50" font-family="arial" font-weight="bold" font-size="40">
#      Victor
#    </text>

Composite SVG

Victor also supports the abiliy to combine several smaller SVG objects into one using the << operator or the #append method.

This operator expects to receive any object that responds to #to_s (can be another SVG object).

require 'victor'
include Victor

# Create a reusable SVG object
frame =
frame.rect x: 0, y: 0, width: 100, height: 100, fill: '#336'
frame.rect x: 10, y: 10, width: 80, height: 80, fill: '#fff'

# ... and another
troll = cx: 50, cy: 60, r: 24, fill: 'yellow'
troll.polygon points: %w[24,50 50,14 76,54], fill: 'red'

# Combine objects into a single image
svg = viewBox: '0 0 100 100'
svg << frame
svg << troll

# ... and save it 'framed-troll'



These two calls are identical:

svg << other
svg.append other

Another approach to a more modular SVG composition, would be to subclass Victor::SVG.

See the composite svg example or the subclassing example for more details.

Saving the Output

Generate the full SVG to a string with render:

result = svg.render

Or, save it to a file with save: 'filename'
# the '.svg' extension is optional

SVG Templates

The :default SVG template is designed to be a full XML document (i.e., a standalone SVG image). If you wish to use the output as an SVG element inside HTML, you can change the SVG template:

svg = template: :html 
# accepts :html, :default or a filename

You can also point it to any other template file:

svg = template: 'path/to/template.svg'

See the templates folder for an understanding of how templates are structured.


To add a CSS to your SVG, simply use the css command inside your build block, like this:

svg = do 
  css['.main'] = {
    stroke: "green", 
    stroke_width: 2,
    fill: "yellow"

  circle cx: 35, cy: 35, r: 20, class: 'main'

You can also set CSS by providing a hash:

svg.css = {
  '.bar': {
    fill: '#666',
    stroke: '#fff',
    stroke_width: 1
  '.negative': {
    fill: '#f66'
  '.positive': {
    fill: '#6f6'

Underscore characters will be converted to dashes (stroke_width becomes stroke-width).

If you need to add CSS statements , like @import, use the following syntax:

css['@import'] = [

When the value of the CSS attribute is an array, Victor will simply use the values of the array and prefix each of them with the key, so the above will result in two @import url(...) rows.

See the custom fonts example.

Using with Rails

See the example_rails folder.

Related Projects

Icodi is a Ruby gem that uses Victor to generate consistent random icon images, similar to GitHub's identicon.


You can’t perform that action at this time.