CSS3 Transition reverse not taking effect - html

I have a create two divs that overlap using z-index and the top one will shrink width ways but I can't get it to shrink from right to left even though I've added animation-direction:reverse;
EXAMPLE
How do I change the direction of the shrink?

animation-direction is irrelevant here. That property relates to css animations. You are using transitions. Two different things entirely.
Give .grow a right position value and wrap your current divs in a container with relative positioning:
WORKING DEMO
<div class="pos_rel">
<div class="holder"></div>
<div class="grow"></div>
</div>
.grow {
right:0;
}
Also, you probably should have the :hover on the parent element to prevent your mouse moving out of .grow as it transitions:
DEMO
.pos_rel:hover .grow {
width: 50px;
}

http://jsfiddle.net/venkat7668/a4DUv/2/
I have modified your code little bit to get your expected animation.
<div class="main">
<div class="grow"></div>
<div class="holder"></div>
<div>
.main {
position: relative;
width: 300px;
height: 300px;
}
.holder {
position:absolute;
width: 300px;
height: 300px;
background:#cccccc;
z-index:1;
}
.grow {
width: 300px;
height: 300px;
background: green;
-webkit-transition: width 5s;
transition: width 5s;
float:right;
position:relative;
z-index:2;
}
.grow:hover {
width: 50px;
}

Related

CSS relative position left works, but top doesn't

I'm trying to position arbitrary elements arbitrarily within an arbitrary container. I want to specify a position as a percentage where
0% means "left edge aligned with the left of the container,"
100% means "right edge aligned with the right of the container,"
Any value in between is linearly interpolated, so 50% would be "middle aligned with middle"
To achieve this, the container has position: relative;. The element has position: absolute; with left and top equal to the percentages - these percentages will be relative to the container's size. Then, the element's contents are shifted back with position: relative; and left and top equal to negative the percentage, as this will be relative to the element's size.
Demo:
#container {
position: relative;
width: 200px;
height: 150px;
background-color: #cfc;
}
#item {
position: absolute;
left: 80%;
top: 80%;
background-color: #fcc;
}
#item>img {
position: relative;
display: block;
left: -80%;
top: -80%;
}
<div id="container">
<div id="item">
<img src="//placehold.it/100x100" />
</div>
</div>
In the demo, the green box is the container, the red box is the element's "real" position, while the placeholder image is the actual content. The coordinate used here is (80%,80%) making it appear in the lower-right corner.
As you can see, the left component works absolutely fine. It is exactly where it should be. The top, however, is not doing the "shift back" thing. It's not moving at all.
Of course there are many similar questions, but all of the ones I've seen stem from the "relative to" element being the relative one, not the absolute, which meant the container had zero height - fair enough. Indeed, explicitly setting the height on my red box in the demo fixes the issue. However, did I mention how arbitrary these components are? I cannot explicitly set the height of the element, I need it to vary based on the content, which may change dynamically.
Any ideas how I might go about this?
As already noticed, the main issue here is that top with percentage values will only work if the parent has a height specified which is not the case here. So in order to fix this we need to find a way to give the item a specified height equal to its content height and different from auto.
And idea would be to consider another div within the #item and make this one a flex container. This will make the new div to be stretched and have a height specified (yes flex is magic) thus the top value on the img will work fine.
#container {
position: relative;
width: 200px;
height: 150px;
background-color: #cfc;
overflow:hidden;
}
#item {
position: absolute;
display:flex;
animation: change-1 1s linear infinite alternate;
}
#item img {
position: relative;
display: block;
animation: change-2 1s linear infinite alternate;
}
#keyframes change-1 {
from {
top:0%;
left:0%;
}
to {
top:100%;
left:100%;
}
}
#keyframes change-2 {
from {
top:0%;
left:0%;
}
to {
top:-100%;
left:-100%;
}
}
<div id="container">
<div id="item">
<div>
<img src="//placehold.it/100x100" >
</div>
</div>
</div>
Here you can use transform property to the placeholder and give value to x and y coordinates the same i.e -80%. Hope this helps you out.
#container {
position: relative;
width: 200px;
height: 150px;
background-color: #cfc;
}
#item {
position: absolute;
left: 80%;
top: 80%;
background-color: #fcc;
}
#item>img {
position: relative;
display: block;
transform: translate(-80%,-80%);
}
<div id="container">
<div id="item">
<img src="//placehold.it/100x100" />
</div>
</div>
You should specify a height of the parent element :)
UPDATE
You can also try to set for your img a negative margin-top: -80% instead of top: 80%, and set the margin-bottom: 80% to preserve parent element height:
#container {
position: relative;
width: 200px;
height: 150px;
background-color: #cfc;
}
#item {
position: absolute;
left: 80%;
top: 80%;
background-color: #fcc;
}
#item>img {
position: relative;
display: block;
left: -80%;
margin-top: -80%;
margin-bottom: 80%;
}
<div id="container">
<div id="item">
<img src="//placehold.it/100x100" />
</div>
</div>
The only trick is that margin in percents is setting relative to the parent element width, so, obviously, if you will have not square image, it will work incorrectly.
I have "resolved" the issue by having JavaScript set margin-left and margin-top based on the pixel size of the content, and added event handlers for the window resizing and the content changing. While this works, I don't like it. A CSS-only solution would trump this by far.

