Responsive <img> for svg has overflow - html

I am trying to have an <img src="*.svg"> tag to display (any) svg file, however with what I have so far there is some overflow of the svg's viewbox when it fills the width:
If I did not need absolute positioning, it works without any overlfow if you remove display: inline-block and use max-width and max-height, but since I need the image to fill its container, I have to use inline-block.
Thanks in advance for any help .
#inner-map {
display: inline-block;
position: relative;
}
#map-svg {
border-style: solid;
}
#map-svg img {
width: 100%;
height: 80vh;
display: block;
}
#pog-outer {
position: absolute;
}
#pog-inner {
position: absolute;
left:-9px;
top:-9px;
}
<div id="inner-map">
<div id="pog-outer" style="top:58.794%;left:28.915%">
<div id="pog-inner">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="18" height="18">
<defs>
<radialGradient id="Shiny" cx="0.5" cy="0.5" r="0.5" fx="0.25" fy="0.25">
<stop offset="0%" stop-color="#FFFFFF" />
<stop offset="50%" stop-color="#DD3333" />
<stop offset="75%" stop-color="#990000" />
<stop offset="100%" stop-color="#000000" />
</radialGradient>
</defs>
<circle r="6" cx="9" cy="9" fill="url(#Shiny)" />
</svg>
</div>
</div>
<div id="map-svg">
<img src="https://upload.wikimedia.org/wikipedia/commons/d/d5/North_America_laea_location_map.svg">
</div>
</div>

Per the question's comments you want the image to fill the whole container and then if the aspect ratio of the image and its container differ, some edges of the image would overflow and are no longer be visible.
So to get that we'd want the image to have have preserveAspectRatio="xMidYMid slice" on its root element but unfortunately it doesn't. It doesn't have that attribute at all and the default if you have a viewBox is preserveAspectRatio="xMidYMid meet"
We'll need to override that value by using an SVG fragment identifier.
To make the example below more obvious I've also changed the width to width: 70vh; so it always overflows. You probably don't want to do that.
#inner-map {
display: inline-block;
position: relative;
}
#map-svg {
border-style: solid;
}
#map-svg img {
width: 70vh;
height: 80vh;
display: block;
}
#pog-outer {
position: absolute;
}
#pog-inner {
position: absolute;
left:-9px;
top:-9px;
}
<div id="inner-map">
<div id="pog-outer" style="top:58.794%;left:28.915%">
<div id="pog-inner">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="18" height="18">
<defs>
<radialGradient id="Shiny" cx="0.5" cy="0.5" r="0.5" fx="0.25" fy="0.25">
<stop offset="0%" stop-color="#FFFFFF" />
<stop offset="50%" stop-color="#DD3333" />
<stop offset="75%" stop-color="#990000" />
<stop offset="100%" stop-color="#000000" />
</radialGradient>
</defs>
<circle r="6" cx="9" cy="9" fill="url(#Shiny)" />
</svg>
</div>
</div>
<div id="map-svg">
<img src="https://upload.wikimedia.org/wikipedia/commons/d/d5/North_America_laea_location_map.svg#svgView(preserveAspectRatio(xMidYMid slice))">
</div>
</div>

You can replace the height: 80vh; with height: 80% in the element and this way it's going to always hide the non-blue svg part and without making any overflow.
#inner-map {
display: inline-block;
position: relative;
}
#map-svg {
border-style: solid;
}
#map-svg img {
width: 100%;
height: 80%;
display: block;
}
#pog-outer {
position: absolute;
}
#pog-inner {
position: absolute;
left:-9px;
top:-9px;
}
<div id="inner-map">
<div id="pog-outer" style="top:58.794%;left:28.915%">
<div id="pog-inner">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="18" height="18">
<defs>
<radialGradient id="Shiny" cx="0.5" cy="0.5" r="0.5" fx="0.25" fy="0.25">
<stop offset="0%" stop-color="#FFFFFF" />
<stop offset="50%" stop-color="#DD3333" />
<stop offset="75%" stop-color="#990000" />
<stop offset="100%" stop-color="#000000" />
</radialGradient>
</defs>
<circle r="6" cx="9" cy="9" fill="url(#Shiny)" />
</svg>
</div>
</div>
<div id="map-svg">
<img src="https://upload.wikimedia.org/wikipedia/commons/d/d5/North_America_laea_location_map.svg">
</div>
</div>

Related

Change svg gradient to solid white with a transition?

