SVG circle take all the height preserving aspectratio on any div size - css

The idea is to draw a circle in SVG that takes the whole height on the parent div whatever the size of the parent div. The width should be somehow ignored.
I've been working a bit with aspect ratio of SVG but this does not really work on all scenarios :
<div style='width:400px;height:100px'>
<svg width="100%" height="100%" viewbox="0 0 200 100" preserveAspectRatio="xMinYMin slice">
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="0" fill="red" />
<text x="100" y="50">Example SVG text 1</text>
</svg>
</div>
With the div width defined with 200px it's working.
Fiddle: https://jsfiddle.net/91sp2j0x/11/

Specifying a value of 50 for the r attribute will allow the nested svg element to maintain a 100% height of its containing (parent) element.
Code Snippet Demonstration:
.resize-demonstration {
resize: auto;
border: 1px solid gray;
box-sizing: border-box;
overflow:hidden;
}
.container-model {
border-right: 1px dashed gray;
}
<p>Resize the element below <u>vertically</u> or <u>horzontally</u> to demonstrate the intended behaviour</p>
<p><em>Note:</em> the <code>svg</code> has been wrapped in an containing element for <em>user-friendly resizing</em> (interaction with the resizing icon in the bottom-right corner), this is <strong>only for the sake of demonstration</strong> and should not be considered required.</p>
<div class="resize-demonstration" style="height: 100px">
<div style='width:50px;height:100%;overflow:hidden;' class="container-model">
<svg height="100%" viewbox="0 0 200 100" preserveAspectRatio="xMinYMin meet">
<circle cx="50" cy="50" r="50" stroke="black" stroke-width="0" fill="red" />
<text x="100" y="50">100px width : Nothing is visible</text>
</svg>
</div>
</div>
Updated JSFiddle

Is this what you would like to happen? I set the height of the div for each of the divs to different heights, and set the divs to display: inline-block so that the width is not 100%, as divs usually are by default, since they are block elements. That way the height of the SVG will be the height of the div.
<div style='height:200px;display:inine-block;overflow:hidden'>
<svg height="100%" viewbox="0 0 200 100" preserveAspectRatio="xMinYMin meet">
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="0" fill="red" />
<text x="100" y="50">200px h</text>
</svg>
</div>
<div style='height:500px;display:inine-block;overflow:hidden'>
<svg height="100%" viewbox="0 0 200 100" preserveAspectRatio="xMinYMin meet">
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="0" fill="red" />
<text x="100" y="50">500px h</text>
</svg>
</div>
<div style='height:300px;display:inine-block;overflow:hidden'>
<svg height="100%" viewbox="0 0 200 100" preserveAspectRatio="xMinYMin meet" >
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="0" fill="red" />
<text x="100" y="50">300px h</text>
</svg>
</div>
https://jsfiddle.net/suefeng/v14e7b81/2/

with preserveAspectRatio="none" and svg{width:100%} will give 100% adjusted height.
svg{
width: 100%;
}
<div style='width:200px;height:100px;overflow:hidden'>
<svg height="100%" viewbox="0 0 200 100" preserveAspectRatio="none">
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="0" fill="red" />
<text x="100" y="50">200px w: cut text</text>
</svg>
</div>
<div style='width:500px;height:100px;overflow:hidden'>
<svg height="100%" viewbox="0 0 200 100" preserveAspectRatio="none">
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="0" fill="red" />
<text x="100" y="50">500px w: full visible text</text>
</svg>
</div>
<div style='width:50px;height:100px;overflow:hidden'>
<svg height="100%" viewbox="0 0 200 100" preserveAspectRatio="none" >
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="0" fill="red" />
<text x="100" y="50">100px width : Nothing is visible</text>
</svg>
</div>

If i understood right, u want to have the circle with the radius of the height...
I did that successfully like so (if i understood what u asked correctly):
<div style='width:800px;height:120px;'>
<svg viewbox="0 -10 200 140" preserveAspectRatio="xMinYMin slice"> /* just remove the height and the width from the svg, it will take the parameters from the div... */
<circle cx="18%" cy="18%" r="18%" stroke="black" stroke-width="0" fill="red" />
<text x="100" y="50">Example SVG text 1</text>
</svg>
</div>

Related

Apply :hover to all children of an svg group

How do I get all the elements of an svg group to change their fill color on hover?
The example below does not work at all. If I use .sgroup circle:hover only the circle under the pointer works not both.
.sgroup:hover {
fill: green;
}
<div>
<svg width="200" height="200">
<g class="sgroup">
<circle cx="50" cy="50" fill="pink" r="10" ></circle>
<circle cx="150" cy="150" fill="purple" r="10" ></circle>
</g>
</svg>
</div>
Please see below. I assume this is what you're looking for?
.sgroup:hover circle {
fill: green;
}
<div>
<svg width="200" height="200">
<g class="sgroup">
<circle cx="50" cy="50" fill="pink" r="10" ></circle>
<circle cx="150" cy="150" fill="purple" r="10" ></circle>
</g>
</svg>
</div>