CSS Transition and Auto position

I have a div .box with which has absolute position set at the bottom of the parent div. It does not have the top position set because the height differs for different .box divs. On hover over the parent div, I want to change its top position to 0 with the transition effect.
In the following code transition does not work if I do not define the top position by default. I have tried using top: auto and it still does not work. How can I use transition without defining the top position.
Here's my code:
HTML:
<div class="wrap">
<div class="box">
Box
</div>
</div>
CSS:
.wrap{
position: relative;
height: 200px;
width: 200px;
background: green;
}
.box{
background: yellow;
position: absolute;
bottom: 0;
left: 0;
transition: all 0.9s ease 0s;
top: 50%; /*== does not work without it ==*/
}
.wrap:hover .box{
top: 0;
bottom: 0;
}
Fiddle: http://jsfiddle.net/5hs09apn/
A slight different approach than using top: http://jsfiddle.net/5hs09apn/2/
set the height for the box, and on hover set it to 100%; let the bottom be zero, so you don't even need to use top
.box{
background: yellow;
position: absolute;
bottom: 0;
left: 0;
height:20px;
transition: all 1s ease 0s;
}
.wrap:hover .box{
height:100%;
bottom: 0;
}
.wrap {
position: relative;
height: 200px;
width: 200px;
background: green;
}
.box {
background: yellow;
position: absolute;
bottom: 0;
left: 0;
height: 20px;
transition: all 1s ease 0s;
}
.wrap:hover .box {
height: 100%;
bottom: 0;
}
<div class="wrap">
<div class="box">
Box
</div>
</div>
Add Top property in JQuery getting the current value of the Top of the .box using position().
This will be dynamic allocation of Top and will not effect your condition of varying .box height.
While doing this, you will have to add the hover effect in the JQuery part too, since the Top will be defined here and CSS wont know what to do with the hover.
Check the Fiddle here
This is the JQuery function added:
$(document).ready(function(){
var x = $('.box').position();
var myTop = x.top;
$('.box').css("top",myTop+"px");
$('.box').css("transition","all 0.9s ease 0s");
$('.wrap').bind('mouseover',function(){
$('.box').css("top","0px");
$('.box').css("bottom","0px");
});
$('.wrap').bind('mouseout',function(){
$('.box').css("top",myTop+"px");
$('.box').css("bottom","0px");
});
});
Hope this gives you what you need.
You can use:
.wrap:hover .box{
margin-bottom: 100%;
}
And try with different percentages until you get one you like. It's crude but I think it can work.

How to shift element upwards to it's variable height using css

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.

How do I make a div "not take space"?

