How to show div again when scroll using vh? - javascript

I am trying to make a horizontal transition when scrolling down and up to show and resize (shrink) div of the first element. I used inline-block to put them in the same position so that when one has been shrunk the other element will slide through but I am a bit confused to achieve this.
I tried to calculate the height and the offset position of the first inline element. This obviously will work for the first inline element but it won't work on the second inline element because it's in the same offset position.
Can you guys give me a bit of direction or tips to achieve this?
var topofDiv = $(".one").offset().top;
var heightDiv = $(".one").outerHeight();
$(window).scroll(function() {
if ($(window).scrollTop() > (topofDiv + heightDiv)) {
$(".one").show();
} else {
$(".one").hide();
}
});
* {
margin: 0;
padding: 0;
}
body {
overflow-x: hidden;
}
.container {
width: 100vw;
height: 100vh;
}
.content-wrapper {
width: 100vw;
white-space: nowrap;
}
.section {
width: 100vw;
height: 100vh;
position: relative;
display: inline-block;
}
.section div {
font-size: 100px;
color: white;
position: absolute;
top: 50%;
left: 50%;
transform: translateX(-50%) translateY(-50%);
}
.one {
background-color: red;
}
.two {
background-color: yellow;
}
<div class="container">
<div class="content-wrapper">
<div class="section one">
<div>one</div>
</div>
<div class="section two">
<div>two</div>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>

The show() and hide() calls need to be swapped over, they're in the wrong sides of your if condition. Also, the page height needs to be greater than the height of one of the .section elements for the transition to work properly, and the .container needs to be in fixed position for the scroll to have no effect on it. Try this:
var topofDiv = $(".one").offset().top;
var heightDiv = $(".one").outerHeight();
$(window).scroll(function() {
if ($(window).scrollTop() > (topofDiv + heightDiv)) {
$(".one").hide();
} else {
$(".one").show();
}
});
* {
margin: 0;
padding: 0;
}
body {
overflow-x: hidden;
height: 2000px;
}
.container {
width: 100vw;
height: 100vh;
position: fixed;
}
.content-wrapper {
width: 100vw;
white-space: nowrap;
}
.section {
width: 100vw;
height: 100vh;
position: relative;
display: inline-block;
}
.section div {
font-size: 100px;
color: white;
position: absolute;
top: 50%;
left: 50%;
transform: translateX(-50%) translateY(-50%);
}
.one {
background-color: red;
}
.two {
background-color: yellow;
}
<div class="container">
<div class="content-wrapper">
<div class="section one">
<div>one</div>
</div>
<div class="section two">
<div>two</div>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>

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>

left div width 100% increase when right div don't have content

