CSS Transition Delay When Fading-In, but No Delay when Fading Out - css

I am following a tutorial on how to create CSS tooltips. Everything works just fine, but there is one modification that I would like to make. I want the tool tip to show up 3 seconds after I hover over an item, but to fade out immediately when I stop hovering over the item. This is the (relevant) code I have right now:
.tooltip:hover .tooltip-text {
opacity: 0.7;
visibility: visible;
}
.tooltip-text {
...
opacity: 0;
transition: all 500ms;
transition-delay: 3s;
visibility: hidden;
...
}
This ALMOSTS works. It delays showing the tooltip for 3 seconds, like I want. However, it also delays removing the tooltip (which I do NOT want). How can I modify my code so that the tool tip fades in 3 seconds after I hover with my mouse and starts fading out immediately when I stop hovering?

Define transition properties in :hover class. Like this:
.tooltip:hover .tooltip-text {
opacity: 0.7;
visibility: visible;
transition: all 500ms;
transition-delay: 3s;
}
.tooltip-text {
opacity: 0;
visibility: hidden;
}
See working demo below. (Try hovering the red box)
.box {
width: 100px;
height: 30px;
background-color: red;
}
.tooltip {
opacity: 0;
visibility: hidden;
}
.box:hover .tooltip {
opacity: 1;
visibility: visible;
transition: all 500ms;
transition-delay: 2s;
}
<div class="box">
<div class="tooltip">
This is tooltip.
</div>
</div>

Related

Disable a transition while an animation is running

Demo of the problem: https://jsfiddle.net/t0qsek8n/1/
<div class="test" id="test">Test text</div>
.test {
position: relative;
top: 0px;
border: 1px solid #ccc;
animation: test 5s;
transition: top 1s;
}
#keyframes test {
0% {
opacity: 0;
transition: none;
}
100% {
opacity: 1;
transition: none;
}
}
const test = document.getElementById('test');
setTimeout(() => {
test.style.top = "100px"
}, 1000);
I expect if the value of top property is changed by JS, transition transition: top 1000ms doesn't happen because of transition: none that provides #keyframes test, but actually, the transition happens.
I cannot understand why transition value from keyframes doesn't override any existing definition for transition.
let's take another example using display:
.test {
position: relative;
top: 0px;
border: 1px solid #ccc;
animation: test 5s forwards;
}
#keyframes test {
0% {
opacity: 0;
display: none;
}
100% {
opacity: 1;
display: none;
}
}
<div class="test" id="test">
Test text
</div>
We logically expect to never see the element since we set display:none and we made the animation to be forwards but display is simply ignored because it cannot be animated. Same logic with transition since it's a property that we cannot animate ref.
Basically, any property that cannot be animated will simply get ignored when used with keyframes.
Properties that aren't specified in every keyframe are interpolated if possible — properties that can't be interpolated are dropped from the animation. ref

Fade out animation in pure CSS

Coming from https://stackoverflow.com/a/9334132/3779853: Let's assume a basic element that gets toggled programmatically. This could mean setting display to none/block or removing/inserting the element altogether.
$('#toggle').click(() => $('#square').toggle());
#square {
width: 50px;
height: 50px;
background: lightblue;
}
.animated {
animation: fade-in 1s;
}
#keyframes fade-in {
from { opacity: 0; }
to { opacity: 1; }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="toggle">toggle</button>
<div id="square" class="animated"></div>
With a simple animation, you can add a transition effect for when the element appears. How do you do the same thing for when the element disappears?
I do not want to add further classes, no :hover, and no more Javascript code. In many JS frameworks, you can show/hide elements easily: .toggle() (JQuery, as above), ng-if (AngularJS), *ngIf (Angular), conditional rendering (React), v-if (VueJS) and so on. With above solution, a simple class="animated" is enough to have it appear with custom animations. So I am looking for a pure CSS solution for fade out animation here, assuming this is a standard problem.
Here is a 100% pure css solution.
#square {
width: 50px;
height: 50px;
background: lightblue;
transition: opacity 1s ease-in-out;
-webkit-transition: opacity 1s ease-in-out;
-moz-transition:opacity 1s ease-in-out;
}
#myBox:checked ~ .animated {
opacity: 0;
}
#myBox ~ .animated {
opacity: 1;
}
<input type="checkbox" id="myBox" style="display:none;"/>
<button id="toggle"><label for="myBox">toggle</label></button>
<div id="square" class="animated"></div>
You can use the opacity property with transition effect.
$('#toggle').click(() => $('#square').toggleClass('animated'));
#square {
width: 50px;
height: 50px;
background: lightblue;
transition: opacity 0.5s;
opacity: 1;
}
#square.animated {
opacity: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="toggle">toggle</button>
<div id="square" class="animated"></div>

