CSS transition position absolute from one edge to the other - css

How can I transition a HTML div with an absolute position (right: 0; bottom: 0px) to another edge (left: 0px; top: 0px;).
I have tried the following code, however, transition with absolute elements only seems to work when using either left/top, or right/bottom.
What is the preferred way to do that in HTML5?
var ele = document.getElementById("my-box");
ele.addEventListener("click", function() {
ele.classList.toggle("clicked");
});
.box {
position: absolute;
top: 0px;
right: 0px;
width: 100px;
height: 100px;
background-color: red;
transition: all 0.7s ease;
}
.box.clicked {
top: auto;
bottom: 0px;
left: 0px;
right: auto;
}
<div class="box" id='my-box'>
</div>

You should keep using the top and right on the clicked below. Just use a calc to position them like below
var ele = document.getElementById("my-box");
ele.addEventListener("click", function() {
ele.classList.toggle("clicked");
});
.box {
position: absolute;
top: 0px;
right: 0px;
width: 100px;
height: 100px;
background-color: red;
transition: all 0.7s ease;
}
.box.clicked {
top: calc(100% - 100px);
right: calc(100% - 100px);
}
<div class="box" id='my-box'>
</div>

change your .clicked class as
.box.clicked {
transform:translate(calc(-100vw + 100px) ,calc(100vh - 100px))
}

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?

Smooth CSS Transform Scale on rectangle, keeping an even border

I have an absolutely positioned div that I want to have slowly increase in size (5s transition) on hover, to become a "border" for a relative-positioned div on top of it:
<div class="rectangle">
<div class="background"></div>
<div class="content">blah</div>
</div>
Styles (vendor prefixes removed for readability):
.rectangle {
position: relative;
}
.background {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.content {
height: 800px;
width: 200px;
}
Transitioning the overall .background size results in choppy animation but an even border:
.rectangle:hover .background {
width: calc(100% + 40px);
height: calc(100% + 40px);
top: -20px;
left: -20px;
right: -20px;
bottom: -20px;
transition: 5s linear all;
}
Transitioning a border is choppy animation, but (obviously) an even border
.rectangle:hover .content {
border: 20px solid red;
transition: 5s linear all;
}
Transitioning a transform-scale is smooth, but results in a larger top and bottom "border" because it is a rectangle:
.rectangle:hover .background {
transition: 5s transform;
transform: scale(1.1);
}
Any way to either get transform-scale to keep even dimensions, or any other way to create this effect?
You can try using box shadow as a border to achieve smooth transitions.
.rectangle {
position: relative;
width: 300px;
height: 300px;
top: 100px;
left: 30%;
}
.background {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.background::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
box-shadow: 0 0 0 0px #000;
transition: 5s linear box-shadow;
}
.content {
height: 300px;
width: 200px;
}
.rectangle:hover .background::before {
box-shadow: 0 0 0 20px #000;
transition: 5s linear box-shadow;
}
<div class="rectangle">
<div class="background"></div>
<div class="content">blah</div>
</div>

CSS transitions in different directions

I am trying to fill a wrapper (600x600px) when hovering over smaller boxes inside it. For a box in the top left corner, it is easily done using regular transition-timing-function, but when trying to enlarge in other directions, I have gotten stuck.
So I have the following:
#allbox {
background: #bbb;
width: 600px;
height: 600px;
margin: auto;
position: absolute;
top: 0; left: 0; bottom: 0; right: 0
}
with boxes:
div.box1 {
position: absolute;
top: 0%;
left: 0%;
}
div.box2 {
position: absolute;
top: 0%;
left: 37.5%;
}
For transition I use:
#div1 {-webkit-transition-timing-function: linear;}
#div1 {transition-timing-function: linear;}
div.box1:hover {
width: 600px;
height: 600px;
}
But I am unable to figure a good way to do it for the following box.
Here is a sample using z-index keeping the hovered on top.
#allbox {
background: #bbb;
width: 600px;
height: 300px;
margin: auto;
position: absolute;
top: 0; left: 0; bottom: 0; right: 0
}
#allbox div {
position: absolute;
z-index: 1;
top: 0%;
width: 33.33%;
height: 50%;
transition: left 0.5s linear, width 0.5s linear, height 0.5s linear, z-index 1s linear;
}
div.box1 {
left: 0;
background: blue;
}
div.box2 {
left: 33.33%;
background: red;
}
div.box3 {
left: 66.66%;
background: green;
}
#allbox div:hover {
z-index: 2;
left: 0;
width: 100%;
height: 100%;
transition: left 0.5s linear, width 0.5s linear, height 0.5s linear, z-index 0s linear;
}
<div id="allbox">
<div class="box1">
</div>
<div class="box2">
</div>
<div class="box3">
</div>
</div>
I think we just add "left: 0;" to the hover state.
div.box2:hover {
left: 0;
width: 600px;
height: 600px;
}
Hope this help you.

