scale() from a high value to low distorts transition - css

I am trying to make a transition so when I click I button two divs are scaled from a small circle to a large circle. Basically that looks something like this when expanded:
This has gone from scale(1) to scale(20) and scale(25). When I click the button, the circles shrink with no problem. However, if I increase the scaling to for example scale(40) and scale(45) the result I get when clicking the button again (to shrink everything) looks like this:
So this happens right after I click. In this case I just have a transition-delay on so I could screenshot it.
The SCSS for the circles are like this:
.inner-circle-bg {
display: none;
width: 30px;
height: 30px;
border-radius: 100%;
position: fixed;
background: $primaryRed;
bottom: 35px;
right: 35px;
z-index: 999999;
transform: scale(1);
transition: transform 0.3s ease-in;
transition-delay: 4.1s;
&.is-active {
transform: scale(40);
transition: transform 0.3s ease-in;
transition-delay: 0.1s;
}
}
.outer-circle-bg {
display: none;
width: 30px;
height: 30px;
border-radius: 100%;
position: fixed;
background: $primaryRedDark;
bottom: 35px;
right: 35px;
z-index: 99999;
transform: scale(1) ;
transition: transform 0.3s ease-in;
transition-delay: 4.2s;
&.is-active {
transform: scale(45) ;
transition: transform 0.3s ease-in;
}
}
And then I just have some JS to toggle the is-active state when a button is clicked.
So yeah, any idea what might be causing this, and if there is a way to fix it ?
EDIT:
I now have a working JSfiddle illustrating the problem (although with a hover effect instead):
https://jsfiddle.net/47znjxwo/

Related

Transition not working on backdrop opacity to 0 when class is removed

I have a backdrop on my site that opens whenever it needs to. Modals, mobile nav etc.
I'd like to get the opacity of the backdrop to fade, however I can't get it to transition properly when the --open class is removed from the backdrop.
I've gone through a few iterations so any ideas on how to make it work AND be better css is appreciated.
Here's a demo demonstrating the ease effect occuring when --open is applied to the backdrop, but will not work when it is removed.
https://jsfiddle.net/p2yz0rvr/
For futures sake here's the code:
.backdrop {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: -9999999999;
opacity: 0;
text-align: center;
transition: opacity 0.3s ease-in;
}
.backdrop--open {
opacity: 0.75;
z-index: 2;
background: #000;
transition: opacity 0.4s ease-out;
}
The problem is that you don't have a background set on the initial .backdrop state, the background is set on the element .backdrop--open.
Since you are only transitioning the opacity property, the transition doesn't occur when you remove the .backdrop--open class. Therefore you would need to move background to the initial .backdrop state in order for the transition to take place when removing the class.
Updated Example
.backdrop {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: -1;
opacity: 0;
text-align: center;
background: #000;
transition: opacity 0.3s ease-in;
}
.backdrop--open {
opacity: 0.75;
z-index: 2;
transition: opacity 0.4s ease-out;
}
As an alternative, you could also keep your initial code and just transition the background property in addition to the opacity property (without having to change where the background is set).
Keep in mind that the z-index property can be transitioned, so depending on what you're trying to achieve you may only want to target those two properties rather than using all.
Updated Example
.backdrop {
/* ... */
transition: background 0.3s ease-in, opacity 0.3s ease-in;
}
.backdrop--open {
/* ... */
background: #000;
transition: background 0.4s ease-out, opacity 0.4s ease-out;
}

CSS Overlay not displaying