I can't seem to get a transition on an SVG when I hover it.
The svg has a gradient inside ... but I want it to transition to white on hover.
Any ideas?
svg {
width: 20px;
height: 20px;
path {
transition: fill 0.4s ease;
&:hover {
fill: $white;
}
}
}
<svg id="Facebook_icon" data-name="Facebook icon" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="8.713" height="16.779" viewBox="0 0 8.713 16.779">
<defs>
<linearGradient id="linear-gradient" x1="0.5" x2="0.5" y2="1" gradientUnits="objectBoundingBox">
<stop offset="0" stop-color="#f7d077"/>
<stop offset="0.112" stop-color="#ffefaa"/>
<stop offset="0.269" stop-color="#ffdb74"/>
<stop offset="0.552" stop-color="#dba846"/>
<stop offset="0.808" stop-color="#dba846"/>
<stop offset="1" stop-color="#f4cd6f"/>
</linearGradient>
</defs>
<path id="Icon" d="M8.713,2.785H7.134c-1.238,0-1.479.588-1.479,1.451v1.9H8.61L8.225,9.125H5.655v7.653H2.576V9.125H0V6.142H2.576v-2.2A3.594,3.594,0,0,1,6.412,0a21.049,21.049,0,0,1,2.3.117Z" fill="url(#linear-gradient)"/>
</svg>
For CSSOM, a gradient is of type <image>, and you can't transition from an <image> to a solid <color>.
What you can do however is to transition from an <image> to an other <image>, so we should have been able to transition between two gradients, but as of this writing it seems no browser supports transitioning between svg gradients and none supports CSS gradients as fill value.
What does work however is to transition the stop-color values of the <stop> elements.
For this to happen only when the <path> is hovered, I did change the structure of your svg.
svg {
width: 20px;
height: 20px;
}
svg stop {
transition: stop-color 0.4s ease;
}
svg path:hover ~ defs stop {
stop-color: white;
}
<svg id="Facebook_icon" data-name="Facebook icon" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="8.713" height="16.779" viewBox="0 0 8.713 16.779">
<path id="Icon" d="M8.713,2.785H7.134c-1.238,0-1.479.588-1.479,1.451v1.9H8.61L8.225,9.125H5.655v7.653H2.576V9.125H0V6.142H2.576v-2.2A3.594,3.594,0,0,1,6.412,0a21.049,21.049,0,0,1,2.3.117Z"
fill="url(#linear-gradient)"/>
<defs>
<linearGradient id="linear-gradient" x1="0.5" x2="0.5" y2="1" gradientUnits="objectBoundingBox">
<stop offset="0" stop-color="#f7d077"/>
<stop offset="0.112" stop-color="#ffefaa"/>
<stop offset="0.269" stop-color="#ffdb74"/>
<stop offset="0.552" stop-color="#dba846"/>
<stop offset="0.808" stop-color="#dba846"/>
<stop offset="1" stop-color="#f4cd6f"/>
</linearGradient>
</defs>
</svg>

SVG - It is possible to add stroke-dasharray Gradient or transparent form one side

