Fill SVG on parent div hover (no JS) - html

I have 2 SVG paths and I would like them to change fill color when users rollover their parents did. I can get the hover working but only when users hover on the svg. I know it is easy with JS but I would prefer to stick with CSS.
<div class="button">
<svg width="100px" height="100px">
<circle cx="30" cy="30" r="20" style="stroke: black;"/>
</svg>
</div>
<div class="button">
<svg width="100px" height="100px">
<circle cx="30" cy="30" r="20" style="stroke: black;"/>
</svg>
</div>
CSS:
.button{
background-color:gray;
margin-bottom: 20px ;
}
svg{
fill:green;
}
svg:hover{
fill:blue;
}
Demo: http://jsfiddle.net/69g7K/

We can do this, by using parent:hover as selector to vary the CSS attributes of child1 and child2 which are within their respective parents..
Use the following for the CSS :
.button:hover .svg1{
fill:blue;
}
.button:hover .svg2{
fill:yellow;
}
Demo : jsFiddle

here is a trick if you have a more complex svg element, for instance if you have multiple paths, do the following:
<div class="your-class">
<svg [svg content...]
<path ...>
<path ...>
<path ...>
</div>
use css to look for paths not only something inside a specific path:
.your-class{
/* code without rover */
transition: 0.3s ease-in-out;
}
.your-class:hover path{
stroke: #C4C4C4; /* use stroke to color svg lines*/
/* use fill to color the inside */
also (maybe worth mentioning) if you your div to be only around the svg you can use the width: fit-content; for your div
hope it helps you out

svg {
fill: #444;
}​
just add a class to each SVG and use the css above something like this:
svg.svg1:hover {
fill: #666;
}​
svg.svg2:hover {
fill: #666;
}​
remove style="fill: yellow" for example from each SVG path otherweise it will overwrite your css
<svg class=svg1 width=150px height=150px>
<circle cx=64 cy=64 r=20>
</svg>
<svg class=svg2 width=150px height=150px>
<circle cx=64 cy=64 r=20>
</svg>
Demo:http://jsfiddle.net/GwWk5/
svg {
fill: red;
}
svg.svg1:hover {
fill: blue;
}
svg.svg2:hover {
fill: green;
}

Related

Start svg polyline exactly at right border of span element

I have a simple html file containing an SVG polyline:
Here's my code:
span {
border: 1px solid red;
}
polyline{
fill:none;
stroke:red;
stroke-width:3
}
<p>A block element containing an <span>inline element</span></p>
<svg height="200" width="500">
<polyline points="0,0 20,0 40,25" />
</svg>
I would like to start the polyline exactly at the midpoint of my span's right border. How can I do that?
This is a very basic idea: you give the svg position:absolute and the same size as the html element overlapped. You calculate the bounding client rect of the span and the position of the point where the polyline shpuld begin. Ypu either translate the polyline or you rewrite the points attribute so that it begins where you want it
let bcr = sp.getBoundingClientRect();
poly.setAttribute("transform",`translate(${bcr.x+bcr.width},${bcr.y+bcr.height/2})`)
svg {
outline: solid;
position: absolute;
top:0;left:0;
}
div {
width: 500px;
height: 200px;
}
span {
border: 1px solid red;
}
polyline {
fill: none;
stroke: red;
stroke-width: 3;
}
<div>
<p>A block element containing an <span id="sp">inline element</span></p>
</div>
<svg height="200" width="500">
<polyline id="poly" points="0,0 20,0 40,25" />
</svg>

Change size of SVG clipping mask on mouseover

I want to show images using a mask. I tried the css clip-path but because the browser support is that poor I want to use an svg for clipping. My question is how can i change the size of the mask on mousover?
Like here:
I am using this code at the moment:
<svg>
<defs>
<!--defines the shape to use for clipping-->
<circle id="circle" cx="100" cy="100" r="100" />
</defs>
<clipPath id="clip">
<!--creates the clipping mask from the shape-->
<use xlink:href="#circle" overflow="visible"></use>
</clipPath>
<!--group containing the image with clipping applied-->
<g clip-path="url(#clip)">
<image overflow="visible" xlink:href="model_detail.jpg"></image>
</g>
</svg
In your case, since you need to resize both the circle and the clipped image, you may scale the svg element on hover like so:
svg {
display: block;
position: absolute;
margin: auto;
top: 0;
bottom: 0;
left: 0;
right: 0;
transform: scale(1);
transition: transform 0.5s;
}
svg:hover {
transform: scale(1.5);
}
<svg viewBox="0 0 200 200" width="200">
<defs>
<!--defines the shape to use for clipping-->
<circle id="circle" cx="100" cy="100" r="100" />
</defs>
<clipPath id="clip">
<!--creates the clipping mask from the shape-->
<use xlink:href="#circle" overflow="visible"></use>
</clipPath>
<!--group containing the image with clipping applied-->
<g clip-path="url(#clip)">
<image overflow="visible" xlink:href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/222579/darwin300.jpg"></image>
</g>
</svg>
Please observe that I've added a viewBox and a width attribute to the svg. If you don't declare the viewBox and the width the svg element will have a size of 300px/150px and the part of the circle that falls outside the svg canvas will be cuted off.
UPDATE
The OP is commenting
I don't want to scale the image, just the mask. Is that possible?
This is how I would do it: In the next example I'm using transitions to scale the circle when you mouse over the svg element:
#c{transform: scale(1);
transition: transform 0.5s;}
svg:hover #c {
transform: scale(1.5);
}
Next comes a working example:
svg {
border: 1px solid;
display: block;
position: absolute;
margin: auto;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
#c{transform: scale(1);
transition: transform 0.5s;}
svg:hover #c {
transform: scale(1.5);
}
<svg viewBox="-150 -150 300 300" width="200">
<defs>
<clipPath id="clip">
<!--creates the clipping mask from the shape-->
<circle id="c" r="100" />
</clipPath>
</defs>
<!--group containing the image with clipping applied-->
<image clip-path="url(#clip)" id="img" xlink:href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/222579/darwin300.jpg" x="-150" y="-150" width="300" height="300"></image>
</svg>
You could do it easily with JavaScript, adding an eventlistener onMouseOver over a class.
However, if you need CSS, you can an animation that will do it,like this.
.zoom {
padding: 50px;
background-color: green;
transition: transform .2s; /* Animation */
width: 200px;
height: 200px;
margin: 0 auto;
}
.zoom:hover {
transform: scale(1.5); /* (150% zoom - Note: if the zoom is too large, it will go outside of the viewport) */
}
</style>
<div class="zoom"></div>