I have 2 div both are 50% width and float left what I want if the right div doesn't have content then left div width should be 100%.
if ($('.wrap .box2').is(':empty')) {
$('.box2').hide();
$('.wrap .box1').css({
"width": "100%"
});
}
.wrap {
width: 100%;
}
.wrap .box1 {
width: 50%;
float: left;
background: red;
}
.wrap .box2 {
width: 50%;
float: left;
background: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrap">
<div class="box1">
<h1>Hello 1</h1>
</div>
<div class="box2">
<h1>Hello 2</h1>
</div>
</div>
So what I want if .box2 dont have text inside h1 then left div width should be 100%
if ($('.wrap .box2 h1').is(':empty')) {
$('.box2').hide();
$('.wrap .box1').css({
"width": "100%"
});
}
.wrap {
width: 100%;
}
.wrap .box1 {
width: 50%;
float: left;
background: red;
}
.wrap .box2 {
width: 50%;
float: left;
background: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrap">
<div class="box1">
<h1>Hello 1</h1>
</div>
<div class="box2">
<h1></h1>
</div>
</div>
I just ran this code and the left div took the whole space
Try this:
.wrap {
width: 100%;
display: flex;
}
.wrap .box1 {
width: 50%;
background: red;
flex-grow:1;
}
.wrap .box2 {
width: 50%;
background: green;
}
.wrap .box2:empty {
width: 0;
}
it works without using javascript/jquery and uses flex-boxes and the :empty selector.

Positioning a div to fixed on scroll to parent div

I have a div scroll-content that contains another div fixme which I want to fix only when the scroll-content div is at the top of the screen. If user scrolls past the scroll-content div, the fixme should disappear. I am using the code below but it doesn't seem to work:
var fixmeTop = $('.fixme').offset().top;
$(window).scroll(function() {
var currentScroll = $(window).scrollTop();
if (currentScroll >= fixmeTop) {
$('.fixme').css({
position: 'fixed',
top: '50%',
left: '50%',
display: 'block'
});
} else {
$('.fixme').css({
display: 'none'
});
}
});
body {
height: 3000px;
}
.content {
height: 500px;
background: white;
}
.scroll-content {
background: black;
height: 1000px;
}
.fixme {
background: green;
color: white;
text-align: center;
width: 100px;
height: 100px;
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
<div class="content"></div>
<div class="scroll-content">
<div class="fixme">Scroll here</div>
</div>
This here is an example that uses position sticky to keep the .fixme element inside of the .scroll-content element. It probably didn't work before in your own attempt because of jQuery overwriting the position property with fixed.
I hope that this is the desired effect.
Otherwise let us know so we can help you figure out another solution.
body {
height: 3000px;
}
.content {
height: 500px;
background: white;
}
.scroll-content {
position: relative;
background: black;
height: 1000px;
}
.fixme {
position: sticky;
top: calc(50% - 50px);
left: 50%;
background: green;
color: white;
text-align: center;
width: 100px;
height: 100px;
transform: translate(-50%, 0%);
}
<div class="content"></div>
<div class="scroll-content">
<div class="fixme">Scroll here</div>
</div>

How to resize bottom fixed div when top div is collapsed?

I have two divs, one on top, the other on the bottom. I need to have the bottom div fixed, and to resize and occupy the space above when the div on top is collapsed. Links to the scenarios below. Is this possible to accomplish using only CSS? This is for an angularJS application.
UPDATE: Support for older versions of browsers, specifically IE, must also be considered.
Div1 expanded
Div1 collapsed
Yes, you can do this using flex. See snippet below.
$(document).ready(function() {
$("#div1").click(function() {
$(this).css("max-height", "50px")
});
});
body, html {
margin: 0;
height: 100%;
}
.container {
height: 100%;
display: flex;
flex-direction: column;
}
.box {
flex-grow: 1;
text-align: center;
}
#div1 {
background-color: #4472C4;
}
#div2 {
background-color: #ED7D31;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- begin snippet: js hide: false console: true babel: false -->
Update
Since you noted in the comments you wanna support older browsers, the same as above can be achieved using the old fasion table layout.
$(document).ready(function() {
$("#div1").click(function() {
$(this).css("height", "50px")
});
});
html, body {
height: 100%;
margin: 0;
}
.container {
display: table;
height: 100%;
width: 100%;
}
.row {
display: table-row;
width: 100%;
}
.box {
display: table-cell;
color: #fff;
vertical-align: middle;
text-align: center;
}
#div1 {
background-color: #4472C4;
}
#div2 {
background-color: #ED7D31;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="row">
<div class="box" id="div1">
<strong>div1</strong>
</div>
</div>
<div class="row">
<div class="box" id="div2">
<strong>div1</strong>
</div>
</div>
</div>
You can try this.
html, body {
height: 100%;
margin: 0;
}
.wrapper {
display: table;
height: 100%;
width: 100%;
background: yellow;
}
.content {
display: table-row;
/* height is dynamic, and will expand... */
height: 100%;
/* ...as content is added (won't scroll) */
background: yellow;
}
.footer {
display: table-row;
background: grey;
}
<div class="wrapper">
<div class="content">
<h2>Content</h2>
</div>
<div class="footer">
<h3>Sticky footer</h3>
<p>Footer of variable height</p>
</div>
</div>
you can try this it works fine for me
<div class="wrapper">
<div class="container">
<div class="top-div">
topd div
</div>
<div class="bottom-div">
bottom div
</div>
</div>
</div>
CSS
.wrapper{
float:left;
height:100%;
}
.container {
position:absolute;
display: block;
float: left;
width: 100%;
height: 100%;
min-height:100%;
}
.top-div {
margin: 5px;
float: left;
position: fixed;
top: 0;
width: 90%;
height: 30%;
background-color: red;
}
.bottom-div {
margin: 5px;
position: absolute;
float: left;
bottom: 0;
width: 90%;
background-color: green;
}
use jQuery
$(function() {
var containerH = $(".container").height();
var topdivH = $(".top-div").height();
$(".bottom-div").height(containerH - topdivH);
});
check out jsfiddle

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.

Categories