Fade-out animation without fade-in, in CSS code

I have this CSS code to insert in my custom CSS field for my website
Here is my need: when I hover on my cart button, I want the box to appear immediately, and then when I remove the mouse, to fade out with an animation of 1,5 sec
So no fade-in animation, only fade-out animation
The box selector is: .header-cart.invisible
I have tried this first:
.header-cart.invisible {
transition: 1.5s;
}
.header-cart.invisible:hover {
visibility: visible;
opacity: 1;
}
But I have fade-out AND fade-in as well.
I have tried this other version, with transition attribute:
.header-cart.invisible {
transition: 0s 1.5s, opacity 1.5s linear;
}
.header-cart.invisible:hover {
visibility: visible;
opacity: 1;
}
This time, fade-in no longer displays, but the animation now interferes with my button "Add to Cart" : when I click on it, my cart box now displays with a 1.5 second delay, while I want it to display without any
So I have tried to add more code on the add to cart button to force it to display the cart box without delay, but I am unsuccessful:
.header-cart.invisible {
transition: 0s 1.5s, opacity 1.5s linear;
}
.header-cart.invisible:hover {
visibility: visible;
opacity: 1;
}
#add_to_cart_btn.button:active > .header-cart.invisible {
visibility: visible;
opacity: 1;
transition: 0s 0s !important;
transition-delay: 0s !important;
}
Would someone happen to have an idea so that it can fit my need, from any version of my code?
It would be great, thank you very much :)
PS: I really need this code to be 100% CSS, even if I know it would be more competitive using PHP or Javascript
when I hover on my cart button, I want the box to appear immediately, and then when I remove the mouse, to fade out with an animation of 1,5 sec So no fade-in animation, only fade-out animation
Then simply specify a transition of 1.5s duration for the normal state of the element (that it will be returning to after :hover), and 0s duration/no transition for the :hover state.
div {
margin: 1em;
padding: 1em;
border: 1px solid red;
}
div + div {
opacity: 0;
transition: 1.5s;
color: #fff;
background: #00f;
}
div:hover + div {
opacity: 1;
transition: none;
}
<div>hover me</div>
<div>whoop whoop</div>
Just don't add transitions when hover the cart button, then add ease-out transition when you hover the box div
.header-cart.invisible {
background-color:#000;
color:#fff;
opacity:0;
padding:20px;
border:solid 1px #ddd;
display:block;
}
.header-cart.invisible:hover {
transition: opacity 1.5s ease-out;
}
#add_to_cart_btn.buton
{
padding:20px;
border:solid 1px #ddd;
display:block;
}
#add_to_cart_btn.button:hover + .header-cart.invisible {
transition: none;
opacity:1;
}
<button id="add_to_cart_btn" class="button">
Cart Button - show box immediately
</button>
<button class="header-cart invisible">
Box - fade when hover
</button>
First, thank you for your reply
I am a bit unfamiliar with the "+" sign in selector
And I'm unsure I understood perfectly the "div" selector from CBroe
But I have tried both your methods from what I understood
1)
.header-cart.invisible {
position: fixed !important;
top: 25px !important;
transition: transition 1.5s !important;
}
.header-cart.invisible:hover {
visibility: visible;
opacity: 1;
}
#add_to_cart_btn.button:active + .header-cart.invisible {
visibility: visible;
opacity: 1;
transition: none !important;
}
So with this method, I have no fade-in and no fade-out.
Maybe my website behaves another way
You may try this URL: https://www.tresor-ethnique.com/collections/tibetain/products/pendentif-arbre-de-vie
And one issue I notice on your code snipped (based on my needs) is that "whoop whoop" disappears in spite me hovering it
2)
.header-cart.invisible {
position: fixed !important;
top: 25px !important;
transition: opacity 1.5s ease-out !important;
}
.header-cart.invisible:hover {
visibility: visible;
opacity: 1;
}
#add_to_cart_btn.button:active + .header-cart.invisible {
visibility: visible;
opacity: 1;
transition: none !important;
}
So with this method, I have fade-in but no fade-out.
Exactly the reverse I want... And I pretty much did the same way with other methods
Again maybe my website behaves in a certain way
Based on your code snippet, It's not exactly what I want to do (sorry if not clear)
I want :
if hover "Cart button" then box appears immediately => OK
if hover "Box" then box still here => not OK on your code snippet, it disappears with 1.5s animation
if remove from "Box" then 1.5s animation => not OK on your code snippet, it disappears immediately
if remove from "Cart button" then 1.5s animation => not OK on your code snippet, it disappears immediately
I hope this is more clear now :)

