How to change svg path width on hover - css

I have an issue I can't find an helpful answer. I have a svg arrow, the arrow has to grow when the user hovers over with the mouse. The problem is that only the line has to change size not the arrow head. I just want the line to grow horizontally.
This is the svg code
<svg width="51" height="8" viewBox="0 0 51 8" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M50.3536 4.35355C50.5488 4.15829 50.5488 3.84171 50.3536 3.64645L47.1716 0.464466C46.9763 0.269204 46.6597 0.269204 46.4645 0.464466C46.2692 0.659728 46.2692 0.976311 46.4645 1.17157L49.2929 4L46.4645 6.82843C46.2692 7.02369 46.2692 7.34027 46.4645 7.53553C46.6597 7.7308 46.9763 7.7308 47.1716 7.53553L50.3536 4.35355ZM0 4.5H50V3.5H0V4.5Z" fill="black"/>
</svg>
And this is the code the I have working right now
svg {
width: 50px;
overflow: visible;
transition: width 0.5s ease;
}
svg:hover {
width: 100px;
}
I also have a Codepen link
https://codepen.io/godhandkiller/pen/xxRZeYv
The problem here is that I'm manipulating the whole SVG but I only need to change the like size.

A possible solution: you can use a line path with a marker-end. The marker is the tip of the arrow. For the animation I'm using SMIL animations changing the d attribute of the path from M1,4L25,4 to M1,4L50,4. The animate element has a begin attribute making the animation to begin when you mouse over the overlaying rectangle: begin="theRect.mouseover". Another animate element animates the path on mouse out: begin="theRect.mouseout"
svg {
border: 1px solid red;
transition: width 0.5s ease;
}
<svg id="theSVG" fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 51 8" stroke="#000" stroke-linecap="round">
<defs>
<marker id="m" overflow="visible" markerUnits="userSpaceOnUse">
<path d="M-3,-3L0,0 -3,3" />
</marker>
</defs>
<path d="M1,4L25,4" marker-end="url(#m)">
<animate attributeName="d" to="M1,4L50,4" dur="1s" begin="theRect.mouseover" repeatCount="1" fill="freeze" />
<animate attributeName="d" to="M1,4L25,4" dur="1s" begin="theRect.mouseout" repeatCount="1" fill="freeze" />
</path>
<rect width="100%" height="100%" stroke="none" pointer-events="all" id="theRect" />
</svg>

Related

Draw a circle in svg with preserveAspectRatio="none"

I have an svg with viewBox="0 0 100 100" preserveAspectRatio="none" since I need to draw some elements with reference to percentages.
If I now draw a <circle cx="30" cy="50" r="0.5" stroke="white"/> though it becomes stretched/distorted as well.
Is there a way to tell the circle element to preserve its own aspect ratio?
If all you need is a circle you can use a very short, very wide line like in the following example.
This will work because
stroke-linecap="round" will give the illusion of a circle and because
strokes can take a vector-effect="non-scaling-stroke".
non-scaling-stroke
This value modifies the way an object is stroked. Normally stroking involves calculating stroke outline of the shape's path in current user coordinate system and filling that outline with the stroke paint (color or gradient). The resulting visual effect of this value is that the stroke width is not dependent on the transformations of the element (including non-uniform scaling and shear transformations) and zoom level.
div {
width: 300px;
height: 50px;
background-color: lime;
}
svg {
width:100%;
height:100%;
}
<div>
<svg viewBox="0 0 100 100" preserveAspectRatio="none">
<!--<circle cx="30" cy="50" r="20"></circle>-->
<line x1="30" y1="50" x2="30.1" y2="50" stroke-width="40" stroke="black" stroke-linecap="round" vector-effect="non-scaling-stroke" />
</svg>
</div>
If you need a white stroke too you can add a white line behind the black one with a bigger stroke width
div {
width: 300px;
height: 50px;
background-color: lime;
}
svg {
width:100%;
height:100%;
}
<div>
<svg viewBox="0 0 100 100" preserveAspectRatio="none">
<line x1="30" y1="50" x2="30.1" y2="50" stroke-width="45" stroke="white" stroke-linecap="round" vector-effect="non-scaling-stroke" />
<line x1="30" y1="50" x2="30.1" y2="50" stroke-width="40" stroke="black" stroke-linecap="round" vector-effect="non-scaling-stroke" />
</svg>
</div>

SVG filter not visible when using custom viewBox

