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>
ph0enix
  • 763
  • 2
  • 8
  • 23
Laurent
  • 21
  • 2

2 Answers2

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>
enxaneta
  • 31,608
  • 5
  • 29
  • 42
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>
ph0enix
  • 763
  • 2
  • 8
  • 23
  • 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 Jul 05 '22 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 Jul 05 '22 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](https://stackoverflow.com/questions/11682826/how-to-use-viewbox-when-height-of-svg-is-dynamically-changing) [Resource 2](https://stackoverflow.com/questions/19484707/how-can-i-make-an-svg-scale-with-its-parent-container) – ph0enix Jul 05 '22 at 13:47