center a div underneath another on click - javascript

I am trying to center a div programmatically underneath another one when a certain div is clicked. I have tried everything with no avail so i need some help. Below is code i wrote. This the jsfiddle link for what i am trying to do http://jsfiddle.net/U3pVM/18656/
<div ng-app>
<h2>Todo</h2>
<div ng-controller="TodoCtrl">
<div class="box" ng-click="do($event)">
<p> HEY THERRE </p>
</div>
<div class="box2" ng-show="show">
</div>
</div>
</div>
function TodoCtrl($scope) {
$scope.show =false;
$scope.do = function(evt) {
var $this = $(evt.target);
var offset = $this.offset();
var width = $this.width();
var height = $this.height();
var centerX = offset.left ;
var centerY = offset.top + height;
$('.box2').css({
'position': 'absolute',
'top': centerY,
'left': centerX
});
$scope.show = !$scope.show;
console.log(evt);
console.log(centerX, centerY);
};
}

Use position: relative on the .box2 element. Also, add margin: 0 auto; to position it horizontally center.
This will cut down your JS code for positioning the element.
Demo
function TodoCtrl($scope) {
$scope.show = false;
$scope.do = function(evt) {
$scope.show = !$scope.show;
};
}
.box {
top: 10px;
right: 400px;
width: 150px;
height: 150px;
background: orange;
color: white;
z-index: 10;
margin: 0 auto;
}
.box2 {
position: relative;
width: 300px;
height: 150px;
background: green;
opacity: 1;
z-index: 9;
margin: 0 auto;
}
.box2.ng-hide-add {
transition: all linear 5.5s;
}
.box2.ng-hide {
opacity: 0;
}
.box2 {
animation: slideDown .5s;
}
#keyframes slideDown {
0% {
transform: translateY(-20%);
}
100% {
transform: translateY(0%);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.min.js"></script>
<div ng-app>
<h2>Todo</h2>
<div ng-controller="TodoCtrl">
<div class="box" ng-click="do($event)">
<p>HEY THERRE</p>
</div>
<div class="box2" ng-show="show"></div>
</div>
</div>
You can also remove your controller as follow:
Demo
.box {
top: 10px;
right: 400px;
width: 150px;
height: 150px;
background: orange;
color: white;
z-index: 10;
margin: 0 auto;
}
.box2 {
position: relative;
width: 300px;
height: 150px;
background: green;
opacity: 1;
z-index: 9;
margin: 0 auto;
}
.box2.ng-hide-add {
transition: all linear 5.5s;
}
.box2.ng-hide {
opacity: 0;
}
.box2 {
animation: slideDown .5s;
}
#keyframes slideDown {
0% {
transform: translateY(-20%);
}
100% {
transform: translateY(0%);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.min.js"></script>
<div ng-app>
<h2>Todo</h2>
<div>
<div class="box" ng-init="show=false" ng-click="show=!show">
<p>HEY THERE</p>
</div>
<div class="box2" ng-show="show"></div>
</div>
</div>

Related

Parent height is changing according to it's visible children height with CSS only

I have such structure:
<div class="body">
<div class="wrapper">
<div class="dialog">
<div class="content-0"></div>
<div class="content-1"></div>
<div class="content-2"></div>
</div>
</div>
</div>
Parent element .dialog holds three content items which are horizontally aligned. Visible is only active .content-*. Other content items are hidden. When user clicks button, active item is sliding to the left to the hidden area, and next item becomes active and visible
Here is fiddle to demonstrate the behaviour: https://jsfiddle.net/fmbn28xs/
My question here - how can I adjust parent (.dialog) height every time user clicks button according to visible content (.content-*) item height only with CSS, is that possible?
Update:
Height of content items is not known in advance.
You can do it with custom css properties(preview with full page):
var index = 0;
function slide() {
index++;
var current = index % 3;
var target = document.querySelector(`.dialog`);
target.style.setProperty('--index', current);
}
.body {
background-color: #fff;
width: 100%;
height: 100%;
position: relative;
}
.wrapper {
background-color: grey;
position: absolute;
top: 50%;
right: 50%;
transform: translate(50%, 20%);
overflow: hidden;
}
.dialog {
--index: 0;
width: 300px;
display: flex;
height: calc(200px + 50px * var(--index));
transition: transform 400ms, height 400ms;
transform: translateX(calc(var(--index) * -100%));
}
.content-0, .content-1, .content-2 {
width: 300px;
flex: 0 0 100%;
position: relative;
}
.content-0 {
background-color: tomato;
height: calc(200px + 50px * 0);
}
.content-1 {
background-color: yellow;
height: calc(200px + 50px * 1);
}
.content-2 {
background-color: green;
height: calc(200px + 50px * 2);
}
button {
position: relative;
}
<div class="body">
<div class="wrapper">
<div class="dialog">
<div class="content-0"></div>
<div class="content-1"></div>
<div class="content-2"></div>
</div>
<button onclick="slide()">Next</button>
</div>
</div>
But you have to assign the height for all the content manually.
If you're using a precompile css library(such as scss), you can also automate this:
.dialog > *{
#for $i from 1 through 3 {
&:nth-child(#{$i}) {
height: calc(200px + 50px * #{$i});
}
}
}
Update
If the height is dynamic, you can use tricks with animation associate with alternating position from relative to absolute to make the container height
adapts accordingly, but this way you can't animate the height change, since the height is determined by the height of its children.
var index = 0;
function slide() {
index++;
var current = index % 3;
var target = document.querySelector(`.dialog`);
target.style.setProperty('--index', current);
target.setAttribute('data-index', current);
}
.body {
background-color: #fff;
width: 100%;
height: 100%;
position: relative;
}
.wrapper {
background-color: grey;
position: absolute;
top: 50%;
right: 50%;
transform: translate(50%, 20%);
overflow: hidden;
}
.dialog {
--index: 0;
width: 300px;
position: relative;
}
.dialog > * {
width: 300px;
position: absolute;
z-index: 0;
animation: popout 400ms both;
top: 0;
}
.dialog[data-index='0'] > *:nth-child(1),
.dialog[data-index='1'] > *:nth-child(2),
.dialog[data-index='2'] > *:nth-child(3) {
position: relative;
z-index: 1;
animation: popin 400ms both;
}
.content-0 {
background-color: tomato;
height: 200px;
}
.content-1 {
background-color: yellow;
height: 250px;
}
.content-2 {
background-color: green;
height: 300px;
}
button {
position: relative;
}
#keyframes popin {
from {
transform: translateX(100%);
}
to {
transform: translateX(0);
}
}
#keyframes popout {
from {
transform: translateX(0);
}
to {
transform: translateX(-100%);
}
}
<div class="body">
<div class="wrapper">
<div class="dialog" data-index="0">
<div class="content-0"></div>
<div class="content-1"></div>
<div class="content-2"></div>
</div>
<button onclick="slide()">Next</button>
</div>
</div>

