CSS3: Transforming ONLY during Transition - css

I know we can transform shape (e.g. circle to square) from one state (e.g. top: 0) to another state (e.g. top: 20px). But I'm not sure how we can keep the shape at both states intact (i.e. keeps it circled # top: 0 and top: 20px), but ONLY during transition I want to transform its shape. An example of what I want to achieve is somewhat like this:

Here's a pure css version of what you want. It transforms only during the transition. Not hard at all. Just use keyframes to specify what properties you want changed and when.
The HTML
<div class="childAnimated"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
And the CSS
.child {
border: .5em solid white;
width: 3em;
height: 3em;
border-radius: 5em;
margin-bottom: 1em;
}
.childAnimated {
position: fixed;
top: 1em;
left: 1em;
z-index: 999;
background-color: white;
width: 3em;
height: 3em;
border-radius: 5em;
-webkit-animation: gooAnim 4s infinite;
}
#-webkit-keyframes gooAnim {
0% { top: 1em; }
25% { top: 3.8em; left: 1.5em; width: 2em; height: 2em; }
50% { top: 6em; width: 3em; height: 3em; left: 1em;}
75% { top: 8.8em; left: 1.5em; width: 2em; height: 2em; }
100% { top: 11em; }
}
If you want to see it in action, here's the codepen. Run it in Chrome if you can. http://codepen.io/shuffguy/pen/JdLXeM
This was a quick example, but if you play around with the keyframe resizing properties you can definitely emulate that example exactly with keyframes.

U can use the #keyframe animation in css for this, just take a look: https://css-tricks.com/snippets/css/keyframe-animation-syntax/
And here is a exemple what i made with keyframes and jquery animate:
Css
#box{
display: block;
background: red;
width: 300px;
height: 300px;
border-radius: 100%;
position: relative;
}
#keyframes change_form {
0% {
width: 300px;
}
50% {
border-radius: 0%;
width: 50px;
height: 100px;
}
100% {
width: 300px;
height: 300px;
}
}
Jquery
$(document).ready(function(){
window.setTimeout(function(){
$( "#box" ).animate({
"top":"+=134px"
,
},{
step: function(now) {
if (now >= 11) {
$("#box").css({'transition':'all linear 1s', 'animation':'change_form ease 2s '});
}
} }
);
}, 2000);
});
In a simple Div
<div id="box"></div>
Just a example what i make to show u how to make this effect, u can make this only with css, just putting the 'animation' in your div

Related

Add style when hover animation is finished

Is it possible to add another style when the hover animation is completely finished?
With the default hover all styles get applied at the same time.
So changing from display: none to display: block will override any transformation because the element will just appear out of nowhere.
In the following example something like this would be helpful, because right now you can trigger the hover effect from outside of the actual "hover area".
.grid_content {
padding: 15px;
position: absolute;
top: 0;
left: 0;
width: 300px;
height: 300px;
background: salmon;
}
.grid_hover {
width: calc(100% - 30px);
height: calc(100% - 30px);
opacity: 0;
transition: all 0.5s;
transition-timing-function: cubic-bezier(1, 0.09, 0.37, 0.93);
position: absolute;
z-index: 5;
}
.bottom_left {
transform-origin: bottom left;
transform: rotate(90deg);
}
.text_overlay {
top: 50%;
width: 70%;
max-height: 80%;
margin: 0 15%;
text-align: center;
z-index: 4;
position: absolute;
}
.background_overlay {
background: #ffffff;
width: 100%;
height: 100%;
bottom: 0;
opacity: 0.95;
z-index: 1;
position: absolute;
}
.box_overlay {
border: 1.5px solid #000000;
width: calc(100% - 2vw);
height: calc(100% - 2vw);
margin: 1vw;
float: left;
z-index: 2;
position: relative;
box-sizing: border-box;
}
.grid_content:hover > .grid_hover {
opacity: 1;
transform: rotate(0);
}
.hover_here {
position: absolute;
top: 350px;
}
<div class="grid_content">
<div class="grid_hover bottom_left">
<div class="text_overlay"> <p>Lorem Ipsum</p></div>
<div class="background_overlay"></div>
</div>
</div>
<p class="hover_here">
Hover somewhere around here to see the "bug"
</p>
I also tried to just set grid_hover to pointer-events: none; that worked, but I can't use it because inside that div will be a button that has to be clickable.
My idea or what I want to achieve is something like this:
.grid_hover is set to display: none at the beginning
hovering on .grid_content will set it to display: block and after that happened the animation should run
Is there a way to make this work in just css without javascript?

child on SCSS transition item causes the parent's border size to change in firefox