I have created an SVG animation in which I am allowing stroke-dasharray to move. Is it possible that I can add a gradient to the tail of stroke-dasharray and keep one side transparent as you can see in the example?
.svg-main {
width: 700px;
margin: 30px auto;
position: relative;
}
svg#svga {
position: absolute;
top: 0;
left: auto;
bottom: auto;
right: auto;
}
.st2{fill:none;stroke:#cccccc;stroke-width:6;}
.sd1{fill:none;stroke:#000000; stroke-width:6;stroke-linecap:round;}
.circ{fill:#000000; }
<div class="svg-main">
<svg id="svga" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="300px" height="200px" viewBox="0 0 685 310">
<g class="st2">
<path id="loop-normal" d="M343.6,156.5c11,15.9,104.6,147.2,181.9,147.6c0.1,0,0.8,0,1,0c82.1-0.3,148.6-67,148.6-149.2
c0-82.4-66.8-149.2-149.2-149.2c-77.2,0-170.8,131-182.2,147.5c-0.8,1.1-1.6,2.3-2.1,3.1c-10.6,15.3-104.8,147.8-182.4,147.8
C76.7,304.2,9.9,237.4,9.9,155S76.7,5.8,159.1,5.8c77.2,0,170.7,130.9,182.2,147.5C342.1,154.4,342.9,155.6,343.6,156.5z"/>
</g>
<use class="sd1" stroke-dasharray="200 1710" xlink:href="#loop-normal">
<animate attributeName="stroke-dashoffset"
from="200" to="-1710"
begin="0s" dur="10s"
repeatCount="indefinite"/>
</use>
<circle id="plug" class="circ" cx="0" cy="0" r="7"/>
<animateMotion
xlink:href="#plug"
dur="10s"
rotate="auto"
repeatCount="indefinite"
calcMode="linear"
keyTimes="0;1"
keyPoints="0;1">
<mpath xlink:href="#loop-normal"/>
</animateMotion>
</svg>
</div>
Please refer this
.svg-main {
width: 700px;
margin: 30px auto;
position: relative;
}
svg#svga {
position: absolute;
top: 0;
left: auto;
bottom: auto;
right: auto;
}
.st2{fill:none;stroke:#cccccc;stroke-width:6;}
.sd1{fill:none; stroke-width:6;stroke-linecap:round;}
.circ{fill:#000000; }
<div class="svg-main">
<svg id="svga" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="300px" height="200px" viewBox="0 0 685 310">
<defs>
<linearGradient id="gradient" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#000000" />
<stop offset="100%" stop-color="#ffffff" />
</linearGradient>
</defs>
<g class="st2" >
<path id="loop-normal" d="M343.6,156.5c11,15.9,104.6,147.2,181.9,147.6c0.1,0,0.8,0,1,0c82.1-0.3,148.6-67,148.6-149.2
c0-82.4-66.8-149.2-149.2-149.2c-77.2,0-170.8,131-182.2,147.5c-0.8,1.1-1.6,2.3-2.1,3.1c-10.6,15.3-104.8,147.8-182.4,147.8
C76.7,304.2,9.9,237.4,9.9,155S76.7,5.8,159.1,5.8c77.2,0,170.7,130.9,182.2,147.5C342.1,154.4,342.9,155.6,343.6,156.5z"/>
</g>
<use class="sd1" stroke="url(#gradient)" stroke-dasharray="200 1710" xlink:href="#loop-normal">
<animate attributeName="stroke-dashoffset"
from="200" to="-1710"
begin="0s" dur="10s"
repeatCount="indefinite"/>
</use>
<circle id="plug" class="circ" cx="0" cy="0" r="7"/>
<animateMotion
xlink:href="#plug"
dur="10s"
rotate="auto"
repeatCount="indefinite"
calcMode="linear"
keyTimes="0;1"
keyPoints="0;1">
<mpath xlink:href="#loop-normal"/>
</animateMotion>
</svg>
</div>

How to give the linear-gradient in svg as a background color for a div?

I have an svg like
<svg>
<linearGradient id="SVGID_124_" gradientUnits="userSpaceOnUse" x1="205.2935" y1="707.9475" x2="206.9863" y2="707.9475" gradientTransform="matrix(41.432 0 0 -41.432 -8114.9512 30139.9746)">
<stop offset="0" style="stop-color:#0071BC"/>
<stop offset="3.780070e-02" style="stop-color:#0071BC"/>
<stop offset="0.6151" style="stop-color:#00538B"/>
<stop offset="0.784" style="stop-color:#004C86"/>
<stop offset="0.9966" style="stop-color:#003B7C"/>
<stop offset="1" style="stop-color:#003B7C"/>
</linearGradient>
</svg>
I'm not sure how can I give this linear gradient as a background for a button. I tried the following, but I don't know how to give gradient transform in css.
.btn {
background: linear-gradient(to right, #0071BC 0%, #0071BC 37.80070%, #00538B 061.51%, #004C86 078.4%, #003B7C 099.66%, #003B7C 100%);
color: white;
border-radius: 8px;
/* border: 1px solid #00538B; */
width: 95%;
height: 25px;
padding: 0px;
}
<button class="btn">button</button>
Can somebody help?
It is expected to look like this
But i'm getting something like:
This is a close gradient in css.
.btn {
background: linear-gradient(to right, #0071bd 0%,#0171bb 39%,#016db5 41%,#005691 58%,#005691 59%,#01538b 61%,#014c86 78%,#003c7b 100%);
border-radius: 5px;
color: #fff;
border: none;
}
<button class="btn">Closed</button>
In generally, I'm using the gradient editor by colorzila to generate gradients from image / css / manually. May there are another tools.
You can use the SVG itself, BUT:
You have to make sure that the gradient's coordinates are right and feet to the element (aka .btn) which in this case, not.
You need to convert it to base64.
In the below snippet, for quick fixing, I created a script that read the svg in the html and convert it to base64 so you can tuning your gradient with it.
Also, I changed a little the SVG syntax, Take a look:
const svg = document.querySelector('svg').outerHTML;
const base64 = window.btoa(svg);
document.querySelector('.btn').style.backgroundImage = `url(data:image/svg+xml;base64,${base64})`;
.btn {
background: top repeat-x;
background-size: cover;
border-radius: 5px;
color: #fff;
border: none;
}
<button class="btn">Closed</button>
<svg width="1000px" height="30000px" xmlns="http://www.w3.org/2000/svg" style="display: none">
<linearGradient id="SVGID_124_" gradientUnits="userSpaceOnUse" x1="205.2935" y1="707.9475" x2="206.9863" y2="707.9475" gradientTransform="matrix(41.432 0 0 -41.432 -8114.9512 30139.9746)">
<stop offset="0" style="stop-color:#0071BC"/>
<stop offset="3.780070e-02" style="stop-color:#0071BC"/>
<stop offset="0.6151" style="stop-color:#00538B"/>
<stop offset="0.784" style="stop-color:#004C86"/>
<stop offset="0.9966" style="stop-color:#003B7C"/>
<stop offset="1" style="stop-color:#003B7C"/>
</linearGradient>
<g>
<rect fill="url(#SVGID_124_)" stroke-width="0" x="0" y="0" width="100%" height="100%" />
</g>
</svg>

SVG take up 400% of screensize

I'm trying to make my SVG take up 400% of the screen width and height so I can move it to change the gradient:
SVG
html, body {
margin:0;
padding:0;
overflow:hidden;
}
svg {
position:fixed;
top:0;
bottom:0;
left:0;
right:0;
height: 400%;
width: 400%;
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<linearGradient id="LinearGradient" x1="0%" y1="0%" x2="100%" y2="100%" spreadMethod="pad" gradientTransform="rotate(45)">
<stop offset="0%" stop-color="#00cc00" stop-opacity="1" />
<stop offset="100%" stop-color="#006600" stop-opacity="1" />
</linearGradient>
</defs>
<rect x="0" y="0" width="100%" height="100%" style="fill:url(#LinearGradient);" />
</svg>
However, this doesn't even fill it up 100% of the screen, yet alone 400%!
Just add your SVG CSS inside svg:not(:root). Check updated Snippet below
html, body {
margin:0;
padding:0;
height: 100%;
}
/*svg {
position:fixed;
top:0;
bottom:0;
left:0;
right:0;
height: 400%;
width: 400%;
}*/
svg:not(:root) {
width: 400%;
height: 400%;
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<linearGradient id="LinearGradient" x1="0%" y1="0%" x2="100%" y2="100%" spreadMethod="pad" gradientTransform="rotate(45)">
<stop offset="0%" stop-color="#00cc00" stop-opacity="1" />
<stop offset="100%" stop-color="#006600" stop-opacity="1" />
</linearGradient>
</defs>
<rect x="0" y="0" width="100%" height="100%" style="fill:url(#LinearGradient);" />
</svg>

Linear Gradient SVG 3 colors increase the width of the middle color

I have a linear gradient with the below code
<svg width="120" height="240" >
<linearGradient id="dsp" x1="0" x2="0" y1="0" y2="1">
<stop class="stop1" offset="0%"/>
<stop class="stop2" offset="50%"/>
<stop class="stop3" offset="100%"/>
</linearGradient>
<style type="text/css">
.stop1 { stop-color: red; }
.stop2 { stop-color: yellow; stop-opacity: 0.7; }
.stop3 { stop-color: green; }
</style>
Now I want to increase the height of the middle color that is the yellow color.
I tried to increase the offset value of yellow color but instead of increasing the width the color band shifts downwards.
I want that the red and green should contain only 10% of the height of the SVG in below format
Red >> 15%
yellow >> 70%
green >> 15%
This is the color distribution expected.
just add two more stops in between the start/end stop and the middle...
EDIT based on squeamish ossifrages comment
.stop1 { stop-color: red; }
.stop2 { stop-color: yellow; stop-opacity: 0.7; }
.stop3 { stop-color: green; }
<svg width="120" height="240" >
<linearGradient id="dsp" x1="0" x2="0" y1="0" y2="1">
<stop class="stop1" offset="0%"/>
<stop class="stop2" offset="20%"/>
<stop class="stop2" offset="80%"/>
<stop class="stop3" offset="100%"/>
</linearGradient>
<rect x="0" y="0" width="240" height="120" fill="url(#dsp)"/>
</svg>