I am starting my foray into Modals and the CSS I am using for the overlay, just doesn't seem to want to work. Any ideas what might be happening?
It is written in SCSS
#mixin transitionSupport($transition){
-webkit-transition: $transition;
-moz-transition: $transition;
-o-transition: $transition;
transition: $transition;
}
.modal-overlay{
position: fixed;
z-index: 998;
top: 0;
left: 0;
opacity: 0;
width: 100%;
height: 100%;
#include transitionSupport(1ms opacity ease);
background: rgb(0,0,0);
.modal-open{
opacity: 1;
}
}
HTML:
<div class="modal-overlay modal-open">
</div>
Link to the codepen
When I view the page itself, the page stays white. And I have no idea why.
Should the .modal-open{opacity:1} not override .modal-overlay?
Change .modal-open { to &.modal-open { to match class="modal-overlay modal-open".
As it's written currently, it's looking to match an element called .modal-open INSIDE .modal-overlay.

picture with border-radius 50% and transform(scale)

I have a sqare image wich is turned into a circle by using border-radius: 50%; That works quite well so far. ;) But the next step is difficult to do: I want the image to zoom "nearer" by using transform: scale. I mean: I dont want to change the same size of the image, it should stay with the same diameter. But I want to show a small section of the image. The zooming should be activated on :hover and it should be processed during a period of 0.8s
My code works perfectly in Firefox, but in Chrome and Safari it does not. Where are my mistakes?
My HTML:
<div class="hopp_circle_img">
<img src="... alt="" />
</div>
My CSS:
.hopp_circle_img {
width: 100% !important;
height: 100% !important;
max-width: 100% !important;
max-height: 100% !important;
overflow: hidden;
-moz-border-radius: 50%;
-webkit-border-radius: 50%;
-o-border-radius: 50%;
border-radius: 50%;
}
.hopp_circle_img img {
transition: all 0.8s;
-moz-transition: all 0.8s;
-webkit-transition: all 0.8s;
-o-transition: all 0.8s;
-ms-transition: all 0.8s;
}
.hopp_circle_img img:hover {
display: block;
z-index: 100;
transform: scale(1.25);
-moz-transform: scale(1.25);
-webkit-transform: scale(1.25);
-o-transform: scale(1.25);
-ms-transform: scale(1.25);
}
The problems:
1) Chrome: The "zoom" works, but during the transition-time (o,8s) the image has sqare borders. After the trasition took place, they are rounded.
2) Safari:
The transition-time is ignored, transition takes place immediately, without "soft" zooming.
3) IE: I did not dare to take a look at IE, if it does not even work in Safari and Chrome. ;)
Thanks for your ideas. I tried many different things, none of them worked.
Raphael
With Harry's suggestion to fix the square, this one should work in Safari as well.
First, prefixed properties should be before unprefixed, second, don't use all as in
transition: all ...
name the properties to be transitioned, in this case
transition: transform 0.8s
Note, you need to add back the rest of the prefixed properties
.hopp_circle_img {
position: relative; /* new property added */
width: 100% !important;
height: 100% !important;
max-width: 100% !important;
max-height: 100% !important;
overflow: hidden;
-webkit-border-radius: 50%;
border-radius: 50%;
z-index: 0; /* new property added */
}
.hopp_circle_img img {
-webkit-transition: transform 0.8s; /* re-ordered property, named */
transition: transform 0.8s; /* what to be transitioned */
}
.hopp_circle_img img:hover {
display: block;
z-index: 100;
-webkit-transform: scale(1.25);
transform: scale(1.25);
}
<div class="hopp_circle_img">
<img src="http://lorempixel.com/400/400/nature/1" alt="" />
</div>
OK, I have a first success:
Changing .hopp_circle_img img:hover into .hopp_circle_img:hover fixed the problem in Safari. But it still remains in Chrome.
What fixed this issue for me was:
.hopp_circle_img {
transform: scale(.99);
}

CSS Transition after animation ends

