CSS suddenly transition out - html

Click me for more information
when the mouse icon is moved away from the element, element suddenly returns to original state
(I showed it in the video)
.productinfo {
display: flex;
flex-direction: column;
align-items: center;
margin-left: 1%;
margin-top: 3%;
color: #ff0062;
flex: 0 0 25%;
border: 3px solid #FF00FF;
transition: 1ms;
}
.productinfo:nth-child(-n+3) {
margin-top: 1%;
}
.productinfo:hover {
animation: changeColor 3s, changefontsize 5s forwards;
}
#keyframes changeColor{
33%{border-top: 3px solid #4281A4;}
66%{border-right: 3px solid #4281A4;}
66%{border-left: 3px solid #4281A4;}
100%{border-bottom: 3px solid #4281A4;}
}
#keyframes changefontsize{
0%{font-size: 5;}
25%{font-size: 10;}
50%{font-size: 15;}
100%{font-size: 25px;}
}
This is my current code

Does this approach based on CSS transitions do what you want (only showing added/changed code)?
.productinfo {
transition: border 3s linear, font-size 5s linear;
}
.productinfo:hover {
border: 3px solid #4281A4;
font-size: 25px;
}

Related

How to show full text on hover but after some delay using CSS?

I want to show full text on cursor hover but only after 1s delay. I tried adding transition property but it seems it doesn't apply to absolute elements. Here's the codepen demo.
Here's the code:
.main {
display: flex;
justify-content: center;
}
.main .parent:hover .cell {
position: absolute !important;
z-index: 1 !important;
padding-right: 10px;
background: gray;
transition-delay: 1s;
}
.main .parent {
display: block;
width: 200px;
border-right: 1px solid rgb(237, 237, 236);
white-space: nowrap;
min-height: 32px;
cursor: default;
height: 32px;
padding: 5px 8px 6px;
font-size: 14px;
overflow: hidden;
}
.main .parent .cell {
line-height: 1.5;
white-space: nowrap;
word-break: normal;
pointer-events: none;
}
<main class="main">
<div class="parent">
<span class="cell">
In publishing and graphic design, Lorem ipsum is a placeholder text
commonly used to demonstrate the visual form of a document or a typeface
without relying on meaningful content.</span
>
</div>
</main>
Notice that background color is transiting properly but the full text is shown instantly as soon as I hover.
Looking for a solution to add some delay in showing full text without using any JavaScript.
Finally made it work by using css animation. Working codepan demo
#keyframes hover-delay {
0% {
background: gray;
position:absolute;
}
100% {
background: gray;
position: absolute ;}
}
.parent {
&:hover {
.cell {
z-index: 1 !important;
padding-right: 10px;
animation-name : hover-delay;
animation-delay: 1s;
animation-duration: 2s;
// animation-iteration-count: infinite; // play animation infinite times
// alternate way: retain the style values that is set by the last keyframe
animation-fill-mode: forwards;
}
}
display: block;
width: 200px;
border-right: 1px solid rgb(237, 237, 236);
white-space: nowrap;
min-height: 32px;
cursor: default;
height: 32px;
padding: 5px 8px 6px;
font-size: 14px;
overflow: hidden;
.cell {
line-height: 1.5;
white-space: nowrap;
word-break: normal;
pointer-events: none;
}
}
Works for me, even with position:absolute;
But I went ahead and included a version that uses animation (transition too)
https://jsfiddle.net/56sxzcu7/
/* Using transition */
h1 {
transition:1s;
transition-delay:1s;
opacity:1;
position:absolute;
}
h1:hover {
opacity:0.5;
}
/* Using animate */
h2:hover {
animation: example 2s linear 2s infinite alternate;
}
#keyframes example {
0% {opacity:1;}
100% {opacity:0.5;}
}

overlay animation should not be shown outside the underlying div [duplicate]