I'm trying to make a "dynamic" background with divs rotating, I have a big image which, when rotated, makes the scroll bars bigger, is there anyway of displaying the image within the div, in the background, rotating but make it so it doesn't take up space/doesn't change scroll bars?
For the rotation I'm using css animations.
CSS
body {
background-color:rgb(80,0,0);
}
.rotating {
width:600px;
height:600px;
position:absolute;
top:-50px;
left:-100px;
background-color:rgb(0,0,255);
-webkit-animation:rotate 140s linear infinite;
}
#-webkit-keyframes rotate /* Safari and Chrome */
{
from {-webkit-transform:rotate(0deg);}
to {-webkit-transform:rotate(360deg);}
}
.content {
background-color:rgba(0,0,0,0.5);
margin:0 auto;
position:relative;
}
HTML
<div class='rotating'></div>
<div class='content'>test</div>
http://jsfiddle.net/kZW8j/
This is possible with little tweaking in your code. You can place the rotating div inside a bg div which is absolutely positioned and given the size of your document and by hiding its overflow.
Here is the code and your fiddle modified http://jsfiddle.net/kZW8j/2/
HTML
<div class="bg">
<div class='rotating'>
</div>
<div class='content'>test</div>
CSS
body {
background-color:rgb(80,0,0);
}
.bg{
position:absolute;
top:0;
left:0;
background-color:rgb(80,0,0);
overflow:hidden;
}
.rotating {
width:600px;
height:600px;
position:absolute;
top:-50px;
left:-100px;
background-color:rgb(0,0,255);
-webkit-animation:rotate 140s linear infinite;
}
#-webkit-keyframes rotate /* Safari and Chrome */
{
from {-webkit-transform:rotate(0deg);}
to {-webkit-transform:rotate(360deg);}
}
.content {
background-color:rgba(0,0,0,0.5);
margin:0 auto;
position:relative;
}
Jquery
function widthContainer()
{
var dw=$(document).width(), dh=$(document).height();
$(".bg").css({"width":dw, "height":dh});
}
$(document).ready(function(){
widthContainer();
$(window).resize(function(){
widthContainer();
});
});
I think this solves your issues. Let me know if you need any help.
You might also want to try working with z-index.
I got it working. The trick is to use z-index on .content and to put the rotating div inside a 0-size relative positioned div, also z-indexed. Overflow will still trigger.
http://jsfiddle.net/acbabis/gwN4H/
HTML
<body>
<div class="background-wrapper">
<div class="rotate"></div>
</div>
<div class="content">
<p>...</p>
<p>...</p>
</div>
</body>
CSS
.content {
width: 40%;
height: 100%;
position: relative;
padding: 10% 30%;
z-index: 10;
}
.background-wrapper {
z-index: 0;
position: relative;
height: 0;
width: 0
}
.rotate {
width: 100px;
height: 100px;
background-color: red;
position: absolute;
left: 200px;
top: 200px;
// Animation code removed
}

Issue with CSS Enlarge on Hover Effect

I found a nice tutorial for making my images enlarge (like a zoom effect) on hover. The main difference between my needs and a tutorial is that I want my all images contained in a single box like container. So when I implemented the tutorial I realize that part of the enlarged image gets cut off when you hover. The effect is constrained to the container. I would like a way for the zoom to go wherever it needs to go on the page. (So you can see the whole zoomed image)
Here is my implementation of the tutorial: http://mulnix.contestari.com/wp/example225/1.php
JSFiddle: http://jsfiddle.net/dsRAH/
Original Code
Remove the overflow: hidden and all other overflows,
than for your images containers DIV remove float:left; and add display:inline-block;
* {
margin: 0;
box-sizing: border-box;
}
.wrapper {
position: relative;
background: #000;
color: #fff;
z-index: 0;
}
.photos {
position: relative;
display: flex;
flex-flow: row wrap;
}
.photo {
box-shadow: 0 0 0 2px #444;
margin: 5px;
position: relative;
max-height: 200px;
transform: translateZ(0);
transition: transform 0.5s;
}
.photo:hover {
z-index: 1;
transform: translateZ(0) scale(1.6);
}
.photo img {
display: block;
width: 100%;
height: 100%;
object-fit: cover;
}
.photo-legend {
position: absolute;
bottom: 0;
width: 100%;
padding: 1em;
background: rgba(0,0,0,0.3);
}
<div class="wrapper">
<div class="photos">
<div class="photo">
<img src="https://placehold.it/200x150/0bf" />
<div class="photo-legend">TEST DESCRIPTION</div>
</div>
<div class="photo">
<img src="https://placehold.it/200x200/f0b" />
</div>
<div class="photo">
<img src="https://placehold.it/200x150/bf0" />
</div>
</div>
</div>
It's not perfect but it's a start. I changed the overflow:hidden; in the wrapper to visible. I also put your code into jsfiddle so people can tinker with it.
http://jsfiddle.net/m8FXH/
You can try to use z-index. An element with greater z-index is always in front of an element with a lower z-index. If you main container is not overflow:hidden than you can try this out.
here is an example where you can see how it works. Hope that is helpful.
https://developer.mozilla.org/en-US/docs/Web/CSS/z-index
I would suggest giving your divs one of the following classes:
colleft for the ones that are at left column
colright for the ones that are at right column
rowtop for the ones at the top row
rowbottom for the ones at the bottom row
And then assign them the following properties
.colleft {
transform-origin-x: 0%;
}
....
transform-origin-x: 100%;
transform-origin-y: 0%;
transform-origin-y: 100%;
(respectively)
That will make the zoom go in the desired direction.
evan stoddard modified fiddle