Parallax elements on scroll

Fiddle
I have a horizontal page with multiple sections on it. On section 2 I have three images. When I scroll section 2 into view, I want the images to move 50px in the opposite scroll direction.
I have two problems which I can't figure out due to the layout of this page (horizontal instead of vertical):
how to detect when I reach section 2
how to move the images by ~50px in the opposite direction of the scroll and make it as smooth as possible
I use this code to figure out the direction of the scroll
var $scrollWrapper = $('.scroll_wrapper');
var $scrollBtn = $('#scrollBtn');
var $scrollOuterWrapper = $('.scroll_outer-wrapper');
$scrollWrapper.scrollTop(0)
$('#scrollBtn').on('click', function() {
$scrollWrapper.scrollTop($scrollWrapper.scrollTop() + 100)
});
var lastScrollTop = 0;
$scrollOuterWrapper.on('scroll', function() {
var st = $(this).scrollTop();
var endOfWrapper = $(this).scrollTop() + $(this).innerHeight() >= $(this)[0].scrollHeight;
if (st > lastScrollTop){
// down scroll
console.log('downscroll');
// parallax elements - move to front
// ??
$moveElement = $('.move-on-scroll');
$moveElement.each(function() {
var firstTop = $(this).offset().top;
var wrapperScrollTop = $scrollOuterWrapper.scrollTop();
var shiftDistance = (firstTop - wrapperScrollTop)*0.02;
$(this).css("transform","translateX("+shiftDistance+"px)");
});
} else {
// upscroll
console.log('upscroll');
// parallax elements - move to back
// ??
}
lastScrollTop = st;
});
Here's also a snippet:
var $scrollWrapper = $('.scroll_wrapper');
var $scrollBtn = $('#scrollBtn');
var $scrollOuterWrapper = $('.scroll_outer-wrapper');
$scrollWrapper.scrollTop(0)
$('#scrollBtn').on('click', function() {
$scrollWrapper.scrollTop($scrollWrapper.scrollTop() + 100)
});
var lastScrollTop = 0;
$scrollOuterWrapper.on('scroll', function() {
var st = $(this).scrollTop();
var endOfWrapper = $(this).scrollTop() + $(this).innerHeight() >= $(this)[0].scrollHeight;
if (st > lastScrollTop){
// down scroll
console.log('downscroll');
// parallax elements - move to front
// ??
$moveElement = $('.move-on-scroll');
$moveElement.each(function() {
var firstTop = $(this).offset().top;
var wrapperScrollTop = $scrollOuterWrapper.scrollTop();
var shiftDistance = (firstTop - wrapperScrollTop)*0.2;
$(this).css("transform","translateX("+shiftDistance+"px)");
});
} else {
// upscroll
console.log('upscroll');
// parallax elements - move to back
// ??
}
lastScrollTop = st;
});
.scroll_outer-wrapper {
width: 100vh;
height: 100vw;
transform: rotate(-90deg) translateX(-100vh);
transform-origin: top left;
overflow-y: scroll;
overflow-x: hidden;
position: absolute;
}
.scroll_wrapper {
display: flex;
flex-direction: row;
width: 400vw;
transform: rotate(90deg) translateY(-100vh);
transform-origin: top left;
transition: transform .5s ease;
}
.scroll_section {
width: 100vw;
height: 100vh;
}
.scroll_section.one{background: black; color: white;}
.scroll_section.two{background: white; color: black;}
.scroll_section.three{background: black; color: white;}
.scroll_section.four{background: pink; color: black;}
#scrollBtn {
position: absolute;
bottom: 20px;
right: 20px;
background-color: darkblue;
color: white;
border: none;
width: 80px;
height: 80px;
border-radius: 50%;
text-transform: uppercase;
font-size: 12px;
line-height: 20px;
cursor: pointer;
}
.move-on-scroll {
width: 150px;
height: 150px;
border: 2px solid red;
margin: 0 20px;
}
.move-on-scroll img {
width: 100%;
height: 100%;
object-fit: cover;
}
.two_inner {
display: flex;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="scroll_outer-wrapper">
<div class="scroll_wrapper">
<section class="scroll_section one">
<h2>section 1</h2>
</section>
<section class="scroll_section two">
<h2>section 2</h2>
<div class="scroll_section two two_inner">
<div class="move-on-scroll">
<img src="https://images.unsplash.com/photo-1590336751349-f65720fee481?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=80" >
</div>
<div class="move-on-scroll">
<img src="https://images.unsplash.com/photo-1590336751349-f65720fee481?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=80" >
</div>
<div class="move-on-scroll">
<img src="https://images.unsplash.com/photo-1590336751349-f65720fee481?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=80" >
</div>
</div>
</section>
<section class="scroll_section three">
<h2>section 3</h2>
</section>
<section class="scroll_section four">
<h2>section 4</h2>
</section>
</div>
</div>
<button id="scrollBtn">Click to Scroll</button>
While writing the answer, start thinking. I'm not quite sure, what is the goal. Maybe if you show some images of a result or explain the scenario - i could do more accurate. For now - made this. First line of image starts moving with the second screen. The second line of images start moving from the beginning. View the code in Full page mode.
UPDATED
Simply added transition to CSS for the element, which is transforming with transform via jquery.
.move-on-scroll {transition: all .5s cubic-bezier(.25,.99,.52,.9);}
If you what to correct the ease transition-timing-function - you can create your own cubic-bezier here https://cubic-bezier.com/
var $scrollWrapper = $('.scroll_wrapper');
var $scrollBtn = $('#scrollBtn');
var $scrollOuterWrapper = $('.scroll_outer-wrapper');
// Have no idea, what it shoud do
/*$scrollWrapper.scrollTop(0);
$('#scrollBtn').on('click', function() {
$scrollWrapper.scrollTop($scrollWrapper.scrollTop() + 100)
});*/
$scrollOuterWrapper.on('scroll', function() {
var st = $(this).scrollTop();
var sOneWidth = $('.scroll_section.one').width();
$moveElement = $('.move-on-scroll');
$moveElement.each(function() {
var firstTop = $(this).offset().left;
var shiftDistance = -st * 0.3;
// detects, when you reash section 2
if (st >= sOneWidth) {
//do something
}
$(this).css("transform", "translateX(" + shiftDistance + "px)");
});
});
* {
box-sizing: border-box;
}
html {
height: 100%;
}
body {
min-height: 100%;
margin: 0;
padding: 0;
}
.scroll_outer-wrapper {
width: 100vh;
height: 100vw;
transform: rotate(-90deg) translateX(-100vh);
transform-origin: top left;
overflow-y: scroll;
overflow-x: hidden;
position: absolute;
}
.scroll_outer-wrapper {
scrollbar-width: thin;
}
.scroll_outer-wrapper::-webkit-scrollbar {
width: 6px;
background-color: #fff;
}
.scroll_outer-wrapper::-webkit-scrollbar-track {
background-color: #F5F5F5;
border-radius: 10px;
}
.scroll_outer-wrapper::-webkit-scrollbar-thumb {
background: #ffa000;
}
.scroll_wrapper {
display: flex;
flex-direction: row;
width: 400vw;
transform: rotate(90deg) translateY(-100vh);
transform-origin: top left;
transition: transform .5s ease;
}
.scroll_section {
width: 100vw;
height: 100vh;
}
.scroll_section.one {
background: black;
color: white;
}
.scroll_section.two {
background: white;
color: black;
}
.scroll_section.three {
background: black;
color: white;
}
.scroll_section.four {
background: pink;
color: black;
}
#scrollBtn {
position: absolute;
bottom: 20px;
right: 20px;
background-color: darkblue;
color: white;
border: none;
width: 80px;
height: 80px;
border-radius: 50%;
text-transform: uppercase;
font-size: 12px;
line-height: 20px;
cursor: pointer;
}
.move-on-scroll {
width: 150px;
height: 150px;
border: 2px solid red;
margin: 0 20px;
transition: all .5s cubic-bezier(.25, .99, .52, .9);
}
.move-on-scroll img {
width: 100%;
height: 100%;
object-fit: cover;
}
.two_inner {
display: flex;
justify-content: flex-end;
overflow: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="scroll_outer-wrapper">
<div class="scroll_wrapper">
<section class="scroll_section one">
<h2>section 1</h2>
</section>
<section class="scroll_section two">
<h2>section 2</h2>
<div class="two_inner">
<div class="move-on-scroll">
<img src="https://images.unsplash.com/photo-1590336751349-f65720fee481?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=80">
</div>
<div class="move-on-scroll">
<img src="https://images.unsplash.com/photo-1590336751349-f65720fee481?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=80">
</div>
<div class="move-on-scroll">
<img src="https://images.unsplash.com/photo-1590336751349-f65720fee481?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=80">
</div>
</div>
</section>
<section class="scroll_section three">
<h2>section 3</h2>
</section>
<section class="scroll_section four">
<h2>section 4</h2>
</section>
</div>
</div>
<button id="scrollBtn">Click to Scroll</button>

Marquee div in flex

I'm trying to create an infinite horizontal "scroll" like a marquee effect (like this one, for example).
This is my code:
.parent {
border: 1px solid black;
width: 100%;
height: 2rem;
}
.container {
height: 100%;
display: flex;
padding-left: 10%;
border: 1px solid tomato;
animation: marquee 5s linear infinite;
}
#keyframes marquee {
0% {
transform: translate(0%, 0);
}
100% {
transform: translate(-100%, 0);
}
}
.child1 {
width: 10rem;
height: 100%;
background-color: #84B7DF;
}
.child2 {
width: 18rem;
height: 100%;
background-color: #f58db6;
}
.child3 {
width: 13rem;
height: 100%;
background-color: #ffc410;
}
.child4 {
width: 21rem;
height: 100%;
background-color: #C8E7C1;
}
<div class="parent">
<div class="container">
<div class="child1"></div>
<div class="child2"></div>
<div class="child3"></div>
<div class="child4"></div>
</div>
</div>
As you can see, it works but not perfectly.
I would like that as soon as the green rectangle has shifted, the blue (slightly spaced) one immediately appears, I don't want there to ever be a whole white screen.
I hope is clear what I mean...
Thanks a lot!
You could just add one more container element with same children, and then use display: flex with overflow: hidden on parent element. Also you can set width of the .container element to be larger then the window width using vw units and flex property.
Adjust width and padding properties on container if you have to.
.parent {
border: 1px solid black;
width: 100%;
height: 2rem;
display: flex;
overflow: hidden;
}
.container {
height: 100%;
flex: 0 0 120vw;
display: flex;
padding-right: 10%;
border: 1px solid tomato;
animation: marquee 5s linear infinite;
}
#keyframes marquee {
0% {
transform: translate(0%, 0);
}
100% {
transform: translate(-100%, 0);
}
}
.child1 {
width: 10rem;
height: 100%;
background-color: #84B7DF;
}
.child2 {
width: 18rem;
height: 100%;
background-color: #f58db6;
}
.child3 {
width: 13rem;
height: 100%;
background-color: #ffc410;
}
.child4 {
width: 21rem;
height: 100%;
background-color: #C8E7C1;
}
<div class="parent">
<div class="container">
<div class="child1"></div>
<div class="child2"></div>
<div class="child3"></div>
<div class="child4"></div>
</div>
<div class="container other">
<div class="child1"></div>
<div class="child2"></div>
<div class="child3"></div>
<div class="child4"></div>
</div>
</div>
Another solution is to add padding-right width vw units on container.
.parent {
border: 1px solid black;
width: 100%;
height: 2rem;
display: flex;
overflow: hidden;
}
.container {
height: 100%;
display: flex;
padding-right: 50vw;
border: 1px solid tomato;
animation: marquee 5s linear infinite;
}
#keyframes marquee {
0% {
transform: translate(0%, 0);
}
100% {
transform: translate(-100%, 0);
}
}
.child1 {
width: 10rem;
height: 100%;
background-color: #84B7DF;
}
.child2 {
width: 18rem;
height: 100%;
background-color: #f58db6;
}
.child3 {
width: 13rem;
height: 100%;
background-color: #ffc410;
}
.child4 {
width: 21rem;
height: 100%;
background-color: #C8E7C1;
}
<div class="parent">
<div class="container">
<div class="child1"></div>
<div class="child2"></div>
<div class="child3"></div>
<div class="child4"></div>
</div>
<div class="container other">
<div class="child1"></div>
<div class="child2"></div>
<div class="child3"></div>
<div class="child4"></div>
</div>
</div>
Javascript / jQuery solution, you can first create clone of the original element and append it to parent. Create a function that will decrease left position of the elements with setInterval function. If the offset is less then -width of the same element that means that element is off the screen. In that case you should move element to the end of the window or to the end of the other element with some offset.
const parent = $(".parent");
const container = $(".container");
const offset = 250;
const clone = cloner(container, parent, offset);
function cloner(element, parent, offset) {
const clone = element.clone();
const width = element.width();
clone.css({left: width + offset})
parent.append(clone)
return clone;
}
function move(element, size = 1) {
const position = element.position().left;
const width = element.width();
if (position < -width) {
const next = element.siblings().first();
const nPosition = next.position().left;
const nWidth = next.width();
const wWidth = $(window).width();
if (nPosition + nWidth < wWidth) {
element.css({left: wWidth})
} else {
element.css({left: nPosition + nWidth + offset})
}
} else {
element.css({left: position - size})
}
}
window.mover = setInterval(() => {
move(container)
move(clone)
}, 5)
.parent {
border: 1px solid black;
width: 100%;
height: 2rem;
display: flex;
overflow: hidden;
position: relative;
}
.parent>div {
position: absolute;
left: 0;
}
.container {
height: 100%;
display: flex;
border: 1px solid tomato;
}
.child1 {
width: 10rem;
height: 100%;
background-color: #84B7DF;
}
.child2 {
width: 18rem;
height: 100%;
background-color: #f58db6;
}
.child3 {
width: 13rem;
height: 100%;
background-color: #ffc410;
}
.child4 {
width: 21rem;
height: 100%;
background-color: #C8E7C1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="parent">
<div class="container">
<div class="child1"></div>
<div class="child2"></div>
<div class="child3"></div>
<div class="child4"></div>
</div>
</div>
.marquee {
position: relative;
width: 100%;
height: 1.5em;
line-height: 1.5em;
overflow: hidden;
> div {
position: absolute;
display: flex;
flex-wrap: nowrap;
animation: marquee 10s linear infinite;
transform: translateX(100%);
> * {
display: inline;
white-space: nowrap;
&:last-child {
padding-right: 100%;
}
}
}
}
#keyframes marquee {
0% {
-moz-transform: translateX(100%);
-webkit-transform: translateX(100%);
transform: translateX(100%);
}
100% {
-moz-transform: translateX(-100%);
-webkit-transform: translateX(-100%);
transform: translateX(-100%);
}
}