This question already has answers here:
Position absolute but relative to parent
(5 answers)
Closed 2 years ago.
here is my attempt to have overlay animation effect but overlay is not hiding after getting out of the underlying div- 'overflowTest'
#overflowTest {
background: #ff0000;
color: white;
padding: 15px;
width: 150px;
height: 100px;
overflow: hidden;
text-shadow: 6px 6px 5px black;
}
#box{
position: absolute;
width: 60px;
height: 60px;
border: 5px solid black;
animation-name: go;
animation-duration: 6s;
animation-fill-mode: forwards;
animation-iteration-count: infinite;
transform: rotate(45deg);
}
#keyframes go {
0%{
border: 3px solid red;
}
100%{
border: 3px solid red;
transform: translateX(200px);
}
}
<div id="overflowTest"><div id="box"></div><div id="hel">This is demo text to test overlay animation on it</div></div>
please help in hiding the overlay when it is outside the 'overflowTest' div
You need to add position: relative; to the parent #overflowTest.
An Element with position: absolute; will behave absolute to the first parent with a relative position. If no other is declared as relative, it will behave absolute to the page itself, which was happening before.
#overflowTest {
position: relative;
background: #ff0000;
color: white;
padding: 15px;
width: 150px;
height: 100px;
overflow: hidden;
text-shadow: 6px 6px 5px black;
}
#box{
position: absolute;
width: 60px;
height: 60px;
border: 5px solid black;
animation-name: go;
animation-duration: 6s;
animation-fill-mode: forwards;
animation-iteration-count: infinite;
transform: rotate(45deg);
}
#keyframes go {
0%{
border: 3px solid #ffaaaa;
}
100%{
border: 3px solid #ffaaaa;
transform: translateX(200px);
}
}
<div id="overflowTest">
<div id="box"></div>
<div id="hel">This is demo text to test overlay animation on it</div>
</div>
Hope that is what you are looking for!
The property you should use is z-index.
Setting z-index:-1; will help you get the desired result. z-index works only when position property is also added.
Try this,
#overflowTest {
background: #ff0000;
color: white;
padding: 15px;
width: 150px;
height: 100px;
overflow: hidden;
text-shadow: 6px 6px 5px black;
}
#box{
position: absolute;
width: 60px;
height: 60px;
border: 5px solid black;
animation-name: go;
animation-duration: 6s;
animation-fill-mode: forwards;
animation-iteration-count: infinite;
transform: rotate(45deg);
z-index:-1;
}
#keyframes go {
0%{
border: 3px solid red;
}
100%{
border: 3px solid red;
transform: translateX(200px);
}
}
<div id="overflowTest"><div id="box"></div><div id="hel">This is demo text to test overlay animation on it</div></div>
Hope it helps.!! Happy Coding!!

How to prevent the child from parent animation in css? [duplicate]