I want to implement SVG clip-path for SVG element

I want to implement SVG clip-path for SVG element. I have a DIV element in which I want to put SVG element which will act as a clipping mask, and also I have the separate SVG element that has an image to which the clipping mask will be applied.
The first problem I faced with is that clipping mask moves to the left top corner of the viewport but not located inside of the parent DIV element.
The second problem is that I want to make an image on the full screen not depending on the screen size.
Incorrect Mask Circle
Correct Mask Circle (what I want to have)
Do you have suggestions how to make it?
Thanks in advance!
html, body { margin:0; padding:0; overflow:hidden }
svg { position:absolute; top:0; left:0;}
.image-clip-src {
width: 100%;
height: 100%;
}
.svg-wrapper {
width: 72px;
height: 72px;
padding: 2.5em;
border: 1px solid #4D4F51;
margin: 0 auto;
border-radius: 50%;
overflow: hidden;
position: fixed;
top: 55%;
z-index: 9;
left: 64%;
transform: translateY(-50%);
cursor: pointer;
}
.clipped-image image {
clip-path: url(#clipping);
}
<svg class="clipped-image" width="100%" height="100%" viewBox="0 0 1440 960" preserveAspectRatio="xMinYMin meet">
<image class="image-clip-src" xlink:href="https://images.unsplash.com/photo-1526327227970-4bda49fa3489?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=3c4bce33d96df6b18af53fb2dae3363e&auto=format&fit=crop&w=1650&q=80" width="100%" height="100%" overflow="visible"/>
</svg>
<div class="svg-wrapper">
<svg class="svg-defs">
<defs>
<clipPath id="clipping">
<circle r="72" stroke="black" stroke-width="3"/>
</clipPath>
</defs>
</svg>
</div>
That's not the way SVG works.
When you tell something to use a clip path, all it sees is the clip path definition itself. It doesn't know or care about where on the page you have positioned it's parent <svg>.
If you want the clip circle to be at a certain position on the water image, you need to specify its position using cx and cy.
html, body { margin:0; padding:0; overflow:hidden }
svg { position:absolute; top:0; left:0;}
.image-clip-src {
width: 100%;
height: 100%;
}
.clipped-image image {
clip-path: url(#clipping);
}
<svg class="clipped-image" width="100%" height="100%" viewBox="0 0 1440 960" preserveAspectRatio="xMinYMin meet">
<defs>
<clipPath id="clipping">
<circle cx="64%" cy="55%" r="72" stroke="black" stroke-width="3"/>
</clipPath>
</defs>
<image class="image-clip-src" xlink:href="https://images.unsplash.com/photo-1526327227970-4bda49fa3489?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=3c4bce33d96df6b18af53fb2dae3363e&auto=format&fit=crop&w=1650&q=80" width="100%" height="100%" overflow="visible"/>
<circle cx="64%" cy="55%" r="72" fill="none" stroke="#4D4F51" stroke-width="1"/>
</svg>

Clipping path from SVG file

I tried copying my SVG into my HTML and defining it as a clipPath, but it doesn't display the shape the right way. Can I define clipPath using a file path?
<div class="gradient">
</div>
<svg height="0" width="0">
<defs>
<clipPath id="Camera">
<style>
.cls-1, .cls-2 {
fill: #363636;
}
.cls-1, .cls-3 {
stroke: #363636;
}
.cls-1 {
stroke-width: 1px;
fill-rule: evenodd;
}
.cls-3 {
fill: none;
stroke-width: 50px;
}
</style>
<path class="cls-1" d="M566.282,395.982s-121.771,16.243-155.258,35.532-93.7,51.606-135.978,123.854c-1.285-10.084-1.014-8.122-1.014-8.122v-33.5a319.278,319.278,0,0,1,20.3-80.2c15.223-37.882,41.848-78.09,77.121-99.489,55.447,0,87.691,5.262,142.067,27.411C565.1,395.035,566.282,395.982,566.282,395.982Zm-136.671,44.24S382.787,553.845,382.741,592.5s-2.176,106.981,39.225,179.738c-9.372-3.929-7.538-3.182-7.538-3.182l-29-16.751a319.037,319.037,0,0,1-59.278-57.684c-25.181-32.13-46.675-75.3-47.563-116.562,27.724-48.04,48.4-73.345,94.761-109.381C428.2,440.773,429.611,440.222,429.611,440.222Zm-34.372,138.5s74.972,97.311,108.424,116.665,91.55,55.336,175.261,55.844c-8.09,6.151-6.526,4.936-6.526,4.936l-29.01,16.739a319.273,319.273,0,0,1-79.6,22.5c-40.418,5.748-88.553,2.786-124.725-17.061-27.733-48-39.3-78.549-47.321-136.692C395.011,580.218,395.239,578.721,395.239,578.721ZM501.768,677.28s121.722-16.3,155.2-35.605,93.676-51.652,135.971-123.924c1.28,10.084,1.011,8.121,1.011,8.121l-0.015,33.5a319.666,319.666,0,0,1-20.323,80.215c-15.233,37.892-41.864,78.115-77.131,99.532-55.422.025-87.649-5.222-141.989-27.348C502.95,678.227,501.768,677.28,501.768,677.28Zm138.679-42.488s46.752-113.61,46.78-152.27,2.126-106.987-39.29-179.768c9.37,3.933,7.536,3.185,7.536,3.185l29,16.765a319.457,319.457,0,0,1,59.277,57.715c25.185,32.144,46.688,75.329,47.594,116.593C763.65,545.042,743,570.339,696.672,606.357,641.857,634.242,640.447,634.792,640.447,634.792ZM672.715,493.3s-74.971-97.311-108.423-116.665S472.741,321.3,389.031,320.789c8.089-6.151,6.525-4.936,6.525-4.936l29.01-16.739a319.289,319.289,0,0,1,79.6-22.5c40.418-5.748,88.552-2.786,124.725,17.061,27.733,48.005,39.3,78.549,47.321,136.692C672.943,491.8,672.715,493.3,672.715,493.3Z"/>
<circle class="cls-2" cx="176" cy="176" r="60"/>
<rect id="Camera_Body" data-name="Camera Body" class="cls-3" x="38" y="38" width="1001" height="1001" rx="100" ry="100"/>
</clipPath>
Will display this
https://codepen.io/TVsVeryOwn/pen/yjwaoy
I'm trying to get something resembling this (I know my gradient is backwards):
< clipPath >  only uses the fill of the shapes.
If you remove < rect id="Camera_Body" > part from your SVG code - you’ll see it’s working as you wanted without this rect element. The rect doesn’t have a fill - only a stroke - and the clipping doesn’t work on stroke.
This may help.

Icon into SVG Circle

How do I out an icon (e.g. font-awesome) into an SVG element?
I want that this is centered in the circle.
<svg class="svg" width=100 height=100>
<circle cx=50 cy=50 r=25>
</circle>
<i class="icon-check"></i>
</svg>
Here is a test:
http://jsfiddle.net/L2Lm3fgm/
Just find out the code for the character font-awesome is using in its class, and use that character as a text node. Remember to group the circle and the text node together.
Example:
svg {
margin: 24px auto;
display: block;
}
circle {
fill: transparent;
stroke: #f00;
stroke-width: 2;
}
svg text#chk {
font-family: sans-serif;
font-size: 24px;
fill: #00f;
}
<svg class="svg" width=100 height=100>
<g>
<circle cx=50 cy=50 r=25></circle>
<text id="chk" x=42 y=58>✓</text>
</g>
</svg>
Example Fiddle: http://jsfiddle.net/abhitalks/L2Lm3fgm/2/