I have a basic setup. When I increase the height, I get a smooth increase. When decreased, I should get a smooth decrease but instead a sharp decrease.
<div className="foo <!-- -->">Hey</div>
You may have noticed className and <!-- -->, I'm using react. <!-- --> gets replaced with the class to decrease the height.
// SCSS
.foo {
height 400px;
// background props
transition: all 250ms ease-out
}
.foo.decreaseClass {
height: 40px;
transition: all 250ms ease-in
}
When the new class is attached, the div becomes
<div className="foo decreaseClass">Hey</div>
How to get both transitions down/up?
It's because you're not properly closing the height declaration in .foo. You're using a comma instead of a semi-colon, rendering both height and transition declarations invalid. Also note the same declaration should contain a colon between the style property name and its value (height: 400px;).
Therefore, your element only has defined height and transition only when having both classes.
See it working:
document.querySelector('.foo').addEventListener('click', function(event) {
event.target.classList.toggle('decreaseClass')
})
.foo {
height: 200px;
transition: all 250ms ease-out;
border: 1px solid
}
.foo.decreaseClass {
height: 40px;
transition-timing-function: ease-in
}
<div class="foo">Hey</div>
Use CSS #keyframe animation and alternate properties. infinite is added just for demo purposes. Instead of height I added transform:scaleY(1) to (10).
Demo
body {
overflow: hidden
}
.test {
width: 200px;
margin: 10px;
background: red;
font-size: 32px;
text-align: center;
color: white
}
.B {
height: 40px;
animation: animB 1s alternate infinite;
transform-origin: top;
}
#keyframes animB {
0% {
transform: scaleY(1);
}
100% {
transform: scaleY(10);
}
}
<div class='test B'>TEST</div>
Related
I am trying to make a loading animation. I am using css transition to transition into the loading by scaling and then using animation to scale out the x axis. But when I try to transition back to the original state it doesn't use the transition anymore it just snaps back. I could use animation for the whole thing but I want to account for the page continuing to load so I don't want to have to write extra javascript logic to handle it. It would be nice if It would just transition on its own.
When you click the following snippet the first time it works fine. But when you click it again it just snaps back to its original state and doesn't use the transition. If you use a different property like opacity in the animation part then it works fine so I'm assuming there is something with the browser not recognizing the current scaled value. Is this a bug or am I doing something wrong?
document.querySelector('.wrapper').addEventListener('click', () => {
document.querySelector('.wrapper').classList.toggle('loading')
})
.wrapper{
position:fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.wrapper > div{
color: white;
display:flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
background: blue;
transition: transform 500ms ease-out;
transform: scale(1);
}
.wrapper.loading > div{
transform: scale(0.2, 0.002);
animation: loading 1000ms ease-out infinite;
animation-delay: 500ms;
}
#keyframes loading {
0%{
transform: scale(0.2, 0.002)
}
50%{
transform: scale(0.5, 0.002)
}
100%{
transform: scale(0.2, 0.002)
}
}
<div class="wrapper">
<div>click me</div>
</div>
TL;DR
I believe that this happens because CSS transition eventually gives a class two states and transitions between them, when you remove your class you don't change its state, you remove it. my solution would be to add another class to set it back.
CSS transitions work by defining two states for the object using CSS. In your case, you define how the object looks when it has the class "loading" and you define how it looks when it doesn't have the class "saved" (it's normal look). When you remove the class "loading", it will transition to the other state according to the transition settings in place for the object without the "loading" class.
If the CSS transition settings apply to the object (without the "loading" class), then they will apply to both transitions.
your transition CSS settings only apply to .saved and thus when you remove it, there are no controls to specify a CSS setting. You may want to add another class ".fade" that you leave on the object all the time and you can specify your CSS transition settings on that class so they are always in effect.
I don't know a pure css fix for this.
But you can add a different class with a animation that restores to what it was before with JS
const wrapper = document.querySelector(".wrapper");
wrapper.onclick = () => {
if ([...wrapper.classList].includes("loading")) {
wrapper.classList.add("restore");
} else {
wrapper.classList.remove("restore");
}
wrapper.classList.toggle("loading");
};
.wrapper {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.wrapper>div {
color: white;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
background: blue;
animation: none;
transform: scale(1);
transition: transform 500ms ease-out;
}
.wrapper.restore>div {
animation: restore 500ms ease-out;
}
.wrapper.loading>div {
transform: scale(0.2, 0.002);
animation: loading 1000ms 500ms ease-out infinite;
}
#keyframes restore {
0% {
transform: scale(0.2, 0.002);
}
100% {
transform: scale(1);
}
}
#keyframes loading {
0% {
transform: scale(0.2, 0.002)
}
50% {
transform: scale(0.5, 0.002)
}
100% {
transform: scale(0.2, 0.002)
}
}
<div class="wrapper">
<div>click me</div>
</div>
You can use animation iteration count property:
div {
animation-iteration-count: 2;
}
or use fill mode to freeze the animation at the end:
-webkit-animation-fill-mode: forwards;
So, I was trying to get an image to, when hovered over, spin 360 degrees and scale up by 1.4, all with its centre staying in place. I tried this:
.logo img[data-v-4fbac4e1] {
width: 50px;
height: 50px;
content: url(https://i.imgur.com/txz1IXI.png);
transition: width 2.0s, height 2.0s, transform 2.0s;
}
with this:
.logo img[data-v-4fbac4e1]:hover{
width: 65px;
height: 65px;
transform: rotate(360deg);
}
and it works fine, but it moves off-centre as it expands. How do I make sure the width and height increase from the centre so it stays in the same place? Sorry if this seems elementary, I'm new to CSS.
Edit: the part of the HTML I'm using looks like this:
<a data-v-4fbac4e1 href="/home" class="logo">
<img data-v-4fbac4e1 src="/img/icons/icon.svg">
</a>
If more is required I can add it, but this is the HTML for the image I'm trying to transform.
Since I'm not entirely sure what you mean, point to which is your culprit and we'll get you sorted out but here's some examples of the differences between techniques.
img, div {
display: inline-block;
margin: 1rem;
height: 10rem;
width: 10rem;
}
.fancy-img1, .fancy-img3 {
object-fit: cover;
outline: red 2px solid;
}
.fancy-img2, .fancy-img4 {
background: url(https://picsum.photos/200) no-repeat center center / cover;
outline: blue 2px solid;
}
/* grow by height value change transition */
.fancy-img1 {
transition: transform .5s, height .5s;
}
.fancy-img2 {
transition: transform .5s, height .5s;
}
.fancy-img1:hover, .fancy-img2:hover {
transform: rotate(360deg);
height: 15rem;
}
/* Scale with transition */
.fancy-img3 {
transition: transform .5s;
}
.fancy-img3:hover {
transform: scaleY(1.5) rotate(360deg);
}
/* Scale with keyframes */
#keyframes spinGrow {
to { transform: scaleY(1.5) rotate(360deg); }
}
.fancy-img4:hover {
animation: spinGrow .5s forwards;
}
<h2>Are you talking about transition height which cause the jumpy effect?</h2>
<img class="fancy-img1" src="https://picsum.photos/200">
<div class="fancy-img2"></div>
<h2>Or actually scale so it remains in its original position?</h2>
<img class="fancy-img3" src="https://picsum.photos/200">
<div class="fancy-img4"></div>
Does anybody know how to play transitions from two separate Components
with the same styling at the same time.
Here is a video, which shows my problem.
https://youtu.be/WNu4Mdfn98U
Important CSS Parts
.Container_Active .Description {
max-height: 500px;
margin-top: 5px;
color: var(--ifm-color-on-primary);
transition: max-height 1000ms ease-in; /* Transiation 1 */
}
.Description {
max-height: 0;
margin: 0;
font-size: var(--ifm-font-size-18);
overflow: hidden;
transition: max-height 1000ms ease-out; /* Transiation 2 */
}
Important HMTL Parts
<div
className={clsx(styles.Container, {
[styles.Container_Active]: active,
})}
>
</div>
<SectionRightItem
key={i}
title={section.title}
description={section.description}
onClick={() => {
setIndex(i);
}}
icon={section.icon}
active={index === i}
/>
My goal is that the one element slowly shows the description and the other element slowly hides the expanded description at the same time.
But somehow the transitions are played in a row, although they are triggered at the same time.
Thank you ^^
Actually your animation is starting at the same time, but the problem is that you use the transition of max-height with a value that's too high, so the transition will start from the height of 500px to 0px, but your content height doesn't even reach half of it, so it appears like there's a delay between your transition
To resolve the problem, you can lower the value of .Container_Active to match your actual description height, or change it to height rather than max-height with an average height of your actual description
Here's a simple snippet about the difference between max-height (light blue) and height (red) for the transition which makes your transition looks like it's delayed, both height / max-height is set to 0 when not opened and 10em when opened
$(function() {
setInterval(function() {
$('div').toggleClass('open');
}, 1500);
});
div {
position: absolute;
}
#front {
max-height: 0;
overflow: hidden;
background: lightblue;
transition: max-height 1000ms ease-in-out;
padding-left: 3em;
}
#front.open {
max-height: 10em;
transition: max-height 1000ms ease-in-out;
}
#back {
height: 0;
background: red;
transition: height 1000ms ease-in-out;
opacity: .75;
}
#back.open {
height: 10em;
transition: height 1000ms ease-in-out;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='front' class='open'>
Hello World Welcome<br/>World</br>Welcome
</div>
<div id='back' class='open'>
BACK
</div>
This question already has answers here:
CSS3 transition doesn't work with display property [duplicate]
(7 answers)
Closed 4 years ago.
My code transition and transform is not works.
My CSS
div.panel {
display: none;
}
div.panel.show {
display: block !important;
}
.panel.show .text-light{
transform:translateY(10%);
background:red;
transition-delay:3s;
}
full code is here. Thanks for your help
Try this
div.panel .text-light{
width: 0;
height: 0;
opacity: 0;
}
div.panel.show .text-light{
width: 100%;
height: 100%;
opacity: 1;
}
.panel.show .text-light{
transform:translateY(10%);
-webkit-transition: all 1s ease-in-out;
-moz-transition: all 1s ease-in-out;
transition: all 1s ease-in-out;
background:red;
}
The problem with your code was that you were applying transition to the element whose styles were not getting changed by the code you wrote. The transition will work only if there is some change in css on the element where you are applying the transition.
Transition animates the process of changing state1 to state1.
First of all you should set property transition and set which parameter to animate, how long. Then optional - type of animation(ease, ease-in-out so on), delay and more you can find here https://www.w3schools.com/cssref/css3_pr_transition.asp.
Then you need to change that property which you want to animate. For example
.animated {
background-color: #eee;
border: 2px dashed black;
border-radius: 5px;
width: 100px;
height: 100px;
/*
this is your transition for background-color
also you could set 'all' insted of propety which will animate any change of element
*/
transition: background-color .5s ease;
}
/* There is a second state which we want to apply a transition to */
.animated:hover {
background-color: #e6e;
}
<div class="animated">
Hover me
</div>
CODE SAMPLE HERE: http://codepen.io/colbisaurusrex/pen/YZdKyO?editors=1100
First problem:
I am trying to smoothly expand and compress a div (class: event) on hover. It expands smoothly, but it snaps back quickly when user is no longer hovering on div. I'd like to transition back at the same ease as it expands
Second problem:
Simultaneously, I'd like to reveal an inner, hidden child(class: hidden) when I hover over its parent(class: event). Ideally, I'd like to reveal it when the parent is fully expanded. And ease it back to hidden as the parent compresses. Right now, it is revealed immediately, before the parent div is fully expanded. I have tried to add a delay.
Basically, there is a beginning and ending transition that exact mirrors of each other. I'd like to do this with no Javascript
Bonus Question: If the entire transition was set off by a button click(say the Show Details button), do I have to use JS? Is there a way to do this with CSS only?
/* This is the CSS I am working with */
.event {
margin-top: 2%;
width: 960px;
border-color:#496DD9;
border-style: dotted;
font-size: 0.5em;
height: 250px;
transform: height 300ms ease-out;
}
.event:hover {
height: 300px;
transition: height 500ms ease-in;
}
.event:hover .hidden {
display: block;
transition: display 300ms ease-in 1s;
}
.hidden {
font-size: 30px;
display: none;
}
/* End of css */
problem 1: transform should be transition
.event {
margin-top: 2%;
width: 960px;
border-color:#496DD9;
border-style: dotted;
font-size: 0.5em;
height: 250px;
transform: height 300ms ease-out; // change this to transition
}
Problem 2: try using opacity instead of display:
.event:hover .hidden {
/* display: block; */
/* transition: display 500ms ease-in 1s; */
-webkit-transition: opacity 2s ease-in-out;
opacity: 1;
}
.hidden {
font-size: 30px;
/* display: none; */
opacity: 0;
}
demo: http://codepen.io/anon/pen/NpeWZz?editors=1100