Rendering Recursive SVG files

recursion, rendering, svg

Solution

You can reference a definition repeatedly. Though this isn't infinite recursion, it is much simpler than the nesting method referenced in the other answer/comments.

See these examples (Example 1, Example 2) by Dudley Storey that I found:

svg {
    display: block;
    width: 40%;
    margin: 0 auto;
}
polygon, line { 
    fill: none; stroke: #32679D; 
    stroke-width: 5px; 
    vector-effect: non-scaling-stroke;
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 750 750">
<defs>
    <g id="hex" transform="rotate(30 375 375)">
        <polygon points="229.3,627.5 83.6,375.5 229.3,123.5 520.7,123.5 666.4,375.5 520.7,627.5" />
        <line x1="229.3" y1="123.5" x2="520.7" y2="627.5"/>
        <line x1="666" y1="375.5" x2="84" y2="375.5"/>
        <line x1="520.7" y1="123.5" x2="229.3" y2="627.5"/>
    </g>
</defs> 
<use xlink:href="#hex" />
<use xlink:href="#hex" transform="translate(470.75, 172) scale(.25)" />
<use xlink:href="#hex" transform="translate(470.75, 390.5) scale(.25)" />
<use xlink:href="#hex" transform="translate(91.75, 172) scale(.25)" /> 
<use xlink:href="#hex" transform="translate(91.75, 390.5) scale(.25)" />    
<use xlink:href="#hex" transform="translate(155, 281.25) scale(.25)" />
<use xlink:href="#hex" transform="translate(407.5, 281.25) scale(.25)" />
<use xlink:href="#hex" transform="translate(281.25, 63.5) scale(.25)" />
<use xlink:href="#hex" transform="translate(281.25, 500) scale(.25)" />
<use xlink:href="#hex" transform="translate(344.5, 172) scale(.25)" />
<use xlink:href="#hex" transform="translate(218, 172) scale(.25)" />
<use xlink:href="#hex" transform="translate(344.5, 390.5) scale(.25)" />
<use xlink:href="#hex" transform="translate(218, 390.5) scale(.25)" />
</svg>

It is possible to get more complicated by nesting:

body {
    margin: 0;
    min-height: 100vh;
    background: #fff;
}
svg {
    display: block;
    width: 100%;
    min-height: 100vh;
}
polygon { 
    fill: none; 
    stroke: rgba(0,0,0,0.3); 
    stroke-width: 3; 
}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
    <pattern id="tesselation" patternUnits="userSpaceOnUse" width="562.6" height="325" patternTransform="scale(.75)">
    <g id="group">
        <polygon points="281.4,0 375.2, 162.5 281.4, 325 187, 161.5" id="base" />
        <g id="basetwist" >
            <use xlink:href="#base" transform="rotate(90 280 162.5) translate(116, 67) scale(.58)" id="base_level1" />
            <g id="diamond"> 
                <use xlink:href="#base" transform="translate(188.85, 108) scale(.33)" id="base_level2" />
                <g id="sidediamond">
                    <use xlink:href="#base_level1" transform="translate(188.85, 108) scale(.33)" id="base_level3" />
                        <use xlink:href="#base_level2" transform="translate(188.85, 108) scale(.33)" id="base_level4" />
                            <use xlink:href="#base_level3" transform="translate(188.85, 108) scale(.33)" /> 
                                <use xlink:href="#base_level4" transform="translate(188.85, 108) scale(.33)" />
                </g>
            </g>
            <use xlink:href="#sidediamond" transform="translate(62,0)" />
            <use xlink:href="#sidediamond" transform="translate(-62,0)" />
            <use xlink:href="#diamond" transform="translate(0,-107)" />
            <use xlink:href="#diamond" transform="translate(0, 107)" />
        </g>
    </g>
    <g id="tesselation">
        <use xlink:href="#group" />
        <use xlink:href="#group" transform="rotate(60 281 0)" />
        <use xlink:href="#group" transform="rotate(-60 281 0)" />
        <use xlink:href="#group" transform="rotate(-60 281 325)" />
        <use xlink:href="#group" transform="rotate(60 281 325)" />
        <g id="vert">
            <use xlink:href="#group" transform="translate(-282, -162)" />
            <use xlink:href="#group" transform="translate(-282, 162)" />
        </g>
        <use xlink:href="#vert" transform="translate(564, 0)" />
    </g>
    </pattern>
</defs>
<rect width="100%" height="100%" fill="url(#tesselation)" />    
</svg>

EDIT: He has blog posts describing how he created them:

- https://thenewcode.com/1141/Recursive-SVG-Designs-Part-1

- https://thenewcode.com/1147/Recursive-SVG-Patterns-Part-2

Problem

Is there an existing renderer that can intelligently handle a recursive (that is, self-referential) svg file? For example, this code from this question: ``` <svg width="100%" height="100%" viewBox="-100 -100 200 200" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <circle cx="-50" cy="-50" r="30" style="fill:red" /> <image x="10" y="20" width="80" height="80" xlink:href="recursion.svg" /> </svg> ``` is not rendered properly in Firefox, Chrome, or Inkscape - but it doesn't seem that hard to make a renderer that keeps track of how many time it's opened a particular file, and stop after some sane number of iterations... (If one doesn't exist, where might I go looking if I wanted to code one myself?)

Original source

Related problems