"position: fixed" not woking when parent has the "transform" CSS property

In my project I have screen which should ease-in from right side of the screen so for that thing I have used transform: translateX(100%) and then changing that to transform: translateX(0%). it works fine I able to achieve the ease-in effect but in that screen I have action button which has css property of Position: Fixed;Bottom: 0px; but this is not working I mean its not sticking in the bottom of the screen.
Here is my JSfiddle : https://jsfiddle.net/sureshpattu/a1seze4x/
Html:
<header>
Heading
</header>
<div class="page__popup page__popup--ease-in-right page__action-btn--visible" style="height: 382px;">
<div class="container">
</div>
<button class="js-action-btn">
SELECT ROOMS
</button>
</div>
Css:
header {
background: #fff;
height: 60px;
position: fixed;
top: 0;
left: 0;
right: 0;
width: 100%;
z-index: 10;
box-shadow: 2px 2px 10px #000;
}
.container {
height: 382px;
}
.page__popup {
position: absolute;
top: 100vh;
z-index: 8;
display: block;
overflow-y: scroll;
max-height: 100vh;
width: 100%;
height: 0;
background: #ffffff;
.js-action-btn {
position: relative;
bottom: -50px;
transition: all 0.25s ease-in-out;
}
//Themes
&--ease-in-bottom {
&.visible {
transition: height 0.25s ease-in-out;
top: 54px;
right: 0;
bottom: 0;
left: 0;
}
}
&--ease-in-right {
transform: translateX(100%);
height: 100vh;
top: 60px;
&.visible {
transition: transform 0.25s ease-in-out;
transform: translateX(0);
}
}
}
.page__action-btn--visible {
.js-action-btn {
background: red;
width: 100%;
height: 30px;
position: fixed;
bottom: 0;
z-index: 10;
box-shadow: 0 7px 4px 10px rgba(0, 0, 0, .12);
}
}
This is not a bug.
Take a look at the spec: The Transform Rendering Model
Specifying a value other than ‘none’ for the ‘transform’ property
establishes a new local coordinate system at the element that it is
applied to.
So according to the spec: the element with fixed positioning will become relative to the element with the transform - not the viewport
As a workaround you could:
1) Use transitions (eg. on the left property) instead of transform (translateX)
2) Remove the position:fixed button from the container which uses transforms

Animate growing div then animate child element

I'm currently trying to animate a growing <div> but I don't want the content to look like it is growing along with it. The content should remain invisible while the <div> is animating and once it's fully grown I'd like for the content to become visible (by changing the opacity of the <a> in that <div>).
This is the code for the <div> animation:
#keyframes menu {
0% {
background-color: white;
right: -25px;
top: -25px;
border-radius: 100px;
width: 0px;
height: 0px;
}
25%{
right: -50px;
top: -50px;
border-radius: 100px;
width: 60px;
height: 60px;
}
50% {
right: -50px;
top: -50px;
width: 80px;
height: 80px;
border-radius: 100px;
}
75%{
right:-50px;
top:-50px;
width: 150px;
height: 150px;
border-radius: 100px;
}
80%{
right:-50px;
top:-50px;
width: 300px;
height: 300px;
border-radius: 300px;
}
100%{
right:-150px;
top:-150px;
width: 450px;
height: 450px;
border-radius: 600px;
}
}
It's basically a menu that starts in the corner and grows until the full screen is covered (mobile). I've tried adding a{ opacity: 1 }; but I guess it doesn't work like that.
If you want the anchor text (within the div) to be visible only after the animation on the parent div is fully complete then add another animation to the a, animate the opacity from 0 to 1 after a delay which is equal to the animation-duration of the parent.
div {
background-color: black;
line-height: 450px;
text-align: center;
animation: menu 4s linear forwards;
}
a {
color: white;
text-decoration: none;
animation: display 1s linear 4s backwards;
}
#keyframes menu {
0% {
background-color: white;
right: -25px;
top: -25px;
border-radius: 100px;
width: 0px;
height: 0px;
}
25% {
right: -50px;
top: -50px;
border-radius: 100px;
width: 60px;
height: 60px;
}
50% {
right: -50px;
top: -50px;
width: 80px;
height: 80px;
border-radius: 100px;
}
75% {
right: -50px;
top: -50px;
width: 150px;
height: 150px;
border-radius: 100px;
}
80% {
right: -50px;
top: -50px;
width: 300px;
height: 300px;
border-radius: 300px;
}
100% {
right: -150px;
top: -150px;
width: 450px;
height: 450px;
border-radius: 600px;
}
}
#keyframes display {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
<div>
<a href='#'>Some Menu Link</a>
</div>
I would use a little jQuery to do that. Using a callback you can call opacity 1 on a after the div is complete grown.
$( ".yourdiv" ).animate({
width: "450"
height: "450"
}, 5000, function() {
//callback will cause the a to change its opacity only when the above function is complete
$('.yourdiv a').css('opacity') = '1';
});

Resources