Max-height transition from 0 to auto or none?

I have an element with a max-height of 0. I want to transition it to no max-height auto or none; whatever makes it expand based on the number of elements present. I don't want to use JS nor flex, yet.
Here's the jsfiddle: https://jsfiddle.net/m9pd8bjh/19/
HTML:
<nav>
<input type="checkbox" id="menu-main-checkbox" hidden>
<label class="toggler" for="menu-main-checkbox">Menu</label>
<div class="hide toggleable">
<ul>
<li>Home</li>
<li>Sample Page</li>
</ul>
</div>
</nav>
CSS:
.hide {
visibility: hidden;
overflow: hidden;
max-height: 0;
}
input[type=checkbox]:checked~.toggleable {
visibility: visible;
max-height: 68px;
}
.toggleable {
transition: visibility 1.5s ease-in-out, max-height .75s ease-in-out;
}
.toggler {
cursor: pointer
}
nav {
background: #e74c3c;
}
When I set the max-height to 68px (the height fitting two list items) it works perfectly, but when I set the max-height to 500px, for example, leaving room for future list items, it takes time to transition from 500 to 0, making it give a delay before the list items disappear again.
I do not wish to use scaling as it complicates it and I have to come up with a solution to solve the spacing under it. It keeps the spacing under the element and reserves it for when it opens out.
One workaround what I found was to use animation with #keyframes.
Remember to add vendor-prefixes.
Browser support for this is the following:
Firefox 5+, IE 10+, Chrome, Safari 4+, Opera 12+
I modified your CSS to this:
.hide {
visibility: hidden;
overflow: hidden;
max-height: 0;
}
input[type=checkbox]:checked~.toggleable {
visibility: visible;
animation: height1 .75s forwards;
}
input[type=checkbox]:not(:checked)~.toggleable {
visibility: visible;
animation: height2 .50s forwards;
}
.toggleable {
transition: visibility 1.5s ease-in-out;
}
.toggler {
cursor: pointer
}
nav {
background: #e74c3c;
}
#keyframes height1 {
0% { max-height: 0; }
100% { max-height: 500px; }
}
#keyframes height2 {
0% { max-height: 500px; }
100% { max-height: 0; }
}
If used like this there will be smaller delay when clicking again.
Here is the updated jsfiddle: https://jsfiddle.net/m9pd8bjh/25/

Pure CSS animation visibility with delay