working on SCSS transition I made two classes trigger and box and while hovering on trigger box should start moving and rotating.
.trigger {
display: inline-block;
width: 100px;
height: 100px;
max-width: 100px;
max-height: 100px;
background-color: #ddd;
outline: 20px solid #999;
position: relative;
margin: 25% 25%;
&:hover {
.box {
transform: translate(200px, 150px) rotate(20deg);
}
}
}
.box {
display: inline-block;
background-color: pink;
width: 100px;
height: 100px;
transition: transform 1000ms ease-in-out;
}
the effect works fine on chrome
[1]: https://i.stack.imgur.com/E2CnC.png
however Firefox scales the trigger borders
[2]: https://i.stack.imgur.com/6OVW4.png
the jade code
.trigger
.box
I added position: relative to .trigger and position: absolute to the box. I didn't have your html so I took a guess at what it might look like. this solution seems to work at least in codepen (I viewed in Chrome and Firefox and both are working). I had to modify your scss to css in this example in order to tinker with it in codepen and post here.
.trigger {
position: relative;
display: inline-block;
width: 100px;
height: 100px;
max-width: 100px;
max-height: 100px;
background-color: #ddd;
outline: 20px solid #999;
position: relative;
margin: 5% 25%;
}
.trigger:hover .box {
transform: translate(200px, 150px) rotate(20deg);
}
.box {
position: absolute;
display: inline-block;
background-color: pink;
width: 100px;
height: 100px;
transition: transform 1000ms ease-in-out;
}
<div class="trigger">
<div class="box"></div>
</div>

CSS transition background color without a hover

I have a div called time-box. Sometimes I will also include an additional class called countdown. If countdown is added then I would like to use a CSS transition effect so the background changes to be red over the course of 60 seconds. In other words, each second that passes the red background gets a little wider until eventually all of the green background has gone.
I have found similar posts here but they all seem to relate to hover
Here is a fiddle
https://jsfiddle.net/e2vbheew/
I don't know a "simple" way to get what you want going from left to right, but there's a way you can create it using before and after pseudoelements. The key here is I'm going to create a :before pseudoelement that has the new background that transitions across, and an :after pseudoelement that replicates the content and puts it on top of the before, so it's still visible. This required putting the content in an attribute on the div so I could reference it in the 'content' of the pseudoelement. If you had more complex content inside, you could probably do away with the :after and simply give the internal content position and z-index to make sure it's visible. Here's the resulting CSS
.time-box {
height: 27px;
text-align: center;
background-color: #25E57B;
font-size:2rem;
padding:0px;
font-size:1.2rem;
text-transform:uppercase;
padding:3px 5px 3px 5px;;
font-weight:600;
height:auto;
position: relative;
}
.time-box:before {
background-color: red;
position: absolute;
left:0;
top: 0;
height: 100%;
width: 0;
content: " ";
transition: width 60s ease;
}
.countdown:after {
content: attr(data-content);
width: 100%;
text-align: center;
height: 100%;
position: absolute;
left: 0;
top: center;
z-index: 1;
}
.countdown:before {
width:100%;
}
And updated fiddle: https://jsfiddle.net/tunzwqd7/2/
Using CSS animation property...
.time-box {
height: 27px;
text-align: center;
background-color: #25E57B;
font-size: 2rem;
padding: 0px;
font-size: 1.2rem;
text-transform: uppercase;
padding: 3px 5px 3px 5px;
font-weight: 600;
height: auto;
position: relative;
z-index: 1;
}
.time-box.countdown:before {
content: '';
width: 0;
height: 100%;
display: block;
position: absolute;
top: 0;
left: 0;
background: red;
animation: countdown 60s forwards;
z-index: -1;
}
#keyframes countdown {
0% {
width: 0;
}
100% {
width: 100%;
}
}
<div class="time-box">
12:00
</div>
<div class="time-box countdown">
<span>12:00</span>
</div>
You would need to add a maximum and a little more math to make the 100% divisible by 60, but this should get you on the right track. Currently this code updates every second and adds 1% to the progress bar width with each iteration.
var time = 0;
var bar = document.querySelector('.countdown .progress-bar');
window.setInterval(function(){
time++;
bar.style.width = time+"%";
}, 1000);
.time-box {
height: 27px;
text-align: center;
background-color: #25E57B;
font-size:2rem;
padding:0px;
font-size:1.2rem;
text-transform:uppercase;
padding:3px 5px 3px 5px;;
font-weight:600;
height:auto;
position: relative;
}
.progress-bar {
display: none;
}
.countdown .progress-bar {
display: block;
position: absolute;
left: 0;
top: 0;
bottom: 0;
background: red;
width: 0%;
z-index: 1;
transition: all 0.3s ease-out;
}
.countdown p {
z-index: 2;
position: relative;
}
<div class="time-box">
<p>12:00</p>
<div class="progress-bar"></div>
</div>
<div class="time-box countdown">
<p>12:00</p>
<div class="progress-bar"></div>
</div>

