csssvg

Brickwork linearGradient pattern for SVG rect element


I've been playing around width linearGradients in SVGs to try and render a brickwork pattern on an SVG rect element.

But i cannot get my head around the repeat spreadMethod and if it can even be used to make a pattern like https://codepen.io/lina994/pen/mdwpodZ . I appreciate this could be done with lots of sperate SVG elements but I would prefer to do this cleanly to make it easy to alter the SVG.

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 1000">
    <defs>
        <linearGradient spreadMethod="repeat" id="brick1" x1="0%" y1="0%" x2="0%" y2="10%">
            <stop class="mortar" offset="0"/>
            <stop class="mortar" offset="1%"/>
            <stop class="brick" offset="1%"/>
            <stop class="brick" offset="9%"/>
            <stop class="mortar" offset="9%"/>
            <stop class="mortar" offset="10%"/>
            <stop class="brick" offset="10%"/>
            <stop class="brick" offset="17%"/>

        </linearGradient>
        <linearGradient id="brick2" spreadMethod="repeat" x1="0%" x2="11%">
            <stop offset="0%" stop-color="transparent" />
            <stop offset="10%" stop-color="transparent" />
            <stop class="mortar" offset="10%" />
            <stop class="mortar" offset="11%" />
            <stop offset="11%" stop-color="transparent" />
        </linearGradient>
        <style>
            .ground {
                fill: #073605;
            }
            .fence {
                fill: #480d0d;
            }
            .front {
                fill: url(#brick1);
            }
            .front-mortar {
                fill: url(#brick2);
            }
            .brick {
                stop-color: #b00;
            }
            .mortar {
                stop-color: #bbb;
            }
            .side {
                fill: darkred;
            }
            .back-roof {
                fill: #901900;
            }
            .front-roof {
                fill: #a62f20;
            }
            .path {
                fill: brown;
            }
            .front-window {
                fill: white;
                height: 50px;
                width: 100px;
            }
            .tree-branches {
                fill: darkgreen;
                stroke: #38682d;
                stroke-width: 5px;
            }
            .tree-trunk {
                fill: brown;
                stroke: #552222;
                stroke-width: 5px;
            }
            .grass {
                fill: green;
            }
        </style>
    </defs>
    <title>Talihouse</title>
    <rect class="ground" height="500" width="1000" y="500" />
    <rect class="fence" height="20" y="480" width="1000" />
    <rect class="front" width="500" height="300" x="100" y="450" />
    <rect class="front-mortar" width="500" height="300" x="100" y="450" />
    <rect class="door" width="50" height="100" fill="black" x="330" y="650" />
    <polygon class="back-roof" points="600,450 550,350 650,250 700,300" />
    <polygon class="front-roof" points="600,450 550,350 150,350 100,450" />
    <polygon class="side" points="600,750 600,450, 700,300 700,500" />
    <polygon class="grass" points="100,750 50,900 600,900 740,500 700,500 600,750 " />
    <polygon class="path" points="320,750 300,800 83,800 66,850 350,850 390,750" />
    <g class="front-windows">
        <rect class="front-window" x="150" y="650" />
        <rect class="front-window" x="150" y="500" />
        <rect class="front-window" x="450" y="500" />
        <rect class="front-window" x="450" y="650" />
    </g>
</svg>


Solution

  • As suggested, using a pattern could be a simple solution. I declare a pattern with two rows of bricks. For now, I have only offset them by half.

    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1500 1500">
        <defs>
            <!-- Define the brick pattern -->
            <pattern id="brickPattern" width="75" height="50" patternUnits="userSpaceOnUse">
                <rect width="50" height="20" x="0" y="0" fill="#b00" />
                <rect width="50" height="20" x="25" y="24" fill="#b00" />
            </pattern>
        </defs>
    
        <rect fill="url(#brickPattern)" width="500" height="500"/>
    </svg>

    It is already clear that to achieve the brick pattern, need to split the second row of bricks into two parts for repetition: a starting and an ending element, and the gap between the bricks should be between the starting and ending elements.

    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1500 1500">
        <defs>
            <!-- Define the brick pattern -->
            <pattern id="brickPattern" width="75" height="50" patternUnits="userSpaceOnUse">
                <rect width="50" height="20" x="0" y="0" fill="#b00" />
                
                <!-- <rect width="50" height="20" x="25" y="24" fill="#b00" /> -->
                <rect width="25" height="20" x="0" y="24" fill="#b00" /> <!-- part end -->
                <rect width="25" height="20" x="50" y="24" fill="#b00" /> <!-- part start -->
            </pattern>
        </defs>
    
        <rect fill="url(#brickPattern)" width="500" height="500"/>
    </svg>

    Now just need to set the proper dimensions:

    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1500 1500">
        <defs>
            <!-- Define the brick pattern -->
            <pattern id="brickPattern" width="54" height="48" patternUnits="userSpaceOnUse">
                <rect width="50" height="20" x="0" y="0" fill="#b00" />
                
                <!-- <rect width="50" height="20" x="25" y="24" fill="#b00" /> -->
                <rect width="25" height="20" x="0" y="24" fill="#b00" /> <!-- part end -->
                <rect width="25" height="20" x="29" y="24" fill="#b00" /> <!-- part start -->
            </pattern>
        </defs>
    
        <rect fill="url(#brickPattern)" width="500" height="500"/>
    </svg>

    Note: I just wanted to demonstrate the quick logic, so I scaled down the SVG's size. The logic itself is a 2-row repeating pattern, where the second row needs to be split into a starting and an ending brick.