I'm trying to build an animation for opening a hamburger menu. I am struggling to get the hamburger to the x. In theory I seem to be doing everything right but the result tells me otherwise xD. I've been playing around with the translate values and also the transform-origin but it all behaves in (for me) unexpected ways. Could someone have a look and help me out?
My Example: https://codepen.io/aki-sol/pen/RwMoEJQ
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"
xmlns="http://www.w3.org/2000/svg">
<rect class="top" y="8.5" width="48" height="3.875" fill="blue" />
<rect class="middle" y="22.0625" width="48" height="3.875" fill="blue" />
<rect class="bottom" y="35.625" width="48" height="3.875" fill="blue" />
</svg>
svg:hover .top {
animation-name: top;
animation-duration: 1.5s;
animation-timing-function: ease-in-out;
/*transform-origin: 25% 25%;*/
animation-fill-mode: forwards;
}
svg:hover .middle {
animation-name: middle;
animation-duration: 1.5s;
animation-timing-function: linear;
transform-origin: center center;
animation-fill-mode: forwards;
}
svg:hover .bottom {
animation-name: bottom;
animation-duration: 1.5s;
animation-timing-function: ease-in-out;
/*transform-origin: 25% 25%;*/
animation-fill-mode: forwards;
}
#keyframes top {
0% {
transform: translateY(0);
}
50% {
transform: translateY(30%);
}
100% {
transform: rotate(45deg) translateY(-25%);
}
}
#keyframes middle {
50% {
opacity: 0;
}
100% {
opacity: 0;
}
}
#keyframes bottom {
0% {
transform: translateY(0);
}
50% {
transform: translateY(-30%);
}
100% {
transform: rotate(-45deg);
}
}
Goal (first example): https://codepen.io/vineethtrv/pen/VYRzaV
Thanks!
I have changed a little bit the dimensions to make the values easier to calculate.
So, svg width is 48, so I set the transform-origin x value at 24, the center.
For top, y is 8 and height is 4, so the center is at 8 + (4 / 2) = 10.
The corrected demo goes like this:
svg:hover .top {
animation-name: top;
animation-duration: 1.5s;
animation-timing-function: ease-in-out;
transform-origin: 24px 10px;
animation-fill-mode: forwards;
}
svg:hover .middle {
animation-name: middle;
animation-duration: 1.5s;
animation-timing-function: linear;
transform-origin: center center;
animation-fill-mode: forwards;
}
svg:hover .bottom {
animation-name: bottom;
animation-duration: 1.5s;
animation-timing-function: ease-in-out;
transform-origin: 24px 38px;
animation-fill-mode: forwards;
}
#keyframes top {
0% {
transform: translateY(0);
}
50% {
transform: translateY(30%);
}
100% {
transform: translateY(30%) rotate(45deg);
}
}
#keyframes middle {
50% {
opacity: 0;
}
100% {
opacity: 0;
}
}
#keyframes bottom {
0% {
transform: translateY(0);
}
50% {
transform: translateY(-30%);
}
100% {
transform: translateY(-30%) rotate(-45deg);
}
}
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect class="top" y="8" width="48" height="4" fill="blue" />
<rect class="middle" y="22" width="48" height="4" fill="blue" />
<rect class="bottom" y="36" width="48" height="4" fill="blue" />
</svg>
Perhaps you can play around with the values in the DevTools. Try nudging it with the arrow keys to get it to a position you like. I got the following:
svg:hover .top {
transform-origin: 4% 28%;
}
svg:hover .bottom {
transform-origin: 5% 50%;
}
My CSS animation is not working when I try to apply it to my <svg> element.
I have tried to use a prefix but it still did not fix the problem.
#keyframes mymove {
0% {
stroke-dashoffset: 0;
}
50% {
stroke-dashoffset: 56.52;
}
}
#-webkit-keyframes mymove {
0% {
stroke-dashoffset: 0;
}
50% {
stroke-dashoffset: 56.52;
}
}
.circle {
position: absolute;
top: 0;
left: 0;
animation-duration: 1.4s;
animation-timing-function: ease-in-out;
animation-iteration-count: infinite;
animation-fill-mode: both;
animation-name: mymove;
-webkit-animation-name: mymove;
}
<nav class="footage-nav">
<a class="link" href="my_work/index.html"><svg height="20" width="20"><circle class="circle" cx="50%" cy="50%" r="9" stroke="#231f20" stroke-width="1" fill-opacity="0" /></svg>Work<div class="underLine"></div></a>
<svg height="20" width="20"><circle class="circle" cx="50%" cy="50%" r="9" stroke="#231f20" stroke-width="1" fill-opacity="0" /></svg>About<div class="underLine"></div>
</nav>
As commented by user4642212
The animation is definitely active (as you can see in dev tools), but
it has no effect. What are you expecting it to do? stroke-dashoffset
modifies where a stroke-dasharray starts. You’ve never set one.
In other words, for the animation to work, you need to add the stroke-dasharray to the animated object.: stroke-dasharray:56.52;
#keyframes mymove {
0% {
stroke-dashoffset: 0;
}
50% {
stroke-dashoffset: 56.52;
}
}
#-webkit-keyframes mymove {
0% {
stroke-dashoffset: 0;
}
50% {
stroke-dashoffset: 56.52;
}
}
.circle {
stroke-dasharray:56.52;
position: absolute;
top: 0;
left: 0;
animation-duration: 1.4s;
animation-timing-function: ease-in-out;
animation-iteration-count: infinite;
animation-fill-mode: both;
animation-name: mymove;
-webkit-animation-name: mymove;
}
<nav class="footage-nav">
<a class="link" href="my_work/index.html"><svg height="20" width="20"><circle class="circle" cx="50%" cy="50%" r="9" stroke="#231f20" stroke-width="1" fill-opacity="0" /></svg>Work<div class="underLine"></div></a>
<svg height="20" width="20"><circle class="circle" cx="50%" cy="50%" r="9" stroke="#231f20" stroke-width="1" fill-opacity="0" /></svg>About<div class="underLine"></div>
</nav>
Animation option when hovering over a link
#keyframes mymove {
0% {
stroke-dashoffset: 0;
}
50% {
stroke-dashoffset: 56.52;
}
}
#-webkit-keyframes mymove {
0% {
stroke-dashoffset: 0;
}
50% {
stroke-dashoffset: 56.52;
}
}
.circle {
stroke-dasharray:56.52;
position: absolute;
top: 0;
left: 0;
}
.link:hover {
animation-duration: 1.4s;
animation-timing-function: ease-in-out;
animation-iteration-count: infinite;
animation-fill-mode: both;
animation-name: mymove;
-webkit-animation-name: mymove;
}
<nav class="footage-nav">
<a class="link" href="my_work/index.html"><svg height="20" width="20"><circle class="circle" cx="50%" cy="50%" r="9" stroke="#231f20" stroke-width="1" fill-opacity="0" /></svg>Work<div class="underLine"></div></a>
<a class="link" href=""><svg height="20" width="20"><circle class="circle" cx="50%" cy="50%" r="9" stroke="#231f20" stroke-width="1" fill-opacity="0" /></svg>About<div class="underLine"></div></a>
</nav>
I have a heart button when onclick it will fill the SVG with red from bottom to top and when unclicked it will unfill the SVG from top to bottom. Heres what I've searched so far:JSFiddle
I'm new with this kind of techniques like keyframes and clip-path thing. These can all be done via css only?
body {
display: -webkit-box;
display: flex;
-webkit-box-pack: center;
justify-content: center;
-webkit-box-align: center;
align-items: center;
height: 100vh;
}
.heart-container {
position: relative;
width: 40px;
height: 40px;
}
.heart-clip {
display: block;
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
-webkit-clip-path: url(#svgPath);
clip-path: url(#svgPath);
}
.heart-clip:hover {
-webkit-animation: pulse .6s .3s infinite;
animation: pulse .6s .3s infinite;
}
.heart-clip:hover::before {
-webkit-transform: scale(1);
transform: scale(1);
opacity: 1;
}
.heart-clip::before {
content: '';
display: block;
width: 100%;
height: 100%;
border-radius: 50%;
background-color: #D32F2F;
opacity: 0;
-webkit-transform: scale(0);
transform: scale(0);
-webkit-transition: opacity .2s linear, -webkit-transform .2s linear;
transition: opacity .2s linear, -webkit-transform .2s linear;
transition: transform .2s linear, opacity .2s linear;
transition: transform .2s linear, opacity .2s linear, -webkit-transform .2s linear;
-webkit-transform-origin: center 60%;
transform-origin: center 60%;
}
.heart-stroke {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
fill: #D32F2F;
}
#-webkit-keyframes pulse {
0% {
-webkit-transform: scale(1);
transform: scale(1);
}
30% {
-webkit-transform: scale(1.2);
transform: scale(1.2);
}
60% {
-webkit-transform: scale(1);
transform: scale(1);
}
}
#keyframes pulse {
0% {
-webkit-transform: scale(1);
transform: scale(1);
}
30% {
-webkit-transform: scale(1.2);
transform: scale(1.2);
}
60% {
-webkit-transform: scale(1);
transform: scale(1);
}
}
<svg height="0" width="0">
<defs>
<clipPath id="svgPath">
<path d="M20,35.09,4.55,19.64a8.5,8.5,0,0,1-.13-12l.13-.13a8.72,8.72,0,0,1,12.14,0L20,10.79l3.3-3.3a8.09,8.09,0,0,1,5.83-2.58,8.89,8.89,0,0,1,6.31,2.58,8.5,8.5,0,0,1,.13,12l-.13.13Z"/>
</clipPath>
</defs>
</svg>
<div class="heart-container">
<svg width="40" height="40" viewBox="0 0 40 40" class='heart-stroke'>
<path d="M20,35.07,4.55,19.62a8.5,8.5,0,0,1-.12-12l.12-.12a8.72,8.72,0,0,1,12.14,0L20,10.77l3.3-3.3A8.09,8.09,0,0,1,29.13,4.9a8.89,8.89,0,0,1,6.31,2.58,8.5,8.5,0,0,1,.12,12l-.12.12ZM10.64,7.13A6.44,6.44,0,0,0,6.07,18.19L20,32.06,33.94,18.12A6.44,6.44,0,0,0,34,9l0,0a6.44,6.44,0,0,0-4.77-1.85A6,6,0,0,0,24.83,9L20,13.78,15.21,9A6.44,6.44,0,0,0,10.64,7.13Z"/>
</svg>
<a href='#' class='heart-clip'></a>
</div>
any alternatives and solutions is much appreciated!
Thanks in advance!
Consider filling with color using the feFlood filters and animating with changing thedy attribute of the feoffset filter.
Repeated clicks change the color direction animation
var svg1 = document.getElementById("svg1"),
close = document.getElementById('close'),
open = document.getElementById("open");
let flag = true;
svg1.addEventListener('click', function() {
if (flag == true) {
close.beginElement();
flag = false;
} else {
open.beginElement();
flag = true;
}
});
<div class="heart-container">
<svg id="svg1" width="40" height="40" viewBox="0 0 40 40" class='heart-stroke'>
<defs>
<filter id="red_fill" x="0%" y="0%">
<feFlood flood-color="#ded9d5" />
<feOffset dx="0">
<!-- Animation fills of color from top to bottom. -->
<animate id="close" attributeName="dy" values="0;40" dur="1s" begin="indefinite" repeatCount="3" restart="whenNotActive" fill="freeze"/>
<!-- Animation fills of color from bottom to top. -->
<animate id="open" attributeName="dy" values="40;0" dur="1s" begin="indefinite" repeatCount="3" restart="whenNotActive" fill="freeze"/>
</feOffset>
<feComposite operator="in" in2="SourceGraphic" />
<feComposite operator="over" in2="SourceGraphic" />
</filter>
</defs>
<path filter="url(#red_fill)" stroke="red" stroke-width="2" fill="red" d="M20,35.07,4.55,19.62a8.5,8.5,0,0,1-.12-12l.12-.12a8.72,8.72,0,0,1,12.14,0L20,10.77l3.3-3.3A8.09,8.09,0,0,1,29.13,4.9a8.89,8.89,0,0,1,6.31,2.58,8.5,8.5,0,0,1,.12,12l-.12.12Z"/>
</svg>
<a href='#' class='heart-clip'></a>
</div>
I am facing a bit of a problem and I cant seem to figure it out. The ultimate outcome I am looking for, when the box is hovered, the borders should animate to make a frame that looks like this. - image attached
But the actual outcome I am getting is different. The border don't make a perfect frame. This is my code.
<section class="services">
<div class="grid">
<div class="box">
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">
<line class="top" x1="0" y1="0" x2="900" y2="0"></line>
<line class="left" x1="0" y1="260" x2="0" y2="-520"></line>
<line class="bottom" x1="300" y1="260" x2="-600" y2="260"></line>
<line class="right" x1="300" y1="0" x2="300" y2="780"></line>
</svg>
<div class="icon-wrapper"><i class="fa fa-users custom-icon"><span class="fix-editor"> </span></i></div>
<p>text</p>
</div>
<div class="box">
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">
<line class="top" x1="0" y1="0" x2="900" y2="0"></line>
<line class="left" x1="0" y1="460" x2="0" y2="-920"></line>
<line class="bottom" x1="300" y1="460" x2="-600" y2="460"></line>
<line class="right" x1="300" y1="0" x2="300" y2="1380"></line>
</svg>
<h3>text</h3>
</div>
<div class="box">
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">
<line class="top" x1="0" y1="0" x2="900" y2="0"></line>
<line class="left" x1="0" y1="460" x2="0" y2="-920"></line>
<line class="bottom" x1="300" y1="460" x2="-600" y2="460"></line>
<line class="right" x1="300" y1="0" x2="300" y2="1380"></line>
</svg>
<h3>text</h3>
</div>
</div><!-- /grid -->
</section>
This is the css
html {background:blue;}
.box {
width: 300px;
height:260px;
position: relative;
background: rgba(255,255,255,1);
display: inline-block;
margin: 0 10px;
cursor: pointer;
color: #2c3e50;
box-shadow: inset 0 0 0 3px #2c3e50;
-webkit-transition: background 0.4s 0.5s;
transition: background 0.4s 0.5s;
}
.box:hover {
background: rgba(255,255,255,0);
-webkit-transition-delay: 0s;
transition-delay: 0s;
}
.box svg {
position: absolute;
top: 0;
left: 0;
}
.box svg line {
stroke-width: 3;
stroke: #ecf0f1;
fill: none;
-webkit-transition: all .8s ease-in-out;
transition: all .8s ease-in-out;
}
.box:hover svg line {
-webkit-transition-delay: 0.1s;
transition-delay: 0.1s;
}
.box svg line.top,
.box svg line.bottom {
stroke-dasharray: 330 240;
}
.box svg line.left,
.box svg line.right {
stroke-dasharray: 490 400;
}
.box:hover svg line.top {
-webkit-transform: translateX(-600px);
transform: translateX(-600px);
}
.box:hover svg line.bottom {
-webkit-transform: translateX(600px);
transform: translateX(600px);
}
.box:hover svg line.left {
-webkit-transform: translateY(520px);
transform: translateY(520px);
}
.box:hover svg line.right {
-webkit-transform: translateY(-520px);
transform: translateY(-520px);
}
.services {text-align: center;}
/* Frame */
.services .box {
background: rgba(0,0,0,0);
color: #fff;
box-shadow: none;
-webkit-transition: background 0.3s;
transition: background 0.3s;
}
.services .box:hover {
background: rgba(0,0,0,0.4);
}
.services .box svg line {
-webkit-transition: all .5s;
transition: all .5s;
}
.services .box:hover svg line {
stroke-width: 10;
-webkit-transition-delay: 0s;
transition-delay: 0s;
}
.services .box:hover svg line.top {
-webkit-transform: translateX(-300px);
transform: translateX(-300px);
}
.services .box:hover svg line.bottom {
-webkit-transform: translateX(300px);
transform: translateX(300px);
}
.services .box:hover svg line.left {
-webkit-transform: translateY(260px);
transform: translateY(260px);
}
.services .box:hover svg line.right {
-webkit-transform: translateY(-260px);
transform: translateY(-260px);
}
And this is a fiddle
Your values for this:
.box svg line.left,
.box svg line.right {
stroke-dasharray:
}
Were causing an error for the first box. Try these numbers:
.box svg line.left,
.box svg line.right {
stroke-dasharray: 290 200;
}
Fiddle
You should be able to tweak these values for the remaining boxes as you need.
I have this animated graph that I created, but the start of the path, for some reason, was at 90deg, so I put a transform: rotate(-90deg) on it to start from 0deg. This works fine on my desktop in Chrome and Safari, but when I view it on my iPhone, it seems to ignore my rotate and go back to its default 90deg starting point. I've tried a bunch of prefixes and nothing changes.
Here's the link on CodePen
body {
background-color: #34495e;
}
.skills-graph {
fill: transparent;
transform: rotate(-90deg);
-webkit-transform: rotate(-90deg);
-ms-transform: rotate(-90deg);
-moz-transform: rotate(-90deg);
-o-transform: rotate(-90deg);
position: absolute;
top: 0px;
right: 0px;
bottom: 0px;
left: 0px;
margin: auto;
}
#javascript {
visibility: visible;
stroke: #ecf0f1;
animation-name: javascript;
animation-duration: 1s;
animation-timing-function: ease;
animation-delay: 0s;
animation-iteration-count: 1;
animation-direction: normal;
stroke-dasharray: 880;
stroke-dashoffset: 780;
animation-fill-mode: forwards;
}
#keyframes javascript {
0% {
stroke-dashoffset: 880;
stroke: white;
}
50% {
stroke: #ecf0f1;
}
100% {
stroke-dashoffset: 780;
stroke: #ecf0f1;
}
}
#html {
visibility: visible;
fill: transparent;
stroke: #95a5a6;
animation-name: html;
animation-duration: 1s;
animation-timing-function: ease;
animation-delay: 0s;
animation-iteration-count: 1;
animation-direction: normal;
stroke-dasharray: 691;
stroke-dashoffset: 271;
animation-fill-mode: forwards;
}
#keyframes html {
0% {
stroke-dashoffset: 691;
stroke: white;
}
50% {
stroke: #95a5a6;
}
100% {
stroke-dashoffset: 271;
stroke: #95a5a6;
}
}
#css {
visibility: visible;
fill: transparent;
stroke: #3dd0ac;
animation-name: css;
animation-duration: 1s;
animation-timing-function: ease;
animation-delay: 0s;
animation-iteration-count: 1;
animation-direction: normal;
stroke-dasharray: 502;
stroke-dashoffset: 172;
animation-fill-mode: forwards;
}
#keyframes css {
0% {
stroke-dashoffset: 502;
stroke: white;
}
50% {
stroke: #3dd0ac;
}
100% {
stroke-dashoffset: 172;
stroke: #3dd0ac;
}
}
<div id="skills-graph">
<!-- JavaScript Graph -->
<svg id="javascript" class="skills-graph" width="300" height="300">
<circle cx="150" cy="150" r="140" stroke-width="20"/>
</svg>
<!-- HTML Graph -->
<svg id="html" class="skills-graph" width="300" height="300">
<circle cx="150" cy="150" r="110" stroke-width="20"/>
</svg>
<!-- CSS Graph -->
<svg id="css" class="skills-graph" width="300" height="300">
<circle cx="150" cy="150" r="80" stroke-width="20"/>
</svg>
</div>
I do not have the answer, but i played a little bit with the codepen snippet on my iPhone 6s (safari) and when i changed the "-webkit-transform: rotate(-90deg);" (in .skills-graph) to "-webkit-transform: rotate(170deg);" it changes direction. Maybe you can find out the answer now yourself. (i'm not that good with code). Good luck!
EDIT: with "-webkit-transform: rotate(-89deg);" it seems right.