The title pretty much says it all but here is an example.
Let's say I have a CSS 'loading spinner' as below:
.spinner {
height: 50px;
width: 50px;
position: relative;
animation: rotate .6s infinite linear;
border-left: 6px solid #222;
border-right: 6px solid #222;
border-bottom: 6px solid #222;;
border-top: 6px solid #ccc;
border-radius: 100%;
}
#keyframes rotation {
from {
transform: rotate(0deg);
}
to {
transform: rotate(359deg);
}
}
I want to add a pseudo element to this - for example with content: 'loading...' before or after .spinner.
Is it possible to ensure the pseudo element does not inherit the animation from .spinner, or must a pseudo element always take what the parent has?
As the pseudo-element is a child element of the parent it will continue to get rotated as long as parent has the animation. Even setting animation: none on the pseudo element will have no effect.
The only way to make it look as though the child has no animation is to reverse the effect like shown in below snippet. What is being done is that the very same animation is added to the pseudo element but the animation-direction is set as reverse. This means that the pseudo get the exact reverse transform effect and thus would retain it in the same position.
.spinner {
height: 50px;
width: 50px;
position: relative;
animation: rotation .6s infinite linear;
border-left: 6px solid #222;
border-right: 6px solid #222;
border-bottom: 6px solid #222;
border-top: 6px solid #ccc;
border-radius: 100%;
}
.spinner:after {
position: absolute;
content: 'Loading..';
top: 0px;
left: 0px;
height: 100%;
width: 100%;
animation: rotation .6s infinite linear reverse; /* added this line */
}
#keyframes rotation {
from {
transform: rotate(0deg);
}
to {
transform: rotate(359deg);
}
}
<div class='spinner'></div>
The above snippet uses the default setting for transform-origin which is 50% 50% but if the child pseudo-element has padding and/or margin then the transform-origin setting has to be adjusted accordingly to avoid the pseudo-element from producing a shivering like effect. The calculation logic is provided in the below snippet.
.spinner {
height: 50px;
width: 50px;
position: relative;
animation: rotation .6s infinite linear;
border-left: 6px solid #222;
border-right: 6px solid #222;
border-bottom: 6px solid #222;
border-top: 6px solid #ccc;
border-radius: 100%;
}
.spinner.parent-padded-margin {
padding: 10px;
margin: 10px;
}
.spinner:after {
position: absolute;
content: 'Loading..';
top: 0px;
left: 0px;
height: 100%;
width: 100%;
animation: rotation .6s infinite linear reverse;
/* added this line */
}
.spinner.child-padded-margin:after {
padding: 10px 8px;
margin: 5px 4px;
transform-origin: calc(50% - 12px) calc(50% - 15px); /* calc(50% - ((padding-left + padding-right)/2 + margin-left)) calc(50% - ((padding-top + padding-bottom)/2 + margin-top)) */
}
.spinner.child-padded-margin-2:after {
padding: 10px 6px 16px 14px;
margin: 7px 12px 5px 10px;
transform-origin: calc(50% - 20px) calc(50% - 20px); /* calc(50% - ((padding-left + padding-right)/2 + margin-left)) calc(50% - ((padding-top + padding-bottom)/2 + margin-top)) */
}
#keyframes rotation {
from {
transform: rotate(0deg);
}
to {
transform: rotate(359deg);
}
}
<div class='spinner'></div>
<div class='spinner parent-padded-margin'></div>
<div class='spinner child-padded-margin'></div>
<div class='spinner child-padded-margin-2'></div>
Positioning the pseudo-element (using top,left,bottom,right ) also has affects the animation. It would also require the transform-origin to be modified accordinly in-order for the animation to work properly. A sample is available in the below snippet.
.spinner {
height: 50px;
width: 50px;
position: relative;
animation: rotation .6s infinite linear;
border-left: 6px solid #222;
border-right: 6px solid #222;
border-bottom: 6px solid #222;
border-top: 6px solid #ccc;
border-radius: 100%;
}
.spinner.parent-padded-margin {
padding: 10px;
margin: 10px;
}
.spinner:after {
position: absolute;
content: 'Loading..';
height: 100%;
width: 100%;
animation: rotation .6s infinite linear reverse; /* added this line */
}
.spinner.child-positioned{
margin-bottom: 40px;
}
.spinner.child-positioned:after {
top: 120%;
left: 2%;
transform-origin: calc(50% - 2%) calc(50% - 120%); /* basically need to subtract the distance from the left and top of the container */
}
.spinner.child-positioned-negative:after {
bottom: -120%;
right: -2%;
transform-origin: calc(50% - 2%) calc(50% - 120%); /* basically need to subtract the distance from the left and top of the container */
}
#keyframes rotation {
from {
transform: rotate(0deg);
}
to {
transform: rotate(359deg);
}
}
<div class='spinner child-positioned'></div>
<div class='spinner child-positioned-negative'></div>
Note: Both the above solutions work perfectly fine in latest versions of Chrome, Opera and Safari but are causing the text to have a slanted appearance in IE 11, Edge and Firefox. Firefox seems to require a separate animation which goes from rotate(-10deg) to rotate(-370deg) for FF while it gets more complex in IE.
The only alternate without setting the reverse animation on pseudo (child) element would be to make use of the method mentioned by Chris in his comment. That would mean setting borders and the animation directly to the pseudo element. This would mean that the parent's contents would remain unaffected as the parent won't get affected by a transform on the child.
.spinner {
height: 50px;
width: 50px;
position: relative;
}
.spinner:after {
position: absolute;
content: '';
top: 0px;
left: 0px;
height: 100%;
width: 100%;
animation: rotation .6s infinite linear;
border-left: 6px solid #222;
border-right: 6px solid #222;
border-bottom: 6px solid #222;
border-top: 6px solid #ccc;
border-radius: 100%;
}
#keyframes rotation {
from {
transform: rotate(0deg);
}
to {
transform: rotate(359deg);
}
}
<div class='spinner'>Loading...</div>
For completeness to the question alongside the comprehensive answer from #Harry I produced a version with the text below the spinner. The method of this is to use the .spinner as a canvas, put the actual spinning circle :before and the loading... in the :after as follows:
.spinner:before {
content: ' ';
display: block;
height: 50px;
width: 50px;
margin: 24px auto 6px auto;
animation: rotation .6s infinite linear;
border-left: 6px solid #222;
border-right: 6px solid #222;
border-bottom: 6px solid #222;;
border-top: 6px solid #ccc;
border-radius: 100%;
}
.spinner {
height: 100px;
width: 100px;
position: relative;
}
.spinner:after {
display: block;
text-align: center;
content: 'loading...';
}
#keyframes rotation {
from {
transform: rotate(0deg);
}
to {
transform: rotate(359deg);
}
}
<div class='spinner'></div>

CSS after mouse is moved from hover

