Interacting with SVG image files using Twig

What is the SVG file format and why should I care?

SVG stands for Scalable Vector Graphics.
It is a file format for vectorial images described using XML tags.

Since it is vectorial, it presents a few advantages:

  • it is lightweight
  • you can zoom it as much as you want without it getting blurry
  • you can dynamically modify it (colours, shapes)

Dynamically change your SVG using CSS

The SVG format can be directly included in a HTML document as a DOM element.
Each stroke or shape is an object that can own a class
Knowing this, we can add CSS styles for strokes and shapes, and dynamically modify the objects.

We will use the following SVG file to illustrate our examples (credits to Jean-Rémi Beaudoin for the very nice drawing skills!).

triangle

This is the content of the svg file:

<?xml version="1.0" encoding="UTF-8"?>
<svg
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   version="1.1"
   viewBox="0 0 100 100"
   height="100"
   width="100">
  <g
     transform="translate(0,-952.36216)">
    <path
       d="m 5,1021.1122 56.071429,-56.96433 -3.75,50.71433 z"
       class="my-path"
       fill="#9f9f9f" />
    <path
       d="M 96.607142,1036.8265 5,1021.1122 l 52.321429,-6.25 z"
       fill="#7a7a7a"
       class="my-path" />
    <path
       d="m 96.607142,1036.8265 -35.535713,-72.67863 -3.75,50.71433 z"
       fill="#e0e0e0"
       class="my-path" />
  </g>
</svg>

For example, this will fill every svg path of the image with red:

path {
    fill: #ff0000;
}

See the Pen wgKKMJ by Pierre Poupin (@Pierpo) on CodePen.

You can be more specific.
You can add classes to your SVG elements and select them independently:

.first-element {
    fill: #ff0000;
}
.second-element {
    fill: #00ff00;
}

You can even use the :hover and :active selectors, which is very nice to integrate nice buttons.

See the Pen EZadxE by Pierre Poupin (@Pierpo) on CodePen.

Using external SVG files

Naive approach

Most of the time, you won’t copy and paste your SVG directly in your HTML page.
You naturally want to import your SVG as an image.

The most intuitive way would be to include it this way:

<img src="my-svg.svg">

Which totally works for an SVG as it is.
However, including it like this prevents you from interacting with it.
The img field will make your browser import it as a black box, and no operation on anything inside it would be possible.
That means the above CSS examples would not work!

Unfortunately, you will get the same behaviour if you use background-image: 'my-svg.svg'.

One simple way using Twig

Thus, we want the SVG and all its sub-elements to be well determined parts of our DOM as well as our SVG to be an external file.

There’s a very simple way to do it using Twig! Simply use the source function in your template.

{{ source('my-svg.svg') }}

This will copy the text present in the SVG file and put it in your generated HTML, thus make it a proper recursive and editable DOM element.

That’s it!

Resources:

  • https://css-tricks.com/using-svg/

You liked this article? You'd probably be a good match for our ever-growing tech team at Theodo.

Join Us

  • Галина

    Oh! I download images to web/uploads/ directory. But can’t use svg from this directory – “Unable to find template “/uploads/597851d4d40e0.svg” (looked into: full_addressapp/Resources/views” (((

  • DadoHR

    You can copy this svg to src/AcmeBundle/Views/inline/597851d4d40e0.svg and then use {{ source(‘@AcmeBundle/inline/597851d4d40e0.svg’) }} to include this SVG inline.

  • Галина

    Thanks. Nice solution!
    I used twig extencion:
    {% if ‘svg’ in brand.image %}
    {{ get_svg_text( brand_image_path ~ ‘/’ ~ brand.image ) | raw }}
    {% else %}

    … ‘get_svg_text’ => new Twig_Function_Method($this, ‘get_svg_text’),…

    function get_svg_text( $path ){
    $request = $this->container->get(‘request’);
    $baseurl = $request->getScheme() . ‘://’ . $request->getHttpHost() . $request->getBasePath();
    return @file_get_contents( $baseurl.$path );
    }