clip-path url fails to find id

I have an SVG that I am trying to use to clip a div, but the id I give to the <clipPath> tag does not work.
I have tried changing the ID, and have made sure that the SVG does indeed exist in the same file, and the ID is visible.
The svg is like so:
<svg id="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 149.559">
<defs>
<clipPath id="clipper">
<g id="svgg" stroke="none" fill-rule="evenodd">
<path id="path0" d= .../>
<path id="path1" d= .../>
<path id="path2" d= .../>
<path id="path3" d= .../>
<path id="path4" d= .../>
</g>
</clipPath>
</defs>
</svg>
I added the <defs> and <clipPath> tag so I could use the svg I had as a clipping mask.
The html element being used is:
<div class="logo-bg" style="clipPath: url(#clipper)"></div>
the div does have a width and height.
Within developer tools, the css property of the div I am trying to clip with clip-path: url(#clip-id) shows "could not load the image". Ideally I would be able to clip the div with the SVG.
here's the code I am working with: https://jsfiddle.net/mzLtsqva/6/
I am new to working with SVGs and so would appreciate any help to solve this issue.
Inside the <clipPath> don't wrap the paths in a group element.
In the next example I'm using a clipping path that is not working: #no and one that is working: #yes. In the one that is not working I'm wrapping the elements inside in a <g> element.
svg{border:1px solid;}
<svg width="250" height="250" viewBox="0 0 250 250" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<rect id="rect" x ="0" y ="0" height ="150" width ="70" style ="stroke:#000;" transform="translate(90, 50)"/>
<clipPath id="no">
<g>
<use xlink:href="#rect" fill="none"></use>
<use xlink:href="#rect" fill="none" transform="rotate(60 125 125)"></use>
<use xlink:href="#rect" fill="none" transform="rotate(-60 125 125)"></use>
</g>
</clipPath>
</defs>
<image xlink:href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/222579/beagle400.jpg" height="250" width="250" x="-15" y ="50" clip-path="url(#no)"></image>
</svg>
<svg width="250" height="250" viewBox="0 0 250 250" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<clipPath id="yes">
<use xlink:href="#rect" fill="none"></use>
<use xlink:href="#rect" fill="none" transform="rotate(60 125 125)"></use>
<use xlink:href="#rect" fill="none" transform="rotate(-60 125 125)"></use>
</clipPath>
</defs>
<image xlink:href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/222579/beagle400.jpg" height="250" width="250" x="-15" y ="50" clip-path="url(#yes)"></image>
</svg>

Fill SVG path with colour but on hover fade-in pattern

I am trying to add an SVG image (in this case a flag of Belgium) as the fill of an SVG path (actually an ellipse). On hover, the ellipse's fill has to transition into red. In other words, the fill SVG has to 'fade out'. I tried it in a way I'd do it with CSS, but neither the SVG pattern nor the transition seem to work. I tried on Chrome and Firefox.
svg ellipse {
fill: url(#img1);
transition: fill 400ms;
}
svg:hover ellipse {
fill: red;
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events" version="1.1" height="480" width="640" viewBox="0 0 640 480">
<defs>
<pattern x="0" y="0" id="img1" height="480" width="640" viewBox="0 0 640 480">
<g fill-rule="evenodd" stroke-width="1pt">
<path d="M0 0h213.335v479.997H0z" />
<path fill="#ffd90c" d="M213.335 0H426.67v479.997H213.335z" />
<path fill="#f31830" d="M426.67 0h213.335v479.997H426.67z" />
</g>
</pattern>
</defs>
<rect fill="none" stroke="blue" x="1" y="1" width="640" height="480"/>
<ellipse stroke="black" stroke-width="5" cx="400" cy="200" rx="350" ry="150" />
</svg>
You can't transition fill like that because the two fills are not something that can be interpolated smoothly between.
What you need to do is have two versions of the ellipse, one on top of the other. Then either fade in or out the top one.
.visible-on-hover {
transition: opacity 400ms;
opacity: 0;
}
.visible-on-hover:hover {
opacity: 1;
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events" version="1.1" height="480" width="640" viewBox="0 0 640 480">
<defs>
<pattern x="0" y="0" id="img1" height="1" width="1"
viewBox="0 0 640 480" preserveAspectRatio="xMidYMid slice">
<g fill-rule="evenodd" stroke-width="1pt">
<path d="M0 0h213.335v479.997H0z" />
<path fill="#ffd90c" d="M213.335 0H426.67v479.997H213.335z" />
<path fill="#f31830" d="M426.67 0h213.335v479.997H426.67z" />
</g>
</pattern>
</defs>
<rect fill="none" stroke="blue" x="1" y="1" width="640" height="480"/>
<ellipse stroke="black" stroke-width="5" cx="400" cy="200" rx="350" ry="150" fill="url(#img1)"/>
<ellipse stroke="black" stroke-width="5" cx="400" cy="200" rx="350" ry="150" fill="red" class="visible-on-hover"/>
</svg>

Hovering over transparent SVGs

How do I get hover to work robustly with transparent SVG polygons?
In the code below, you'll see that the second triangle isn't readily recognizing :hover (and it fails completely when stroke attribute is deleted or none'd). In the third triangle, hover starts to work with transparency, but only near the text.
<html><head><style>
body { background-color: Green }
polygon:hover {
fill:Red;
}
g:hover polygon {
fill:Red;
}
</style></head><body>
<svg width="300px" height="600px" viewBox="0 0 100 200" xmlns="http://www.w3.org/2000/svg" version="1.1">
<polygon fill="white" stroke="black" stroke-width="0.5px" points="0,0 100,0 100,100 0,0" />
<polygon fill="none" stroke="black" stroke-width="0.5px" points="0,0 0,100 100,100 0,0" />
<g>
<polygon fill="none" stroke="black" stroke-width="0.5px" points="0,100 100,100 100,200 0,100" />
<text x="50" y="150" font-family="Verdana" font-size="30">hi</text>
</g>
</svg>
</body></html>
I've confirmed this over Chrome, Firefox, and Safari. Any ideas (that'll work across most browsers)?
For each element state the fill color as fill="red", and set 0 as the fill opacity fill-opacity="0". On hover change the fill-opacity to 1:
body {
background-color: Green
}
polygon:hover {
fill-opacity: 1;
}
g:hover polygon {
fill-opacity: 1;
}
<svg width="300px" height="600px" viewBox="0 0 100 200" xmlns="http://www.w3.org/2000/svg" version="1.1">
<polygon fill="white" stroke="black" stroke-width="0.5px" points="0,0 100,0 100,100 0,0" />
<polygon fill="red" fill-opacity="0" stroke="black" stroke-width="0.5px" points="0,0 0,100 100,100 0,0" />
<g>
<polygon fill="red" fill-opacity="0" stroke="black" stroke-width="0.5px" points="0,100 100,100 100,200 0,100" />
<text x="50" y="150" font-family="Verdana" font-size="30">hi</text>
</g>
</svg>
Another approach is to use pointer-events="all".
With pointer-events you can control wich part of your shape reacts to pointer-events, independently of its fill or stroke.
circle:nth-of-type(1) {
pointer-events: fill
}
circle:nth-of-type(2) {
pointer-events: all
}
circle:nth-of-type(3) {
pointer-events: stroke
}
circle:nth-of-type(4) {
pointer-events: none
}
circle:hover {
fill: red;
stroke: blue
}
<svg width="300px" height="300px" viewBox="0 0 100 100">
<circle cx="25" cy="25" r="20" fill="none" stroke="red" stroke-width="5" />
<circle cx="75" cy="25" r="20" fill="none" stroke="none" stroke-width="5" />
<circle cx="25" cy="75" r="20" fill="green" stroke="none" stroke-width="5" />
<circle cx="75" cy="75" r="20" fill="green" stroke="red" stroke-width="5" />
</svg>

How to resize SVG clip-path?

I am using an SVG as a mask for an image and I'm trying to resize it. I tried indicating the width & height (to 100) but it still doesn't scale. Just remains the same size.
Codepen Demo
This is the SVG code:
<svg height="100" width="100">
<defs>
<clipPath id="svgPath">
<path fill="#EDEBEA" d="M468.855,234.292H244.117V9.439L468.855,234.292z" />
<path fill="#EDEBEA" d="M6.864,8.939h224.73v224.733L6.864,8.939z" />
<path fill="#EDEBEA" d="M244.118,469.73V245.005h224.737L244.118,469.73z" />
<path fill="#EDEBEA" d="M231.594,245.005V469.73H6.863L231.594,245.005z" />
</clipPath>
</defs>
</svg>
Firts, when you set the width and height attributes to 100, it makes the svg 100px high and wide. If you want the svg to be full width, you need to give it 100% width.
Second, as commented by #Paulie_D you need to give a value to the viewbox attribute to provide a scale and coordinate system for the elements in your svg. Here is an example with viewbox="0 0 500 500" and width="30%" :
<svg viewbox="0 0 500 500" width="30%" >
<defs>
<clipPath id="svgPath">
<path fill="#EDEBEA" d="M468.855,234.292H244.117V9.439L468.855,234.292z" />
<path fill="#EDEBEA" d="M6.864,8.939h224.73v224.733L6.864,8.939z" />
<path fill="#EDEBEA" d="M244.118,469.73V245.005h224.737L244.118,469.73z" />
<path fill="#EDEBEA" d="M231.594,245.005V469.73H6.863L231.594,245.005z" />
</clipPath>
</defs>
<image xlink:href="http://i.stack.imgur.com/3DR2G.jpg" x="0" y="0" height="500" width="500" style="clip-path: url(#svgPath);"/>
</svg>
Output :

Resources