I am trying to implement some animation onLoad without Javascript. JS is easy, CSS is ... not.
I have a div which should be on display: none; and should be display: block; after 3 secondes. Lots of resources told me animate does not work with display, but should with visibility (which I use often in my transition).
Right know I have this terrible javascript function :
<script type="text/javascript">
$(document).ready(function(){
$(".js_only").hide();
setTimeout(function () {
$(".js_only").show();
}, 3000);
});
</script>
I tried some animation in CSS but no result ... nothing seems to work.
I have few animation in my page, but just struggling with the display: none; on animation.
#-moz-keyframes showEffect {
0% { display: none; visibility: hidden; }
100% { display: block; visibility: block; }
}
#-webkit-keyframes showEffect {
0% { display: none; visibility: hidden; }
100% { display: block; visibility: block; }
}
#keyframes showEffect {
0% { display: none; visibility: hidden; }
100% { display: block; visibility: block; }
}
.css_only {
-moz-animation-name: showEffect;
-moz-animation-iteration-count: 1;
-moz-animation-timing-function: ease-in;
-moz-animation-duration: 2.3s;
-webkit-animation-name: showEffect;
-webkit-animation-iteration-count: 1;
-webkit-animation-timing-function: ease-in;
-webkit-animation-duration: 2.3s;
animation-name: showEffect;
animation-iteration-count: 1;
animation-timing-function: ease-in;
animation-duration: 2.3s;
}
It is important as hidden, this element does not take space at all. I created a JSFiddle to make quite tests.
My main concerne is SEO ... I don't think the JS option is really nice for that which is why I would like a pure CSS alternative. Also interested to test those animations and see where are those limits (Am I seeing one right now ?). Kinda having fun on such challenge.
Thanks for reading, hope someone has an answer.
You are correct in thinking that display is not animatable. It won't work, and you shouldn't bother including it in keyframe animations.
visibility is technically animatable, but in a round about way. You need to hold the property for as long as needed, then snap to the new value. visibility doesn't tween between keyframes, it just steps harshly.
.ele {
width: 60px;
height: 60px;
background-color: #ff6699;
animation: 1s fadeIn;
animation-fill-mode: forwards;
visibility: hidden;
}
.ele:hover {
background-color: #123;
}
#keyframes fadeIn {
99% {
visibility: hidden;
}
100% {
visibility: visible;
}
}
<div class="ele"></div>
If you want to fade, you use opacity. If you include a delay, you'll need visibility as well, to stop the user from interacting with the element while it's not visible.
.ele {
width: 60px;
height: 60px;
background-color: #ff6699;
animation: 1s fadeIn;
animation-fill-mode: forwards;
visibility: hidden;
}
.ele:hover {
background-color: #123;
}
#keyframes fadeIn {
0% {
opacity: 0;
}
100% {
visibility: visible;
opacity: 1;
}
}
<div class="ele"></div>
Both examples use animation-fill-mode, which can hold an element's visual state after an animation ends.
Use animation-delay:
div {
width: 100px;
height: 100px;
background: red;
opacity: 0;
animation: fadeIn 3s;
animation-delay: 5s;
animation-fill-mode: forwards;
}
#keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
Fiddle
You can play with delay prop of animation, just set visibility:visible after a delay, demo:
#keyframes delayedShow {
to {
visibility: visible;
}
}
.delayedShow{
visibility: hidden;
animation: 0s linear 2.3s forwards delayedShow ;
}
So, Where are you?
<div class="delayedShow">
Hey, I'm here!
</div>
Unfortunately you can't animate the display property. For a full list of what you can animate, try this CSS animation list by w3 Schools.
If you want to retain it's visual position on the page, you should try animating either it's height (which will still affect the position of other elements), or opacity (how transparent it is). You could even try animating the z-index, which is the position on the z axis (depth), by putting an element over the top of it, and then rearranging what's on top. However, I'd suggest using opacity, as it retains the vertical space where the element is.
I've updated the fiddle to show an example.
Good luck!
you can't animate every property,
here's a reference to which are the animatable properties
visibility is animatable while display isn't...
in your case you could also animate opacity or height depending of the kind of effect you want to render_
fiddle with opacity animation

Resources