Why is setting an svg viewBox to say 0 0 1 1 causing my filter to disappear? I also tried playing around with x, y, height, and width attributes as well as changing primitiveUnits attribute, nothing did work. Any help would be appreciated.
svg {
border: 1px solid red;
height: 100px;
width: 100px;
}
svg circle {
fill: black;
}
<html>
<body>
<svg viewBox="0 0 1 1">
<defs>
<filter id="halo1">
<feGaussianBlur in="SourceGraphic" stdDeviation="3" />
</filter>
</defs>
<circle cx="50%" cy="50%" r="25%" filter="url(#halo1)"></circle>
</svg>
<svg>
<defs>
<filter id="halo2">
<feGaussianBlur in="SourceGraphic" stdDeviation="3" />
</filter>
</defs>
<circle cx="50%" cy="50%" r="25%" filter="url(#halo2)"></circle>
</svg>
</body>
</html>
Fiddle playground: https://jsfiddle.net/6x34urzg/14/
When the image is scaled from 1x1 (the viewBox="0 0 1 1") to 100x100 px the standard deviation (stdDeviation="3") is also scaled. The circle with the filter is still there but 100 time too big.
If you set the standard deviation to 1/100 (stdDeviation=".03") you will get the same result as the other SVG.
svg {
border: 1px solid red;
height: 100px;
width: 100px;
}
svg circle {
fill: black;
}
<html>
<body>
<svg viewBox="0 0 1 1">
<defs>
<filter id="halo1">
<feGaussianBlur in="SourceGraphic" stdDeviation=".03" />
</filter>
</defs>
<circle cx="50%" cy="50%" r="25%" filter="url(#halo1)"></circle>
</svg>
<svg>
<defs>
<filter id="halo2">
<feGaussianBlur in="SourceGraphic" stdDeviation="3" />
</filter>
</defs>
<circle cx="50%" cy="50%" r="25%" filter="url(#halo2)"></circle>
</svg>
</body>
</html>
Actually, in the CSS you know insert CSS to HTML like Internal CSS and Inline CSS. Internal CSS is you write css on in inside on tag and that tend general for use to give style on SVG. While, Inline CSS used to write css on unique element on tags like your program(coding). Although you have writenn css svg, your svg on "Hallo1" disappear because your program have write inline CSS viewBox="0 0 1 1"make your svg "Halo 1" disappear. Moreover, viewBox="0 0 1 1" make your circle dissapear because weight=1 and height=1 so that cirle which resulted so small and you cannot see that. To solve that problem you can change your viewBox become 'viewBox="0 0 100 100" '

svg rotate 90deg but disappear

I have a svg which is an arrow facing right. However, i am unable to make the arrow downward by adding transform: rotate(). When I change css svg path, the entire arrow is gone. How do I solve it?
Before:
After:
In my html and css,
svg path {
transform: rotate(90);
}
<svg class="arrow-right" xmlns="http://www.w3.org/2000/svg" width="25" height="25" viewBox="0 0 25 25">
<g id="ico___black" data-name="ico_>_black" transform="translate(19525 16160)">
<path id="パス_60" data-name="パス 60" d="M1061.961,192.633l5.465,5.465,5.465-5.465"
transform="translate(-19707.389 -15080.434) rotate(-90)" fill="none" stroke="#2b2525"
stroke-width="2" />
<rect id="長方形_124" data-name="長方形 124" width="25" height="25" transform="translate(-19525 -16160)"
fill="none" />
</g>
</svg>
you can apply the transform on the svg instead of the path.
svg {
transform: rotate(90);
}

Animating feComposite SVG filter elements

I have two svg shapes, one on top of the other, and I've applied the feComposite filter on both so that the top shape knocks out part of the bottom shape. The code is as follows and works fine.
<svg width="100" height="100">
<defs>
<filter id="myfilter">
<feImage xlink:href="#layer1" result="lay1"/>
<feImage xlink:href="#layer2" result="lay2"/>
<feComposite operator="out" in="lay1" in2="lay2"/>
</filter>
</defs>
<g filter="url(#myfilter)">
<circle id="layer1" cx="50" cy="50" r="40" stroke-
width="0" fill="green" />
<circle id="layer2" class="small" cx="20" cy="60" r="20" stroke-
width="0" fill="red" />
</g>
</svg>
Now I want to animate the top shape, but when I tried to apply the animation, both shapes animates and I can't figure out why because I've only targeted the second shape with class="small". Here is the css code for the animation.
#keyframes rock {
0% {
transform: rotate(45deg);
}
50% {
transform: rotate(0deg);
}
100% {
transform: rotate(-45deg);
}
}
.small {
animation-name: rock;
animation-duration: 5s;
animation-iteration-count: infinite;
animation-timing-function: linear;
}
I am puzzled by this behavior and hope someone can shed some light to this problem. Is it not possible to animate the svg elements individually when filters are applied to them as a group? But that doesn't seem to make sense because the svg elements can be targeted individually.
Here is a link to codepen: https://codepen.io/lanlanonearth/pen/bGbRyVo
Please try this: You put both circles in the <defs> and you <use xlink:href="#layer1". Next you apply the filter to the <use> element.
<svg width="100" height="100">
<defs>
<circle id="layer1" cx="50" cy="50" r="40" stroke-width="0" fill="green" />
<circle id="layer2" class="small" cx="20" cy="60" r="20" stroke-width="0" fill="red" />
<filter id="myfilter">
<feImage xlink:href="#layer1" result="lay1"/>
<feImage xlink:href="#layer2" result="lay2"/>
<feComposite operator="out" in="lay1" in2="lay2"/>
</filter>
</defs>
<use xlink:href="#layer1" filter="url(#myfilter)"></use>
</svg>
Check it on codepen

Animated growing arrow link