I have a css transition that moves an element on hover and an animation that rotates the element on hover too. There's a delay on the animation equal to the transition duration so that after it's transitioned to it's correct position, the animation starts. And it works nice, however, when we mouse off, the animation stops but it doesn't transition back down.
Is it possible to get it to transition back after we mouse off and the animation ends?
You can see an example here: http://codepen.io/jhealey5/pen/zvXBxM
Simplified code here:
div {
width: 200px;
height: 200px;
margin: 40px auto;
background-color: #b00;
position: relative;
&:hover {
span {
transform: translateY(-60px);
animation-name: rotate;
animation-duration: 1s;
animation-delay: .5s;
animation-iteration-count: infinite;
animation-direction: alternate;
}
}
}
span {
position: absolute;
width: 20px;
height: 20px;
background-color: #fff;
bottom: 10px;
left: 0;
right: 0;
margin: auto;
transition: .5s;
}
#keyframes rotate {
from {
transform: translateY(-60px) rotate(0);
}
to {
transform: translateY(-60px) rotate(-90deg);
}
}
I have forked your project and adapted it so it works. You can find it here.
What I have changed is the following:
I give the white square a start position of top: 150px and let it, on hover of div, get a top: 0. The span gets a transition: top .5s and with that it goes to top: 0; on hover and back to top: 150px; when the mouse leaves.
I have removed the translateY(-60px); from the animation, because that would move it even more up when the animation would start.
Here's your new CSS:
div {
width: 200px;
height: 200px;
margin: 40px auto;
background-color: #b00;
position: relative;
&:hover {
span {
top: 0px;
animation: rotate 1s infinite .5s alternate;
animation-direction: alternate;
}
}
}
span {
position: absolute;
width: 20px;
height: 20px;
background-color: #fff;
bottom: 10px;
left: 0;
right: 0;
top: 150px;
margin: auto;
transition: top .5s;
}
#keyframes rotate {
from {
transform: rotate(0);
}
to {
transform: rotate(-90deg);
}
}
Edit: The problem is that an animation is time-based and not action-based, which means that as soon as you trigger an animation, a timer starts running and it will run through all the keyframes until the set time has passed. Hover-in and hover-out have no effect, except that the timer can be stopped prematurely, but the animation will not continue (or reversed, which you wanted) after that. transition is action-based, which means it gets triggered every time an action (for example :hover) is happening. On :hover, this means it takes .5s to go to top:0 and when the hover ends, it takes .5s to got to top:150px.
I hope the above addition makes sense :)
As you can see, I also cleaned up a bit in your animation-name: etc., since it can be combined into one line.
As Harry pointed out, the problem is that you are animating/transitioning the same property, in this case transform. It looks like the current versions of Chrome/FF will allow the animation to take control of the property, thereby breaking the transition. It seems like the only way to work around this is to transition/animation a different property. Since you need to continue rotating the element, you could translate/position the element by changing the bottom property instead. I know that doesn't produce the exact same results, but nonetheless, it does move the element (just not relative to the parent element).
Updated Example
div:hover span {
bottom: 80px;
}
As an alternative, you could also wrap the span element, and then translate that element instead.
In the example below, the .wrapper element is transitioned to translateY(-60px) on hover, and then the child span element is rotated and maintains the animation.
Example Here
div {
width: 200px;
height: 200px;
margin: 40px auto;
background-color: #b00;
position: relative;
}
div:hover .wrapper {
transform: translateY(-60px);
}
div:hover .wrapper span {
animation-name: rotate;
animation-duration: 1s;
animation-delay: .5s;
animation-iteration-count: infinite;
animation-direction: alternate;
}
.wrapper {
display: inline-block;
transition: .5s;
position: absolute;
bottom: 10px;
left: 0;
right: 0;
text-align: center;
}
.wrapper span {
display: inline-block;
width: 20px;
height: 20px;
background-color: #fff;
}
#keyframes rotate {
from {
transform: rotate(0);
}
to {
transform: rotate(-90deg);
}
}
<div>
<span class="wrapper">
<span></span>
</span>
</div>

Smooth CSS rotate animation on hover

I've create a button, and I want it to rotate 360deg on mouse hover, and rotate backwords 360deg on hover off. So far it work well, but if you go slowly towards it with the mouse, it flickers.
Here's the short version of the code:
.btn {
display: block;
margin: 60px auto;
width: 250px;
padding: 15px;
position: relative;
color: #3498db;
font-weight: 300;
font-size: 24px;
text-decoration: none;
border: 5px solid #3498db;
transform: rotate(360deg);
transition: all 0.5s;
transition-timing-function: cubic-bezier(1, 0.8, 0.5, 1);
}
.btn-rotate:hover {
transform: rotate(0deg);
transition-delay: 0;
transition: all 0.5s;
}
I am a button!
for full code, check the codpen demo http://codepen.io/andornagy/pen/ojBNZx
The flicker issue is happening because, when you hover on the element, the elements start to rotate. After rotating some x degree, the element would've rotated to certain degree and the mouse/cursor is not anymore on the element.
This is the reason the flicker is happening.
Comparing to the above one, I feel using wrapper (div) and analyzed how much width we may need, we set that to div. On div:hover element, we can perform the transition. It gives better result compared to now.
Here is the fiddle
.buttonHolder {
padding: 50px;
}
.buttonHolder:hover .btn-rotate {
transform: rotate(360deg);
transition-delay: 0;
transition: all 0.6s;
}
Here's an idea where it adds an extra pseudo element only when you're hovering :
Demo
.btn:after {
content: '';
width: 300px;
height: 150px;
display: none;
position: absolute;
top: 50%;
left: 50%;
border-radius: 50%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
.btn:hover:after {
display: block;
}
Gave it a bit of background color, just so it's better visible what's going on...
For the most control, I'd resort to some JavaScript though.

Resources