CSS bad rendering in translateZ( ) vs scale( )

I noticed that there is a big quality difference when transforming text in this 2 ways:
.text1 {
width: 200px;
height: 22px;
position: absolute;
top: 40%;
left: 0;
transform-origin: 50% 50%;
transform: scale(2); /* here */
color: red;
text-align: center;
font-size: 22px;
}
.text2 {
width: 200px;
height: 22px;
position: absolute;
top: 60%;
left: 0;
transform-origin: 50% 50%;
transform: translateZ(400px); /* here */
text-align: center;
font-size: 22px;
}
.perspective {
width: 200px;
height: 200px;
perspective: 800px;
transform-style: preserve-3d;
}
<div class="perspective">
<div class="text1">Text</div>
<div class="text2">Text</div>
</div>
Is there a way to force a better rendering when displacing text on the Z axis?
the reason the text blurs when you're transforming with translateZ(400px) is that this is a 3D transformation ; the browser treats the element as textures instead of vectors in order to provide hardware 3d acceleration.
So basically the resolution will be lower when increasing size.
On the other hand transforming with scale is a 2D transformation,
the browser treats the element as vector and blurring doesn't occur.
take a look at what happens to scale as soon as we kick in with 3d, without actually setting any translateZ value:
.text1 {
width: 200px;
height: 22px;
position: absolute;
top: 40%;
left: 0;
transform-origin: 50% 50%;
transform: scale(2);
/* here */
color: red;
text-align: center;
font-size: 22px;
}
.text1a {
width: 200px;
height: 22px;
position: absolute;
top: 40%;
left: 50%;
transform-origin: 50% 50%;
transform: translateZ(0) scale(2);
/* here */
color: blue;
text-align: center;
font-size: 22px;
}
.text2 {
width: 200px;
height: 22px;
position: absolute;
top: 60%;
left: 0;
transform-origin: 50% 50%;
transform: translateZ(400px);
/* here */
text-align: center;
font-size: 22px;
}
.perspective {
width: 200px;
height: 200px;
perspective: 800px;
transform-style: preserve-3d;
}
<div class="perspective">
<div class="text1">Text</div>
<div class="text1a">Text</div>
<div class="text2">Text</div>
</div>
the only workaround I can think of at the moment is checking the stylesheet through JS and overriding translateZ with transform: scale
var styles = document.styleSheets;
//patterns
var perspPat = /perspective\s*?:\s*?(\d+)/;
var transZPat = /translateZ\(\s*?(\d+)/;
var perspective;
var translateZ = [];
[].slice.call(styles).forEach(function (x) {
[].slice.call(x.rules).forEach(function (rule) {
if (perspPat.test(rule.cssText)) {
perspective = perspPat.exec(rule.cssText)[1]
};
if (transZPat.test(rule.cssText)) {
translateZ.push([
rule.selectorText,
transZPat.exec(rule.cssText)[1]]);
}
});
})
translateZ.forEach(function (x) {
document.querySelector(x[0]).style.transform = 'scale(' + perspective / x[1] + ')';
})
fiddle
As you can see, even if it does work, a lot of optimization is needed..
(I wouldn't consider it production ready in it's current state ).
You can add font-smooth (for firefox), and antialiasing for webkit
.text2 {
-webkit-font-smoothing: antialiased;
font-smooth: always;
}
https://developer.mozilla.org/en-US/docs/Web/CSS/font-smooth
http://davidwalsh.name/font-smoothing

Recreate this radial image using css

I would like to know if it's possible to recreate the following image using css.
I am currently using it but in svg format.
Imagine this:
jsfiddle link
#circle {
background: #ccc;
border-radius: 50%;
/* Change these two equally to change circle size. Can be pixels, too. */
width: 25%;
padding-top: 25%;
height: 0;
position: relative;
}
.hand {
background: black;
width: 1px;
height: 100%;
position: absolute;
left: 50%;
top: 0;
}
.hand:nth-child(2) {
transform: rotate(90deg);
}
.hand:nth-child(3) {
transform: rotate(45deg);
}
.hand:nth-child(4) {
transform: rotate(135deg);
}
#circle:after {
content: '';
display: block;
width: 80%;
height: 80%;
border-radius: 50%;
background: white;
position: absolute;
top: 10%;
left: 10%;
}
<div id="circle">
<div class="hand"></div>
<div class="hand"></div>
<div class="hand"></div>
<div class="hand"></div>
</div>
Or if you need the middle to be transparent (this is a little hacky, and you may have to modify it to fit your exact needs): https://jsfiddle.net/wdoe8r3m/1/

Resources