Hi, I was wondering how one would go about animating an svg arrow like above (on hover).
I have tried playing around with CSS transforms, but they also scale the arrow-head which is no good. I assume the correct way to do this is using SVGs animations, but I don't know where to start.
For example I would the following arrow (line only) to grow and arrow head to move accordingly.
<svg width="600px" height="100px">
<defs>
<marker id="arrow" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto" markerUnits="strokeWidth">
<path d="M0,0 L0,6 L9,3 z" fill="#f00" />
</marker>
</defs>
<line x1="50" y1="50" x2="100" y2="50" stroke="#000" stroke-width="5" marker-end="url(#arrow)" />
</svg>
Any help is very much appreciated!
You can create growing arrow by using "respoinsive" SVG like this.
svg{
width: 20px;
height: 20px;
transition:width 2s ease;
overflow: visible;
}
svg:hover{
width: 100px;
}
<svg>
<defs>
<marker id="m" markerWidth="4" markerHeight="8"
refX="0" refY="1" viewBox="0 0 1 2">
<polygon points="0,0 1,1 0,2" fill="black"/>
</marker>
</defs>
<line x1="0" y1="50%" x2="100%" y2="50%"
stroke-width="2" marker-end="url(#m)" stroke="black"/>
</svg>
There are some points to implement.
svg has no viewBox (so it is "responsive" SVG).
Line of arrow is defined by relative position of (root) svg size.
Arrow head is defined by marker element.
Growing animation is defined by CSS transition which animate width of svg. So, arrow grows with svg size.
In order to animate the individual SVG elements like HTML elements, you'll need to embed the SVG directly into the page like this:
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="612px" height="502.174px" viewBox="0 65.326 612 502.174" enable-background="new 0 65.326 612 502.174"
xml:space="preserve" class="logo">
<ellipse class="ground" cx="283.5" cy="487.5" rx="259" ry="80"/>
<path class="kiwi" d="M210.333,65.331C104.367,66.105-12.349,150.637,1.056,276.449c4.303,40.393,18.533,63.704,52.171,79.03
c36.307,16.544,57.022,54.556,50.406,112.954c-9.935,4.88-17.405,11.031-19.132,20.015c7.531-0.17,14.943-0.312,22.59,4.341
c20.333,12.375,31.296,27.363,42.979,51.72c1.714,3.572,8.192,2.849,8.312-3.078c0.17-8.467-1.856-17.454-5.226-26.933
c-2.955-8.313,3.059-7.985,6.917-6.106c6.399,3.115,16.334,9.43,30.39,13.098c5.392,1.407,5.995-3.877,5.224-6.991
c-1.864-7.522-11.009-10.862-24.519-19.229c-4.82-2.984-0.927-9.736,5.168-8.351l20.234,2.415c3.359,0.763,4.555-6.114,0.882-7.875
c-14.198-6.804-28.897-10.098-53.864-7.799c-11.617-29.265-29.811-61.617-15.674-81.681c12.639-17.938,31.216-20.74,39.147,43.489
c-5.002,3.107-11.215,5.031-11.332,13.024c7.201-2.845,11.207-1.399,14.791,0c17.912,6.998,35.462,21.826,52.982,37.309
c3.739,3.303,8.413-1.718,6.991-6.034c-2.138-6.494-8.053-10.659-14.791-20.016c-3.239-4.495,5.03-7.045,10.886-6.876
c13.849,0.396,22.886,8.268,35.177,11.218c4.483,1.076,9.741-1.964,6.917-6.917c-3.472-6.085-13.015-9.124-19.18-13.413
c-4.357-3.029-3.025-7.132,2.697-6.602c3.905,0.361,8.478,2.271,13.908,1.767c9.946-0.925,7.717-7.169-0.883-9.566
c-19.036-5.304-39.891-6.311-61.665-5.225c-43.837-8.358-31.554-84.887,0-90.363c29.571-5.132,62.966-13.339,99.928-32.156
c32.668-5.429,64.835-12.446,92.939-33.85c48.106-14.469,111.903,16.113,204.241,149.695c3.926,5.681,15.819,9.94,9.524-6.351
c-15.893-41.125-68.176-93.328-92.13-132.085c-24.581-39.774-14.34-61.243-39.957-91.247
c-21.326-24.978-47.502-25.803-77.339-17.365c-23.461,6.634-39.234-7.117-52.98-31.273C318.42,87.525,265.838,64.927,210.333,65.331
z M445.731,203.01c6.12,0,11.112,4.919,11.112,11.038c0,6.119-4.994,11.111-11.112,11.111s-11.038-4.994-11.038-11.111
C434.693,207.929,439.613,203.01,445.731,203.01z"/>
<filter id="pictureFilter" >
<feGaussianBlur stdDeviation="15" />
</filter>
</svg>
After doing this, you can use CSS animations on any of the individual SVG elements, just like HTML elements. For example, you could do the following:
svg ellipse { animate: grow 3s infinite; }
Without having the exact SVG code for your arrow, I can't give you more specific direction than that, but can point you in the direction of this article: https://css-tricks.com/using-svg/

Resources