I have an animation of a box, where it's width increases on hover:
JSFiddle: https://jsfiddle.net/hbpncv34/
HTML:
<div></div>
CSS:
div {
background-color: red;
height: 10vh;
width: 10vw;
}
div:hover {
animation: change_width 0.7s forwards;
}
#keyframes change_width {
from {
width: 10vw;
}
to {
width: 15vw;
}
}
Issue:
I also want the box to smoothly move back when I hover off of it.
There are two ways I could do this:
Method 1:
JSFiddle: https://jsfiddle.net/hbpncv34/1/
HTML:
<div></div>
CSS:
div {
background-color: red;
height: 10vh;
width: 10vw;
animation: change_width_back 0.7s forwards;
}
div:hover {
animation: change_width 0.7s forwards;
}
#keyframes change_width {
from {
width: 10vw;
}
to {
width: 15vw;
}
}
#keyframes change_width_back {
from {
width: 15vw;
}
to {
width: 10vw:
}
}
Issue:
The change_width_back animation also runs on page load.
Also, mousing on / off rapidly is not smooth like it is with transition, so:
Method 2:
JSFiddle: https://jsfiddle.net/hbpncv34/2/
HTML:
<div></div>
CSS:
div {
background-color: red;
height: 10vh;
width: 10vw;
transition: width 0.7s;
}
div:hover {
width: 15vw;
}
Issue:
The animation also runs on zooming in and out.
I can fix this by using px or % instead of vw for my widths, but it's crucial in my actual issue that I keep it as viewport units.
So, is there any way to play an animation on hover on and off, and only hover on and off?
Since I don't know Javascript, please keep answers HTML / CSS only. If JS is absolutely needed, make it simple enough to just copy + paste with minimal editing.
Thanks for any help.
You need "ready" state flag in order to accomplish this:
$(function(){
$("div").attr("ready",true);
});
div {
background-color: red;
height: 10vh;
width: 10vw;
}
div[ready] {
transition: width 0.7s;
}
div[ready]:hover {
width: 15vw;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>.</div>
There may be a better way, but with very little js combined to your Method 1, you can do this:
<div onmouseover="this.classList.add('animate')"></div>
And in your css:
div {
background-color: red;
height: 10vh;
width: 10vw;
}
div.animate
{
animation: change_width_back 0.7s forwards;
}
https://jsfiddle.net/vhyfewnt/
EDIT
First solution is meant to work with animate, not with transition. There's a way to make transition work, but it needs a little more javascript.
<body onresize="document.getElementsByTagName('div')[0].classList.add('zoom'); setTimeout(function(e){document.getElementsByTagName('div')[0].classList.remove('zoom')}, 100)">
<div></div>
</body>
div {
background-color: red;
height: 10vh;
width: 10vw;
}
div:not(.zoom)
{
transition: width 0.7s;
}
div:hover {
width: 15vw;
}
https://jsfiddle.net/cdj7L5r3/
2nd EDIT:
To apply to more elements, you can add the class to body (or any ancestor) and change the rule. Like this:
<body onresize="document.body.classList.add('zoom'); setTimeout(function(e){document.body.classList.remove('zoom')}, 100)">
<div></div>
<div></div>
<div></div>
<div></div>
<section></section>
</body>
div, section{
background-color: red;
height: 10vh;
width: 10vw;
}
body:not(.zoom) div, body:not(.zoom) section
{
transition: width 0.7s;
}
div:hover, section:hover {
width: 15vw;
}
https://jsfiddle.net/cdj7L5r3/1/
RE: animate on zoom in/out, I don't think you're going to find a way around the animation issue with the CSS transition solution, because zooming changes the viewport size, and your units are in terms of the viewport. So when the viewport changes, those units have to be recalculated/repainted and that change is animated, as specified in the transition property.
If you could provide some background on the use case for this effect, we might be able to help think of another way to solve this problem.
If you are willing to add a litter js code maybe this help you, the key is that classes have the animation behavior, when the animation ends you remove the classes, so there is no transition when the page is zoom or loaded
var element = $("div");
element.bind("mouseover", function(){
$(this).removeClass('sh');
$(this).addClass('lg');
});
element.bind("mouseout", function(){
$(this).addClass('sh');
$(this).removeClass('lg');
});
/*this is for remove the class when animation ends*/
element.bind("transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd", function(){
$(this).removeClass('sh');
});
div {
background-color: red;
height: 10vh;
width: 10vw;
}
.lg{
width: 15vw;
-webkit-transition: .3s;
}
.sh{
width: 10vw;
-webkit-transition: .3s;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div></div>
Here a jsfiddle example to play with
Related
I have a container that contains a div inside it. By clicking on that div square, it begins moving and ends up being outside the container.
My problem is that this inner block is being trimmed out really harsh while going beyond the borderline. How could this transition be done more smoothly using CSS means? I want to get an effect when this square disappearing becomes gentle for the eyes.
Maybe I'm supposed to use some kind of an image mask for the main container or a fade effect for the square. I'm not exactly sure how to achieve that behaviour.
Thank you in advance!
Codepan sandbox
.borderline {
position: relative;
text-align: center;
vertical-align: middle;
line-height: 150px;
width: 400px;
height: 150px;
overflow: hidden;
}
.square {
position: absolute;
width: 150px;
height: 150px;
background-color: #0087ff;
}
.square:focus {
transform: translateX(500px);
transition: all 2s;
}
<div class='borderline'>
<div class='square' tabindex="1">Click me</div>
</div>
maybe you could add an animation to your css with opacity like:
.square:focus {
transform: translateX(500px);
transition: all 2s;
animation-name: example;
animation-duration: 1s;
}
#keyframes example {
0% {opacity:1}
50% {opacity:1}
100% {opacity:0}
}
https://codepen.io/anon/pen/rzppON
I'm trying to increase the width of a div on hover while the height stays the same. This is tough because I get the height from padding-top: 100% which allows it to be a resizable square. So naturally as I increase the width the height organically increases too. (It is important the div height and width are equal in its normal state so it's a perfect square)
I'm now lost and unsure how to achieve this, any input is appreciated.
https://jsfiddle.net/9tc2mbwd/2/
.work-container { padding-top: 100%; }
If you don't want to set fix width and height into .work-wrapper, then..
Make the .work-container the hovered element, and do like this:
.work-wrapper {
width: 30%;
}
.work-container {
padding-top: 100%;
width: 100%;
transition: all ease 0.5s;
}
.work-container:hover {
width: 200%;
}
.work-1 {
background-color: #FEF102;
}
<div class="work-wrapper">
<div class="work-container work-1">
</div>
</div>
You can use viewport units and get rid of work-wrapper, like this:
.work-container {
width: 30vw;
height: 30vw;
transition: all ease 0.5s;
}
.work-container:hover {
width: 50vw;
}
.work-1 {
background-color: #FEF102;
}
<div class="work-container work-1">
</div>
Well, you can start off by getting rid of the percentages and adding this to " .work-wrapper":
width:150px;
height:150px;
overflow: hidden;
and keep everything the same!
Hope this helps!
I want to change an HTML element position from static to fixed at top 50% and left 50% of the browser window but the code just leads to background-color change!
div {
width: 100px;
height: 100px;
background-color: red;
position: static;
top: auto;
left: auto;
animation-name: example;
animation-duration: 4s;
}
#keyframes example {
from {
background-color: red;
position: static;
top: auto;
left: auto;
}
to {
background-color: yellow;
position: fixed;
top: 50%;
left: 50%;
}
}
Short answer: You can't animate position.
Instead of applying position: fixed through keyframes try to add a class fixed or something via javascript.
An example: https://jsfiddle.net/6Ldqhoce/
Alternative you could move the element with transform: translate but it won't be fixed.
You cannot change position using CSS-animation because position is NOT an animatable property.
List of animatable properties.
However, this fiddle might help you.
I found the answer via 'Vangel Tzo' help :
div {
width: 100px;
height: 100px;
background-color: red;
animation-name: example;
animation-duration: 4s;
}
#keyframes example {
from {
background-color: red;
}
to {
background-color: yellow;
transform: translate(50vw, 50vh);
}
}
You can't change css position value with css animation.
You can do this with jQuery
example is with hover, you can do according to your choice.
Jquery
With the use of "Css"
$(".div_name").hover(function(){
$(this).css("position", "static");
}, function(){
$(this).css("position", "fixed");
});
With the use of "Animate"
$(".div_name").hover(function(){
$(this).animate({"position":"static"}, 1000);
}, function(){
$(this).animate({"position":"fixed"}, 1000);
});
Main question
I have two divs, one nested inside the other and i wish to shift inner div outside (upwards) of outer div and slide-in it on a hover.
Markup is looking like so:
<div class="body">
<div class="inner">Green is variable-height text which slides in on viewport hover</div>
Blue is a viewport (<body>, visible part of a page), which content should be compressed upon green slide-in
</div>
And (a little pseudo) css:
.body {
background: #aaf;
height: 300px;
width: 300px;
overflow: hidden;
}
.inner, .body:hover .inner {
-webkit-transition:all linear 0.2s;
transition:all linear 0.2s;
}
.inner {
background: #afa;
width: 300px;
margin-top:-some-magic-to-get-this-div-height;
}
.body:hover .inner {
margin-top: 0;
}
And a final result animation i'd like to get, without using fixed height of green div:
Also, this example (with a guessed and hard-coded height value of 2.5em) on jsfiddle to experiment with:
http://jsfiddle.net/n7vyLoh4/20/
Possible partial work-around (not satisfactory)
It is possible to partially implement what i want, using transitioning max-height instead of transitioning margin-top, the transition of max-height: 0; -> max-height: 100%; with overflow: hidden; set at all times
works, but has two draw-backs:
it doesn't slide in, it's more like drops the curtain
it doesn't stop transition at the end of green div, it transits till the end of outer blue div, which especially noticeable at reverse transition, when it first travels all the way from bottom of blue div to bottom of green div before any effect is visible. Also, this means that despite transition time set to 0.2s, it will spend only fraction of this time on transiting trough green div, because this 100% are 100% of parent div, not inner one (and my question could be answered if there is a way to calculate the 100% of inner div height).
Here is an illustration:
And fiddle for that:
http://jsfiddle.net/bsd7vnwu/1/
This is the pure css solution, which means it does not require any scripts, just a browser that support transitions:
.body {
background: #aaf;
height: 300px;
width: 300px;
overflow: hidden;
}
.inner {
-webkit-transition:all cubic-bezier(0,.81,.4,1) 0.5s;
transition:all cubic-bezier(0,.81,.4,1) 0.5s;
}
.inner {
background: #afa;
width: 300px;
position: absolute;
margin-top: -100%;
float: left;
}
.body:hover .inner {
position: relative;
margin-top: 0;
}
And Fiddle is here
I think this is the effect you want. CSS doesn't allow you to get the height of an element to use in calc() for positioning and margins, so a little JS is needed.
CSS:
.body {
background: #aaf;
height: 300px;
width: 300px;
overflow: hidden;
}
.inner, .body:hover .inner {
-webkit-transition:all linear 0.2s;
transition:all linear 0.2s;
}
.inner {
background: #afa;
width: 300px;
overflow: hidden;
}
.body:hover .inner {
margin-top : 0 !important;
}
JS:
Array.prototype.forEach.call(document.getElementsByClassName('inner'), function (item) {
item.style.marginTop = (item.clientHeight * -1) + 'px';
});
Demo:
http://jsfiddle.net/09tyLr9b/
I added transition to your fiddle to get what i think you are looking for
.inner {
background: #afa;
width: 300px;
overflow: hidden;
max-height: 0;
transition:0.5s ease-out;
}
.body:hover .inner {
max-height: 100%;
transition:0.5s ease-in;
}
JSFIDDLE
and by lowering the time for transition:ease-out you will get a more responsive slide up when you mouse out of the div
like this JSFIDDLE
Another CSS solution after 2.5 years, using flex layout:
.body {
background: #aaf;
height: 300px;
width: 300px;
overflow: hidden;
}
.inner {
display: flex;
align-items: flex-end;
-webkit-transition: all cubic-bezier(0, 1, 0, 1) 0.5s;
transition: all cubic-bezier(0, 1, 0, 1) 0.5s;
background: #afa;
max-height: 0;
overflow: hidden;
}
.body:hover .inner {
-webkit-transition: all ease-in-out 0.5s;
transition: all ease-in-out 0.5s;
max-height: 100%;
}
<div class="body">
<div class="inner">Green is variable-height text which slides in on viewport hover</div>
Blue is a viewport (<body>, visible part of a page), which content should be compressed
Also on JSFiddle.
I have a div with some images in it. When I move the mouse over one of the images, I want it to grow, when I move the mouse out I want it to shrink again. I know that there isn't a mouseout ore something like that in CSS, so I put the reverse animation into the normal style of the images. Now my problem is, that when I load the site all images do the shrinking animation.
Is there a way to do this only with CSS or do I have to use Javascript?
My HTML:
<div id="picmen">
<img src="/images/b1.png" />
<img src="/images/b2.png" />
<img src="/images/b3.png" />
<img src="/images/b4.png" />
<img src="/images/b5.png" />
<img src="/images/b6.png" />
<img src="/images/b7.png" />
</div>
My CSS:
#picmen img {
float: right;
margin: 3px 1px 3px 1px;
height: 50px;
width: 50px;
animation: shrink 0.5s;
}
#keyframes shrink {
from{ width: 60px; height: 60px; }
to{ width: 50px; height: 50px; }
}
#picmen img:hover {
animation: grow 0.5s;
width: 60px;
height: 60px;
}
#keyframes grow {
from{ width: 50px; height: 50px; }
to{ width: 60px; height: 60px; }
}
Try using:
transition-duration: 0.5s;
instead of creating #keyframe animations.
Your code would look like:
#picmen img {
float: right;
margin: 3px 1px 3px 1px;
height: 50px;
width: 50px;
transition-duration: 0.5s;
}
#picmen img:hover {
transition-duration: 0.5s;
width: 60px;
height: 60px;
}
If you want to add easing, you can use:
transition-timing-function: ease-in-out;
More information about transition css3 can be found on the w3schools website.
See it in action.
Why it works:
When you define and use an #keyframe animation, your code will run the animation every time it is seen.
A browser will read your code like this:
#picmen img{ //define all images inside 'picmen' div
... //all of the basics (float, margin)
height:50px; //set height to 50px (iff no further instructions about height follow)
width:50px; //set width to 50px (iff no further instructions about width follow)
animation: shrink 0.5s; //run an animation called shrink for 0.5 seconds
//every time this state is entered
--run animation called 'shrink'--
#keyframes shrink { //defines 'shrink'
from{ width: 60px; height: 60px; } //redefines starting width and height
to{ width: 50px; height: 50px; } //defines ending width and height
}
--end animation--
} //end image definition
transition, will only make those changes on (as the name suggests) transitions.
The first time your images are loaded, they don't go through any state changes, thus no transition.