HTML/CSS Animation - JavaScript

I've been trying to animate a sliding door that is triggered on the click of a button.
Here is my fiddle
I've got two sides of the sliding door. Left side is blue, right side is red. The left side should slide to the left and the right door should slide to the right.
First of all, I'm trying to position the button to the middle of the door. I'm using
#button {
z-index: 2;
position: absolute;
top: 50%;
left: 50%;
}
but still the button appears kind of sideways
But secondly when the button is clicked, both sides of the door should slide out at the same time, but unfortunately only the red door functions correctly.
The blue door is stuck. What am I doing wrong?
You can use simple JQuery animation to do what you require.
FIDDLE
Here is the code:
$("button").click(function() {
$(".one").animate({
left: '0'
});
$(".three").animate({
left: '200px'
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="one" style="background:#98bf21;height:100px;width:100px;position:absolute;left:100px;"></div>
<div class="two" style="background:blue;height:100px;width:100px;position:absolute;left:100px;">
</div>
<div class="three" style="background:red;height:100px;width:100px;position:absolute;left:100px;"></div>
<button style="position:absolute;left:110px;top:50px;">
CLICK ME
</button>
It should be like this
function myMove() {
var elem = document.getElementById("myAnimationRight");
var elem_l = document.getElementById("myAnimationLeft");
var elem_R = document.getElementById("myAnimationRight");
elem_l.className += " opened";
elem_R.className += " opened";
}
#container {
width: 800px;
}
#button {
z-index: 2;
position: absolute;
top: 50%;
left: 50%;
}
#wrapper {
z-index: 1;
position: absolute;
display:inline-block;
width: 810px;
overflow:hidden;
}
#left {
display:inline-block;
width: 400px;
}
#right {
display:inline-block;
width: 400px;
}
#myContainer {
width: 400px;
height: 300px;
position: relative;
background: yellow;
}
#myAnimationLeft {
width: 400px;
height: 300px;
position: absolute;
background-color: blue;
transition:linear all 0.5s;
left:0;
}
#myAnimationRight {
width: 400px;
height: 300px;
position: absolute;
background-color: red;
transition:linear all 0.5s;
right:0;
}
#myAnimationRight.opened{
right:-100%;
transition:linear all 0.5s;
}
#myAnimationLeft.opened{
left:-100%;
transition:linear all 0.5s;
}
<div id="container">
<div id ="button">
<button onclick="myMove()">Click Me</button>
</div>
<div id="wrapper">
<div id ="left">
<div id ="myContainer">
<div id ="myAnimationLeft"></div>
</div>
</div>
<div id ="right">
<div id ="myContainer">
<div id ="myAnimationRight"></div>
</div>
</div>
</div>
</div>
You can handle animation via CSS and just add class opened to elements on button click.
You need to minus half the button width and height to bring it to the center.
If button's width is fixed, its correct to use calc(50% - 50px) as Icewine's answer.
For elements with dynamic widths and heights u can always use:
position: absolute;
top: 50%;
left: 50%;
transform:translateX(-50%) translateY(-50%);
The above code will center the element even if you dont know the height and width of the element.
Example:
body {
padding: 0px;
margin: 0px;
}
div {
width: 100px;
height: 100px;
position: absolute;
top: 50%;
left: 50%;
transform: translateX(-50%) translateY(-50%);
background: red;
}
<div></div>
As for animation, why not use classes and let the CSS handle the animation?
function myMove() {
document.getElementById("myAnimationLeft").className = "DoorOpenLeft";
document.getElementById("myAnimationRight").className = "DoorOpenRight";
}
* {
box-sizing: border-box;
}
body {
margin: 0px;
}
#container {
width: 100%;
}
#button {
z-index: 2;
position: absolute;
top: 50%;
left: 50%;
display: inline-block;
transform: translateX(-50%) translateY(-50%);
}
#wrapper {
z-index: 1;
position: absolute;
width: 100%;
overflow-x: hidden;
clear: both;
}
#left {
display: inline-block;
width: 50%;
float: left;
}
#right {
display: inline-block;
width: 50%;
float: right;
}
#myContainer {
width: 100%;
height: 300px;
position: relative;
background: yellow;
}
#myAnimationLeft {
width: 100%;
height: 300px;
left: 0px;
position: absolute;
background-color: blue;
transition: all 1s ease;
}
#myAnimationRight {
width: 100%;
height: 300px;
left: auto;
right: 0px;
position: absolute;
background-color: red;
transition: all 1s ease;
}
.DoorOpenLeft {
left: -100% !important;
}
.DoorOpenRight {
right: -100% !important;
}
<div id="container">
<div id="button">
<button onclick="myMove()">Click Me</button>
</div>
<div id="wrapper">
<div id="left">
<div id="myContainer">
<div id="myAnimationLeft"></div>
</div>
</div>
<div id="right">
<div id="myContainer">
<div id="myAnimationRight"></div>
</div>
</div>
</div>
</div>
Defining same vars causing issues and for the left door you need to decrease value _pos--
Solution for button
left: calc(50% - 38px);
#container {
width: 810px;
}
#button {
z-index: 2;
position: absolute;
top: 50%;
left: 50%;
}
#wrapper {
z-index: 1;
position: absolute;
display: inline-block;
width: 810px;
}
#left {
display: inline-block;
width: 400px;
}
#right {
display: inline-block;
width: 400px;
}
#myContainer {
width: 400px;
height: 300px;
position: relative;
background: yellow;
}
#myAnimationLeft {
width: 400px;
height: 300px;
position: absolute;
background-color: blue;
}
#myAnimationRight {
width: 400px;
height: 300px;
position: absolute;
background-color: red;
}
<div id="container">
<div id="button">
<button onclick="myMove()">Click Me</button>
</div>
<div id="wrapper">
<div id="left">
<div id="myContainer">
<div id="myAnimationLeft"></div>
</div>
</div>
<div id="right">
<div id="myContainer">
<div id="myAnimationRight"></div>
</div>
</div>
</div>
</div>
<script>
function myMove() {
var _elem = document.getElementById("myAnimationLeft");
var _pos = 0;
var _id = setInterval(_frame, 5);
function _frame() {
if (_pos == 410) {
clearInterval(_id);
} else {
_pos--;
_elem.style.right = _pos + 'px';
_elem.style.left = _pos + 'px';
}
}
var elem = document.getElementById("myAnimationRight");
var pos = 0;
var id = setInterval(frame, 5);
function frame() {
if (pos == 410) {
clearInterval(id);
} else {
pos++;
elem.style.left = pos + 'px';
elem.style.right = pos + 'px';
}
}
}
</script>
JQuery Solution created on #shubhamagrawal's answer.
$(document).ready(function() {
$('button').click(function() {
$("#myAnimationLeft").offset({
left: 0
})
$("#myAnimationRight").offset({
left: $("#myAnimationRight").width()
})
$("#myAnimationLeft").animate({
left: -$("#myAnimationLeft").width()
}, 2000);
$("#myAnimationRight").animate({
left: $("#myAnimationRight").width()
}, 2000);
})
})
body,
html {
margin: 0;
padding: 0;
}
#container {
width: 810px;
position:relative;
overflow:hidden;
height:300px;
}
#button {
z-index: 2;
position: absolute;
top: calc(50% - 11px);
left: calc(50% - 34px);
}
#wrapper {
z-index: 1;
position: absolute;
display: inline-block;
width: 810px;
}
#left {
display: inline-block;
width: 400px;
}
#right {
display: inline-block;
width: 400px;
}
#myContainer {
width: 400px;
height: 300px;
position: relative;
background: yellow;
}
#myAnimationLeft {
width: 400px;
height: 300px;
position: absolute;
background-color: blue;
}
#myAnimationRight {
width: 400px;
height: 300px;
position: absolute;
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<div id="button">
<button>Click Me</button>
</div>
<div id="wrapper">
<div id="left">
<div id="myContainer">
<div id="myAnimationLeft"></div>
</div>
</div>
<div id="right">
<div id="myContainer">
<div id="myAnimationRight"></div>
</div>
</div>
</div>
</div>
For the button, you need to minus the width and height of the button to center it.
left: calc(50% - 50px); if button width is 100px;
Also, you need to set the parent div above button to position: relative; or the absolute wont work. You should also set a height of the parent div while you are at it.

