I have a hover animation on my HTML page, it is custom. Now the HTML looks like this:
HTML:
<figure class="schedule-info-box">
<a href="">
<img src="images/gallery/schedule/1.jpg" alt="schedule image">
<figcaption>
<div class="caption-wrapper">
<h4>Yin Yoga Dessi</h4>
<p>06:30 - 07:30</p>
</div>
<a href="" class="book-online">
Cick Here For <br>
Online Booking
</a>
</figcaption>
</a>
</figure>
you can see the FIDDLE HERE(the fiddle doesn't recreate the problem. )
Now when I hover over the box, I basically want the following effect:
unfortunately the effect in FF(mozilla) breaks. I get the following instead:
The problem as you can see is that the top portion of the image can be seen in FF.
Now if I open my dev tools in mozilla and change the state of
<div class="caption-wrapper">
</div>
To :hover and then in the dev tools add the following property height:50% , it works just fine , I.E. that portion of the image is no longer shown. This is funny because the effect that applied to .caption-wrapper , is the following:
#keyframes expand-schedule-header {
0% {
width: 75%;
}
25% {
width: 100%;
}
50% {
left: 0;
/*top: 0;*/
width: 100%;
height: 50%;
}
100% {
height: 50%;
left: 0;
width: 100%;
bottom: 50%;
border-bottom: 1px solid rgba(255,255,255,.3);
}
}
So the height applied is indeed 50% , so why does;t this work ? , also I have animation-fill-mode: set to both;:
.schedule-info-box:hover .caption-wrapper {
-webkit-animation-name: expand-schedule-header;
-o-animation-name: expand-schedule-header;
animation-name: expand-schedule-header;
-webkit-animation-duration: .5s;
-o-animation-duration: .5s;
animation-duration: .5s;
-webkit-animation-fill-mode: both;
-o-animation-fill-mode: both;
animation-fill-mode: both;
align-items:center;
}
The bug can be seen HERE(works fine in chrome , not in FF).
So why am I having this issue? Why is the element not taking 50% height in FF ? Why am I seeing the image in the background?
From What I see it is caused because FireFox renders fonts different from the other browsers and as a result your element's height is shorter than expected, but since you have it set as position:absolute you can just set the top:0 to the .caption-wrapper on .schedule-info-box:hover
.schedule-info-box:hover .caption-wrapper {
-webkit-animation-name: expand-schedule-header;
-o-animation-name: expand-schedule-header;
animation-name: expand-schedule-header;
-webkit-animation-duration: .5s;
-o-animation-duration: .5s;
animation-duration: .5s;
-webkit-animation-fill-mode: both;
-o-animation-fill-mode: both;
animation-fill-mode: both;
align-items:center;
top:0;
}
Related
I'm using a keyframes animation for a transformation. It works perfectly on desktop, but it acts extremely strange on mobile. I'm testing on Chrome on my Macbook and on Chrome on my iPhone X. Another user found the same issue on Safari on iPhone.
Basically, when the page loads, the animation doesn't play. The delay works, but the actual transition and fade doesn't happen. You can see what it should look like (from a computer) at asilhavy.com. It doesn't play on load, but if I go to a new page and select the back button, it will play after I scroll. So weird. The scroll bar is also weird when I go back after visiting a new page.
I'm suspicious that it might be something very wrong somewhere else in my code, but I don't know where. Any pointers on where to look are helpful. The full code is available at the link above, but here's the code I have now specifically for that animation. I've gone through a few other solutions, like setting display: block, using -webkit-, and avoiding shorthand animation.
Update: Through more debugging it appears ios and safari aren't rendering properly. The animation is technically playing, but the transition (ease) isn't following. They move, just not smoothly.
#-webkit-keyframes slide-in {
from {
-webkit-transform: translateX(-150%);
transform: translateX(-150%);
}
to {
-webkit-transform: translateX(-50%);
transform: translateX(-50%);
}
}
#keyframes slide-in {
from {
transform: translateX(-150%);
}
to {
transform: translateX(-50%);
}
}
.land-cont {
overflow: hidden;
position: absolute;
top: 30px;
left: 0;
height: 80px;
width: 250px;
}
.reveal-cont {
transform: translateX(-150%);
-webkit-animation-duration: 0.6s;
-webkit-animation-timing-function: ease;
-webkit-animation-delay: 1.6s;
-webkit-animation-iteration-count: 1;
-webkit-animation-direction: normal;
-webkit-animation-fill-mode: forwards;
-webkit-animation-play-state: running;
-webkit-animation-name: slide-in;
animation-duration: 0.6s;
animation-timing-function: ease;
animation-delay: 1.6s;
animation-iteration-count: 1;
animation-direction: normal;
animation-fill-mode: forwards;
animation-play-state: running;
animation-name: slide-in;
display: block;
position: absolute;
width: 100%;
height: 100%;
overflow: hidden;
top: calc(50% - 50px);
background: rgb(32, 6, 6);
left: 50%;
z-index: 2;
color: #FFF;
z-index: 2;
background: -webkit-linear-gradient($gradient);
background: -o-linear-gradient($gradient);
background: linear-gradient($gradient);
-webkit-box-shadow: $shadow;
-moz-box-shadow: $shadow;
box-shadow: $shadow;
opacity: 1;
}
<div class="land-cont">
<div class="reveal-cont">
<h2>Alicia</h2>
</div>
</div>
Finally fixed it. I can't point to one exact change, but I know this question was the one that got it working in the end. Turns out the problem was in iOS and Safari, not Chrome. Here's a list of changes I made:
Implemented proper use of -webkit-
Didn't use shorthand animation
Used display: block
Added animation class after page load
I'm not sure why that last one works, but it fixed it. If anyone knows why it worked please let me know.
I have multiple divs zero width on page load, they are then extended (just after page load) by a keyframe transition like so (for example). Each of these divs has a different final width.
#keyframes growN {
from {width: 0px;}
to {width: 21vw;}
}
I would like to add a second animation that extends the div further (to a fixed value) on hover, and sets it back to its original (post page load animation) width on de-hover (un-hover?). Something like this:
#keyframes hover_grow {
from {width: element.width;}
to {width: 50vw;}
}
Since there are many divs, I'd rather not do the maths myself (separate animation for each div, with its own width in place of element.width).
I have tried the following:
bar:hover {
-webkit-animation-name: hover_grow;
-webkit-animation-duration: 0.1s;
-webkit-animation-timing-function: ease-out;
-webkit-animation-direction: alternate;
animation-name: grow;
animation-duration: 1s;
animation-timing-function: ease-out;
animation-direction: alternate;
}
#-webkit-keyframes hover_grow {
from {width: initial;}
to {width: 25vw;}
}
#keyframes hover_grow {
from {width: initial;}
to {width: 25vw;}
}
This works on hover - the div extends further, but on de-hover, it returns it to its page load, pre animation value (i.e. 0), and its page load animation triggers again. Also, the timing seems to be ignored.
JSFiddle: https://jsfiddle.net/an1o4brL/3/
one way to work this around is to use a wrapper, animate the initial appearance then grow and shrink the wrapper on hover, the child will follow its parent's width,
other wise use js
#bar4 {
height: 30px;
transition: width .5s linear;
display: block;
animation-name: grow4;
animation-duration: .5s;
animation-timing-function: ease-out;
animation-iteration-count: 1;
background-color: white;
border: 2px solid #5e0734;
margin-top: 0.15vh;
margin-bottom: 0.15vh;
margin-left: 0.5vh;
overflow: hidden;
}
#keyframes grow4 {
from {
width: 0;
}
to {
width: 100%;
}
}
#bar4Wrap {
width: 21vw;
transition: width .5s linear;
}
#bar4Wrap:hover {
width: 100%;
}
<div id="bar4Wrap">
Link
</div>
I am trying to animate with CSS the a line through on a bit of text, but it's not actually animating, just going from hidden to displayed. Can anyone advise if what I'm trying is actually possible? If not, is there another way to achieve this?
HTML:
<div>
The text in the span <span class="strike">is what I want to strike out</span>.
</div>
CSS:
#keyframes strike{
from{text-decoration: none;}
to{text-decoration: line-through;}
}
.strike{
-webkit-animation-name: strike; /* Chrome, Safari, Opera */
-webkit-animation-duration: 4s; /* Chrome, Safari, Opera */
animation-name: strike;
animation-duration: 4s;
animation-timing-function: linear;
animation-iteration-count: 1;
animation-fill-mode: forwards;
}
You can use a pseudo like this
Note (thanks to Phlame), this left-to-right animation won't work if the line to strike breaks in to a second line. For that one need to use yet another pseudo element and some script to position the two properly. Or use some other animation effect, e.g. like the one suggested in Oriol's answer.
#keyframes strike{
0% { width : 0; }
100% { width: 100%; }
}
.strike {
position: relative;
}
.strike::after {
content: ' ';
position: absolute;
top: 50%;
left: 0;
width: 100%;
height: 1px;
background: black;
animation-name: strike;
animation-duration: 4s;
animation-timing-function: linear;
animation-iteration-count: 1;
animation-fill-mode: forwards;
}
<div>
The text in the span <span class="strike">is what I want to strike out</span>.
</div>
It depends on how you want to animate it.
Since text-decoration-color is animatable, you can animate it from transparent to auto.
But this property is not widely supported yet.
#keyframes strike {
from { text-decoration-color: transparent; }
to { text-decoration-color: auto; }
}
.strike {
text-decoration: line-through;
animation: strike 4s linear;
}
<div>
The text in the span <span class="strike">is what I want to strike out</span>.
</div>
Here's a variation on the accepted answer, using an image to provide an animated "scribble" strike-through.
html {
font-family: Helvetica;
font-size: 24px;
}
.strike { position:relative; }
.strike::after {
content:' ';
position:absolute;
top:50%; left:-3%;
width:0; height:10px;
opacity:80%;
transform:translateY(-50%);
background:repeat-x url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB0AAAAKAQMAAAByjsdvAAAABlBMVEUAAADdMzNrjRuKAAAAAXRSTlMAQObYZgAAADdJREFUCNdj+MMABP8ZGCQY/h9g+MHw/AHzDwbGD+w/GBhq6h8wMNj/b2BgkP8HVMMPUsn+gQEAsTkQNRVnI4cAAAAASUVORK5CYII=);
animation: strike 2s linear .3s 1 forwards;
}
#keyframes strike { to { width: 106%; } }
This thing and <span class="strike">this thing and</span> this thing.
It's very elegant, IMO, to use linear-gradient as background, and paint line which is the same color as the text (currentColor).
This solution is very flexible, opens up the door to many interesting effects and is also much less code than a pseudo-element solution.
PS: It also supports multi-line texts
From my CodePen:
span {
--thickness: .1em;
--strike: 0;
background: linear-gradient(90deg, transparent, currentColor 0) no-repeat
right center / calc(var(--strike) * 100%) var(--thickness);
transition: background-size .4s ease;
font: 25px Arial;
padding: 0 .2em;
}
span:hover {
--strike: 1; /* "1" means "true" (show the strike line) */
background-position-x: left;
}
<span contenteditable spellcheck='false'>
Strike-through animation (hover)
</span>
According to W3Schools, the text-decoration property is not animatable.
However, if you use jQuery, you can. (See here)
I have used a CSS3 effect where the black box scales to 0.25 to the top-left corner on a mouse hover.
The problem I face here is that once hovered, the animation starts and if the mouse pointer is still within range of the black box (and get hovered), the animation again restarts from the existing point. This prevents a smooth transition. How can this be solved?
This link contains the black box
Below is the code. Note that the black box is wrapped in the CSS clas 'image-effect'.
.image-effect {
animation-name: slideUp;
transition: all 0.5s;
-webkit-animation-name: slideUp;
animation-duration: 1s;
-webkit-animation-duration: 1s;
animation-timing-function: ease;
-webkit-animation-timing-function: ease;
}
.image-effect:hover {
transform: scale(0.25) ;
transform-origin: top left;
overflow: hidden;
}
Thanks in advance.
You need to add a parent element that contains the hover, but does not transform. Your CSS would end up looking something like this:
.parent-element:hover .image-effect {
transform: scale(0.25) ;
transform-origin: top left;
overflow: hidden;
}
Check out this fiddle http://jsfiddle.net/7wdqmhrd/
Target an inner div element with the effect instead like the following :
.image-effect div {
animation-name: slideUp;
transition: all 0.5s;
-webkit-animation-name: slideUp;
animation-duration: 1s;
-webkit-animation-duration: 1s;
animation-timing-function: ease;
-webkit-animation-timing-function: ease;
}
.image-effect:hover div {
transform: scale(0.25);
transform-origin: top left;
overflow: hidden;
}
Hope it helps!
1) Add an inner div tag
<div class="image-effect">
<div> // Beginning Tag Added
<img class="size-full wp-image-225 alignleft" src="http://albion123.byethost7.com/creative/wp-content/uploads/2015/01/bg11.png" alt="bg1" data-id="225">
</div> // Ending Tag Added
</div>
2) Just add a div tag to both your classes
.image-effect div
.image-effect:hover div
Because you are wanting to move the inner div.
I have a div I've animated on hover. However when I am not hovering the div won't disappear
This is what the entire thing looks like in action: http://jsfiddle.net/Vbxtc/
This is the html:
<nav>
<div id="controls">
<button id="playButton">Play</button>
<div id="defaultBar">
<div id="progressBar"></div>
</div>
<button id="vol" onclick="level()">Vol</button>
<button id="mute">Mute</button>
<button id="full" onclick="toggleFullScreen()">Full</button>
</div>
<div id="playlist" class="animated fadeInRight">
<div>cats</div>
<div>cats</div>
<div>cats</div>
</div>
</nav>
This is the CSS i've made:
#playlist{
position:absolute;
display:block;
border:1px solid red;
height: 82%;
width: 25%;
top: 20px;
right: 0px;
z-index: 2;
float:right;
padding: 0px;
margin: 0px;
color:white;
background-color:#999999;
opacity: 0;
}
#playlist:hover {
opacity: 1;
}
This is the animation im trying
.animated:hover {
-webkit-animation-fill-mode: both;
-moz-animation-fill-mode: both;
-ms-animation-fill-mode: both;
-o-animation-fill-mode: both;
animation-fill-mode: both;
-webkit-animation-duration: 1s;
-moz-animation-duration: 1s;
-ms-animation-duration: 1s;
-o-animation-duration: 1s;
animation-duration: 1s;
}
.fadeInRight {
-webkit-animation-name: fadeInRight;
-moz-animation-name: fadeInRight;
-o-animation-name: fadeInRight;
animation-name: fadeInRight;
}
#-webkit-keyframes fadeOutRight {
0% {
opacity: 1;
-webkit-transform: translateX(0);
}
100% {
opacity: 0;
-webkit-transform: translateX(20px);
}
}
#-webkit-keyframes fadeInRight {
0% {
opacity: 0;
-webkit-transform: translateX(20px);
}
100% {
opacity: 1;
-webkit-transform: translateX(0);
}
}
I noticed that when you time the mouse over exactly right (hover for about 1 second and move mouse up top), it DOES fade out nicely.
The other thing is, if you add the class fadeOutRight as follows:
<div id="playlist" class="animated fadeInRight fadeOutRight">
It fades out too quickly.
I know I didn't help much but the answer lies in the timing.
Also, if you had the fadeOutRight class on, for example, the sidebar, it works nicely!
<aside id="sidebar" class="fadeOutRight">
Perhaps, put the class of fadeOutRight on everything EXCEPT the fadeInRight div.
It's not a good idea to play with an element position in the hover state.
Even if you get to program it right (that is not easy), most of the time the user won't understand what's happening.
You can get flickering scenarios where, without the user moving the cursor, your div leaves the cursor position, canceling the hover, the div re-entering the cursor, the hover triggering , and so on.
I would recomend to trigger the hover on another div that covers the full area where the moving div will be.