2

I want to create a svg that fills the browser window size and that contains 2 elements:

  • The first element is a vector logo that must stay in the center of the window (H and V) whatever the size of the window.
  • The second element, which comes on top of the first, is a rectangle with color gradient and transparency that must fill the entire window whatever the size of the window.

How can I merge the two svg elements into one to obtain what I want? Thanks!

example of expected final result

<svg
    xmlns="http://www.w3.org/2000/svg"
    width="100%"
    height="100%"
    viewBox="100 -600 2000 2500"
>
    <defs>  
        <filter id="blur">
            <feGaussianBlur stdDeviation="7" />
        </filter>
    </defs>
    <g id="logo" fill="#e5cd98" filter="url(#blur)">
        <polygon class="cls-1" points="514.86 528.38 850.86 280.38 898.86 432.38 1238.86 372.38 1720.86 528.38 1734.86 788.38 1390.86 752.38 1232.86 906.38 1048.86 936.38 934.86 606.38 588.86 676.38 514.86 528.38"/>
    </g>
</svg>

<svg
    xmlns="http://www.w3.org/2000/svg"
>
    <defs>
        <linearGradient id="g" x1="0%" x2="100%" y1="0%" y2="100%">
            <stop style="stop-color: #754C24;" offset="0" stop-opacity="0.8"/>
            <stop style="stop-color: #C7B299;" offset="1" stop-opacity="0.9"/>
        </linearGradient>
    </defs>
    <rect style="fill: url(#g);" width="100%" height="100%"/>
</svg>

2 Answers 2

1

The rect needs to use the values of the viewBox (viewBox ="100 -600 2000 2500")

<rect style="fill: url(#g);" x="100" y="-600" width="2000" height="2500"/>

In order to make it cover the whole window I'm using width="100vw" height="100vh" Also I use preserveAspectRatio="xMidYMid slice" This is preserving the aspect ratio and the entire viewport is covered by the viewBox.

xMidYMid - Force uniform scaling. Align the midpoint X value of the element's viewBox with the midpoint X value of the viewport. Align the midpoint Y value of the element's viewBox with the midpoint Y value of the viewport.

Slice - Since the aspect ratio of the viewBox does not allways match the viewport, some of the viewBox will extend beyond the bounds of the viewport. Whar I mean by this is that part of the rectangle will fall outside the svg canvas and will be sliced off.

Please read about the preserveAspectRatio attribute.

body{margin:0; padding:0;}
<svg
    xmlns="http://www.w3.org/2000/svg"
    width="100vw"
    height="100vh"
    viewBox="100 -600 2000 2500"
    preserveAspectRatio="xMidYMid slice"
>
    <defs>  
        <filter id="blur">
            <feGaussianBlur stdDeviation="7" />
        </filter>
    </defs>
    <g id="logo" fill="#e5cd98" filter="url(#blur)">
        <polygon class="cls-1"  points="514.86 528.38 850.86 280.38 898.86 432.38 1238.86 372.38 1720.86 528.38 1734.86 788.38 1390.86 752.38 1232.86 906.38 1048.86 936.38 934.86 606.38 588.86 676.38 514.86 528.38"/>
      
    </g>

    <defs>
        <linearGradient id="g" x1="0%" x2="100%" y1="0%" y2="100%">
            <stop style="stop-color: #754C24;" offset="0" stop-opacity="0.8"/>
            <stop style="stop-color: #C7B299;" offset="1" stop-opacity="0.9"/>
        </linearGradient>
    </defs>
 
    <rect style="fill: url(#g);" 
          x="100" y="-600" width="2000" height="2500"/>

</svg>

2
  • Many thanks! That works as it should. Great.
    – Laurent
    Commented Jul 5, 2022 at 14:26
  • @Laurent Please mark as answered and upvote accordingly.
    – Lee Taylor
    Commented Jul 5, 2022 at 14:34
0

The solution for superimposing two elements should be quite simple, just adding the two elements inside the same SVG in the proper order.

Since you are using viewBox, the centering can be achieved with a transform attribute applied to polygon, like this: transform: translate(-100px, 380px); (feel free to tweak the coordinates since it is centered by heart). This way, the resizing will not affected the polygon and it will always be centered.

The final code look like this:

<svg
    xmlns="http://www.w3.org/2000/svg"
    width="100%"
    height="100%"
    viewBox="100 -600 2000 2500"
>
    <defs>  
        <filter id="blur">
            <feGaussianBlur stdDeviation="7" />
        </filter>
    </defs>
    <g id="logo" fill="#e5cd98" filter="url(#blur)">
        <polygon style="transform: translate(-100px, 380px);" class="cls-1" points="514.86 528.38 850.86 280.38 898.86 432.38 1238.86 372.38 1720.86 528.38 1734.86 788.38 1390.86 752.38 1232.86 906.38 1048.86 936.38 934.86 606.38 588.86 676.38 514.86 528.38"/>
    </g>

    <defs>
        <linearGradient id="g" x1="0%" x2="100%" y1="0%" y2="100%">
            <stop style="stop-color: #754C24;" offset="0" stop-opacity="0.8"/>
            <stop style="stop-color: #C7B299;" offset="1" stop-opacity="0.9"/>
        </linearGradient>
    </defs>
    <rect style="fill: url(#g);" width="100%" height="100%"/>

</svg>
3
  • Thanks for looking at this for me. The logo is indeed centered on the rectangle. But, with your solution the rectangle (gradient) does not fill the entire browser window when we resize it. Any clue to solve this? Thanks.
    – Laurent
    Commented Jul 5, 2022 at 12:48
  • This is due to viewBox, you can set first two params (min-x and min-y) to 0,set the preserveAspectRatio="none" in SVG and adjust translate and scale values accordingly. This way rectangle will always fit the screen, but if the user changes the aspect ratio your polygon logo will get deformed (I don't know if this is the behaviour you accept).
    – ph0enix
    Commented Jul 5, 2022 at 13:46
  • Maintaining aspect ratio and position of polygon doesn't seem so simple, these answers might provide you with additional insight: Resource 1 Resource 2
    – ph0enix
    Commented Jul 5, 2022 at 13:47

Not the answer you're looking for? Browse other questions tagged or ask your own question.