CSS diagonal mousemove fill on hover

I'm trying to fill a button with a diagonal effect on the mousemove (so the button is filled where the mouse is)
I have the effect of a diagonal fill on a hover:
.demo {
text-align: center;
margin-top: 150px;
}
.mt {
margin-top: 20px;
}
.small {
width: 120px;
}
.medium {
width: 160px;
}
.large {
width: 230px;
}
.extra-large {
width: 360px;
}
.diagonal {
position: relative;
display: inline-block;
line-height: 50px;
border: 1px solid black;
color: black;
background: white;
font-weight: book;
font-family: 'Open Sans', sans-serif;
overflow: hidden;
z-index: 1;
padding: 0px;
}
.diagonal:after {
content: "";
position: absolute;
top: 30;
left: 0;
width: 500%;
height: 1000%;
background: #F5FF35;
z-index: -1;
transform-origin: 0% 0%;
transform: translateX(calc(-130% - 0px)) translateY(10%) rotate(45deg);
transition: transform 1s;
}
.diagonal:hover::after {
transform: translateY(-100%) translateX(-50px) rotate(45deg);
direction: ltr;
}
<div class="demo">
<a class="mt small diagonal">Click me!</a><br>
<button class="mt medium diagonal">Click me!</button><br>
<button class="mt large diagonal">Click me!</button><br>
<button id="demo" class="mt extra-large diagonal">Click me!</button>
</div>
Codepen
But I can't set it up on a mousemove, I have found something similar from an other question, fiddle.
Basically, I am trying to fit the codepen and the jsfiddle together
I tried to rotate the div in the jsfiddle but the fill effect would be all over instead of only the start, plus it would not cover the whole area..
You can try something like this:
$('.green').on('mousemove', function(e) {
if (e.pageX < $(this).width());
var percent = e.pageX - $(this).offset().left * 100 / $(this).width();
$(this).css({
'background': 'linear-gradient(45deg, rgba(0,0,0,1) 0%,rgba(0,0,0,1) ' + percent + '%,rgba(0,0,0,0) ' + (percent + 0.1) + '%,rgba(0,0,0,0) 100%)'
});
});
demo:https://jsfiddle.net/sdq5z7ej/4/
You could do this by mostly adjusting the CSS, basically rotating that green div.
var parent = document.getElementById('parent');
var child = document.getElementById('child');
parent.addEventListener("mousemove", fill);
parent.addEventListener("mouseleave", hasLeft);
function fill(e) {
if (e.x <= parent.offsetWidth) {
child.style.width = e.x + 'px';
}
};
function hasLeft(e) {
if (child.offsetWidth === parent.offsetWidth) {
} else {
child.style.width = '0px';
}
}
.wrapper {
overflow: hidden;
height: 60px;
width: 100px;
background-color: #FFFF00;
}
#parent {
height: 65px;
width: 100px;
transform: scale(2) rotate(-45deg);
}
#child {
height: 65px;
width: 0;
background-color: #00FF00;
}
<div class="wrapper">
<div class='orange' id='parent'>
<div class='green' id='child'>
</div>
</div>
</div>
JSFIDDLE

Categories