In CSS, the hover event is triggering as it should. However, when it is an animation, when the mouse is moved back off the object (in this case a button), it returns to its normal state without an animation back. This results in it looking really jumping and going against the theme I'm shooting for. So, I need an event that is triggered after the hover event, like what I thought would work: .button-default:hover:after {}, but didn't work the way I expected. My CSS below:
.button-default {
width: 40vw;
height: 5vh;
color: white;
background: transparent;
border: solid 2px;
border-radius: 5px;
border-color: white;
}
.button-default:hover {
animation-name: animate-button;
animation-duration: 2s;
animation-fill-mode: forwards;
}
.button-default:hover:after {
animation-name: normalize-button;
animation-duration: 2s;
animation-fill-mode: forwards;
}
#keyframes normalize-button {
from {
color: blue;
background: white;
border-color: blue;
}
to {
width: 40vw;
height: 5vh;
color: white;
background: transparent;
border: solid 2px;
border-radius: 5px;
border-color: white;
}
}
#keyframes animate-button {
from {
.button-default;
}
to {
color: blue;
background: white;
border-color: blue;
}
}
body {
font-family: 'Oswald', sans-serif;
/*background: url('../images/novam.png') no-repeat center;*/
background: black;
background-size: cover;
}
As your animation only need two stages, you can just use css transition instead of animation to get that effect. And FYI, after is pseudo element. It is not event.
.button-default {
width: 40vw;
height: 5vh;
color: white;
background: transparent;
border: solid 2px;
border-radius: 5px;
border-color: white;
-webkit-transition: all 2s ease;
transition: all 2s ease;
-moz-transition: all 2s ease;
}
.button-default:hover {
color: blue;
background: white;
border-color: blue;
}
Fiddle here

Css animation-fill-mode backwards does not work

I have a link that i want to animate his border from 1px to 5px on click and in the end of the animation i want the 1px to stay, i am using animation-fill-mode with backwards but i see that the 1px border does not apply after the animation is finish.
document.querySelector('a').onclick = function() {
this.classList.add('border-g');
}
/* Styles go here */
body {
margin: 100px;
}
a {
border: 1px solid transparent;
display: inline-block;
padding: 20px;
}
.border-g {
-webkit-animation: border-grow 0.5s;
animation: border-grow 0.5s;
-webkit-animation-delay: 1s;
animation-delay: 1s;
-webkit-animation-fill-mode: backwards;
animation-fill-mode: backwards;
}
#-webkit-keyframes border-grow {
from {
border: 1px solid #D74C43;
}
to {
border: 5px solid #D74C43;
}
}
#keyframes border-grow {
from {
border: 1px solid #D74C43;
}
to {
border: 5px solid #D74C43;
}
}
<a>Hello world</a>
In this instance, you have to define the final state in your CSS first.
Then define the new start point in your animation
body {
margin: 100px;
}
a {
border: 1px solid #D74C43;
/* end like this */
display: inline-block;
padding: 20px;
-webkit-animation: border-grow 0.5s;
animation: border-grow 0.5s;
-webkit-animation-delay: 1s;
animation-delay: 1s;
-webkit-animation-fill-mode: backwards;
animation-fill-mode: backwards;
}
#-webkit-keyframes border-grow {
from {
border: 1px solid transparent;
/* starts like this */
}
to {
border: 5px solid #D74C43;
/* animation ends then switches to final state */
}
}
#keyframes border-grow {
from {
border: 1px solid transparent;
}
to {
border: 5px solid #D74C43;
}
}
<a>Hello world</a>
EDIT
To solve your updated question...the default states would need to be applied to the border-g class.
Otherwise the answer remains as previously.
document.querySelector('a').onclick = function() {
this.classList.add('border-g');
}
body {
margin: 100px;
}
a {
display: inline-block;
padding: 20px;
}
a.border-g {
border: 1px solid #D74C43;
-webkit-animation: border-grow 0.5s;
animation: border-grow 0.5s;
-webkit-animation-delay: 1s;
animation-delay: 1s;
-webkit-animation-fill-mode: backwards;
animation-fill-mode: backwards;
}
#-webkit-keyframes border-grow {
from {
border: 1px solid transparent;
}
to {
border: 5px solid #D74C43;
}
}
#keyframes border-grow {
from {
border: 1px solid transparent;
}
to {
border: 5px solid #D74C43;
}
}
<a>Hello world</a>
From what I read on w3.org, in case of animation-fill-mode: backwards, the properties defined in the keyframe (from or to) will only apply to animation-delay period:
4.9. The animation-fill-mode property
backwards
During the period defined by animation-delay, the animation
will apply the property values defined in the keyframe that will start
the first iteration of the animation. These are either the values of
the from keyframe (when animation-direction is normal or alternate) or
those of the to keyframe (when animation-direction is reverse or
alternate-reverse).