I have three inline-block divs on my page (see JSFiddle):
Div #one contains a button 'Show' and is absolutely positioned so that it overlaps the div #two. When 'Show' is clicked, div #two slides out from under #one using translateX, like so:
When this happens, I would like to push div #three down so that it appears just below div #two, like so:
I'm not sure how to go about achieving this using pure CSS that doesn't involve moving #three along the Y-axis using #three { transform: translateY(...) }. I was wondering if translateX is the wrong approach here since it does not disturb the position of neighbouring elements, but I don't know what to use in its place.
As I have already stated in the comment section: It really depends on what your final goal is and what content you put in your divs - how everything is structured.
I feel like this is more of a XY-problem. I.e. the design-choice demands for a special case/solution that could be solved in another way so that the "hacky" solution does not have to exist in the first place.
Nevertheless, since you have asked for it I give you a solution for this specific problem:
const container = document.querySelector('.container');
const slide = document.getElementById('show');
const done = document.getElementById('hide');
const two = document.getElementById('two');
const right = document.querySelector('.right');
show.addEventListener('click', function() {
two.classList.add('show');
right.classList.add('shift');
});
hide.addEventListener('click', function() {
two.classList.remove('show');
setTimeout(function() {
right.classList.remove('shift');
}, 1000)
});
.left,
.right {
position: relative;
height: 200px;
margin-top: 5px;
display: inline-block;
border: 1px solid black;
float: left;
}
.left {
width: 100px;
}
.right {
width: 200px;
margin-left: 10px;
transform: translateX(0);
}
.right.shift {
clear: left;
display: block;
float: none;
transform: translateX(100px);
}
#one,
#two {
height: 100%;
}
#one {
background-color: lightblue;
position: absolute;
z-index: 1;
}
#two {
background-color: yellow;
transform: translateX(0);
transition: transform 1s;
}
#two.show {
transform: translateX(100%);
}
<div class="left">
<div id="one">
Click 'Show' to show panel 2
<button type='button' id='show'>Show</button>
</div>
<div id="two">
Click 'Hide' to hide panel 2
<button type='button' id='hide'>Hide</button>
</div>
</div>
<div class="right">Some other content</div>
Alternative
You could implement a spoiler section that you can toggle to display more information if it is desired.
const spoilerBtn = document.getElementById('spoiler-btn');
const spoiler = document.getElementById('spoiler');
spoilerBtn.addEventListener('click', function() {
spoiler.classList.toggle('show');
});
.left,
.right {
position: relative;
height: 200px;
margin-top: 5px;
display: inline-block;
border: 1px solid black;
float: left;
}
.left {
width: 100px;
}
.right {
width: 200px;
margin-left: 10px;
}
#spoiler {
background-color: tomato;
display: none;
}
#spoiler.show {
display: block;
}
<div class="left">Aside text here</div>
<div class="right">
Toggleable section: <button id="spoiler-btn">toggle</button>
<div id="spoiler">This content can be toggled</div>
<p>Some other content</p>
</div>
Related
Hoping for a little guidance. I'm making a "slide up" menu for a site i'm using and I have it working, except it's not responsive. Ideally, i'd like to have it so whatever I put in the content under "Book Now" would be hidden no matter the size, while keeping "Book Now" shown.
The way I have it set up now, I have to be very verbose about heights, and it doesn't seem to really want to work on mobile.
Hoping you kind folks could point me in the right direction of what CSS I actually need to make this work!
Here is the JSFiddle:
https://jsfiddle.net/yg13exft/
<style>
/* footer fixed Menu stuff */
.bottomNav{
overflow: hidden;
position: fixed;
bottom: -210px;
width: 100%;
transition: all .7s ease-in-out;
z-index: 9999;
}
.tipBar{
text-align: center;
transition: all .7s ease-in-out;
}
.tipBar a{
color: #6c0505;
background: orange;
display: inline-block;
padding: 5px 15px 5px 15px;
}
.menuBar{
background-color: #6c0505;
display: grid;
grid-template-columns: auto auto;
justify-content: center;
padding-top: 10px;
height: 100%;
}
.bottomNav p{
color: black;
}
.displayNone{
display: none;
}
.tipToggleAnim{
bottom: 46px;
}
.bottomMenuAnim{
bottom: 0;
}
.rightCol img{
max-height: 200px;
}
</style>
<div class="bottomNav" id="bottomNav">
<div class="tipBar" id="tipBar">
<a id="bookNowButton" class="animate__animated animate__backInUp">
Book Now!
</a>
</div>
<div id="dialog" class="menuBar" >
<div class="leftCol">
<p>
TEST TEXT HERE! :)
</p>
</div>
<div class="rightCol">
<img src="https://images.unsplash.com/photo-1589883661923-6476cb0ae9f2?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1374&q=80" alt="cat">
</div>
</div>
</div>
<script>
let toggledVar = false;
function popupMenu(){
let menuToggle = document.getElementById("bottomNav");
let divButton = document.getElementById("tipBar");
if (toggledVar == true){
toggledVar = !toggledVar;
menuToggle.classList.remove('bottomMenuAnim');
}
else {
toggledVar = !toggledVar;
menuToggle.classList.add('bottomMenuAnim');
}
}
let buttonTest = document.getElementById("bookNowButton");
buttonTest.addEventListener("click", popupMenu, false);
</script>
Thank you.
I would use clientHeight to get the height of the dialog section and then set that as the bottom attribute so it will always be hidden. That way no matter what the height of the content, it will always know how many pixels to set bottom to and hide the div, but keep the Book Now showing.
There is a window load event because we need the DOM to fully load before we retrieve dialog div height.
Then, we use animate to smooth the change of the bottom attribute. Animate takes two parameters, the keyframes and the options. In the options, fill makes the animation run and stay in its end state. You can adjust the duration to fit your liking.
// We wait for the page to fully load, then we can grab the height of the div
window.addEventListener('load', function() {
// Toggle boolean
let toggledVar = false;
// Set toggle to Book now button
let menuToggle = document.getElementById("bookNowButton");
// Get bottomNav section
let bottomNav = document.getElementById("bottomNav");
// Get the height of the div
let hiddenSection = document.getElementById("dialog").clientHeight;
// Set bottom css attribute
bottomNav.style.bottom = `-${hiddenSection}px`;
function popupMenu(){
if (toggledVar == false) {
// Set bottom css attribute to 0px to reveal it
bottomNav.animate([
// keyframes
{ bottom: `-${hiddenSection}px` },
{ bottom: '0px' }
], {
duration: 1000,
fill: 'forwards'
});
toggledVar = true;
} else {
// Set bottom css attribute to hide it
bottomNav.animate([
// keyframes
{ bottom: '0px' },
{ bottom: `-${hiddenSection}px` }
], {
duration: 1000,
fill: 'forwards'
});
toggledVar = false;
}
}
menuToggle.addEventListener('click', popupMenu);
});
* {
box-sizing: border-box;
}
html, body {
padding: 0;
margin: 0;
width: 100%;
min-height: 100vh;
}
#bottomNav {
max-width: 100%;
position: fixed;
overflow: hidden;
left: 0px;
}
#bookNowButton {
display: block;
margin: 0 auto;
text-align: center;
padding: 1rem;
max-width: 200px;
background-color: yellow;
cursor: pointer;
}
#dialog {
background-color: #6c0505;
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-gap: 1rem;
padding: 1rem;
}
.rightCol img {
max-width: 100%;
}
<div id="bottomNav">
<span id="bookNowButton">Book Now!</span>
<div id="dialog">
<div class="leftCol">
<p>
TEST TEXT HERE! :)
</p>
</div>
<div class="rightCol">
<img src="https://images.unsplash.com/photo-1589883661923-6476cb0ae9f2?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1374&q=80" alt="cat">
</div>
</div>
</div>
I know that title here is hard to understand. I really need help changing this fiddle. So here is what I am trying to do:
When button is clicked, I want the div (coding) to resize to the size of the button itself and I want the button with div(coding) to float over the div (coding2). (coding2) div should resize to its full width at that time.
When button is clicked again, bring the view back to the way it was initially. Attached you will find an image of before and after of what I am looking for. All of this I hope to accomplish just using CSS.
<div id="coding">
<button id = "content" onclick="dosomething()">Click Me</button>
</div>
<div id = "coding2">
</div>
switch the width of the both divs between 0% to 50% for the first one and 49% to 100% for the second one:
function dosomething() {
if($('#coding').width() > 0){
$('#coding').width('0')
$('#coding2').width('100%')
}
else {
$('#coding').width('50%')
$('#coding2').width('49%')
}
}
#coding {
width: 50%;
border: 1px solid black;
height: 300px;
position:absolute;
left:0;
z-index:1;
overflow:visible;
background:yellow;
}
#coding2 {
border: 1px solid black;
height: 300px;
width: 49%;
position:absolute;
right:0;
z-index:0;
background:blue;
}
button {
width:70px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="coding" class="larger">
<button onclick="dosomething()">Click Me</button>
</div>
<div id = "coding2">
</div>
float used to be the way to create layouts, but nowadays we have tools like CSS Grid Layout and Flexbox to create awesome layouts with.
The example below use the former, Grid, which enables you to create a layout and place your child elements within that layout. All width and height calculations are done from the parent (#grid). All the children (#coding and #coding2) have to do is say where in the grid they need to go.
With JavaScript, and in this case jQuery, listen to a click on the button. Then toggle a class on the #grid element. With that class you can set styles on the children which can make them move around in the grid, and in this case, take the width of the entire parent (#grid).
$('#button').on('click', () => {
$('#grid').toggleClass('is-active');
});
#grid {
position: relative;
display: grid;
grid-template-rows: 200px;
grid-template-columns: 200px 1fr;
}
#button {
position: absolute;
top: 10px;
left: 10px;
z-index: 2;
}
#coding {
grid-row: 1 / 2;
grid-column: 1 / 2;
background: blue;
}
#coding2 {
grid-row: 1 / 2;
grid-column: 2 / 3;
background: yellow;
z-index: 1;
}
#grid.is-active #coding2 {
grid-column: 1 / 3;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="grid">
<button id="button">Click Me</button>
<div id="coding"></div>
<div id="coding2"></div>
</div>
Create 4 classes, two for each div. The just use .toggleClass() to add or remove it on button click.
function dosomething() {
$("#coding").toggleClass("clicked unclicked");
$("#coding2").toggleClass("clicked2 unclicked2");
}
#coding {
background-color: lightgreen;
}
#coding2 {
background-color: yellow;
}
.clicked {
width: auto;
height: auto;
position: absolute;
border:1px solid black;
}
.unclicked {
width: 50%;
border:1px solid black;
height:300px;
float: left;
}
.clicked2 {
width: 100vw;
height: 300px;
border:1px solid black;
float: none;
}
.unclicked2{
border:1px solid black;
height:300px;
float: right;
width: 49%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<div id="coding" class="unclicked">
<button onclick="dosomething()">Click Me</button>
</div>
<div id="coding2" class="unclicked2">
</div>
I'm trying to make something where I need to duplicate all the entries (multiple times) and then later I would like to make it spin and land on a colour slowly, etc. I'm now just getting stuck at duplicating the colours, how can I make it so the new colours are overflowing, without doubling the width?
I want it so that the colours go out of the wrapper div. Now they are just distributing themselves.
Any ideas?
$(document).on("click", ".duplicate", function() {
var $wrapper = $('.wrapper .inner');
$wrapper.find('.color').each(function() {
$wrapper.append($(this).clone());
});
});
.wrapper {
width: 75%;
margin: 12px auto;
height: 26px;
border-radius: 6px;
overflow: hidden;
position: relative;
}
.wrapper .inner {
width: 100%;
height: 100%;
position: absolute;
display: flex;
}
.wrapper .color {
width: 100%;
height: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div class="inner">
<div class="color" style="background:red;width:231%"></div>
<div class="color" style="background:purple;width:111%"></div>
<div class="color" style="background:orange;width:91%"></div>
</div>
</div>
<button class='duplicate'>
Duplicate
</button>
In order to have two items in the same position in document flow you need to wrap them in a parent with position:relative and give one of them position:absolute; top:0;left:0. Also note that if your element doesn't have any content, you might need to define it's height and width. To make it same size as parent, you can give it top:0;bottom:0;left:0;right:0;.
Here's a demo started from your fiddle. You might want to inspect DOM after you press "Duplicate". I made it revert to original, so you can do it multiple times.
But do note your question is currently unclear. I'm afraid you lost me at "to make it spin and land on a colour slowly". It's truly poetic, but won't get you very far on SO...
I guess you are simply over complicating this. All what you need is a reapeated linear-gradient like this:
.wrapper {
width: 75%;
margin: 12px auto;
position: relative;
}
.wrapper .inner {
width: 100%;
height: 25px;
display: flex;
border-radius: 6px;
overflow: hidden;
}
.wrapper .color {
width: 100%;
height: 100%;
}
.new {
margin-top:5px;
height:25px;
border-radius: 6px;
background-image:linear-gradient(to right,red,red 54%,purple 54%, purple 80%,orange 0);
background-size:100% 100%;
animation:change 5s linear infinite alternate;
}
#keyframes change {
from {
background-position:0 0;
}
to {
background-position:-1000px 0;
}
}
<div class="wrapper">
<div class="inner">
<div class="color" style="background:red;width:231%"></div>
<div class="color" style="background:purple;width:111%"></div>
<div class="color" style="background:orange;width:91%"></div>
</div>
<div class="new"></div>
</div>
So I have 2 divs children of a display block parent. I would like to make div #2 (green) be on top of div #1 (red). With "on top" I'm not talking about z-index, I'm talking about literally being on top of the other. And then I was wondering if there could be a way to make div #2 slideDown()
As far as I tested, jQuery slideDown() or slideUp() works differently.
In the demo I made, when I run
$('.item-1').slideUp();
The item 2 is sliding up instead of item 1, why is that? I'm getting confused.
Any hints would be appreciated,
Thanks in advance.
window.slide = function() {
$('.item-1').slideUp();
}
.items-container {
height: 400px;
width: 240px;
background-color: #c3c3c3;
display: block;
/* overflow: hidden; */
}
.item {
height: 100%;
width: 240px;
position: relative;
font-size: 30px;
text-align: center;
vertical-alignment: middle;
}
.item-1 {
background-color: red;
}
.item-2 {
float: left;
position: relative;
background-color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button onclick="slide()">
Click me!
</button>
<div class="items-container">
<div class="item item-1">
1
</div>
<div class="item item-2">
2
</div>
</div>
jQuery's slideUp() and slideDown() methods animate the height of the matched elements, not position as you seemed to want: http://api.jquery.com/slideUp/.
What you seem to want is to translate the div it so that it moves on top of the first one.
http://www.w3schools.com/css/css3_2dtransforms.asp
window.slideUp = function() {
$('.item-2').addClass('slideUp');
}
window.slideDown = function() {
$('.item-2').removeClass('slideUp');
}
.items-container {
height: 100px;
width: 240px;
background-color: #c3c3c3;
display: block;
/* overflow: hidden; */
}
.item {
height: 100%;
width: 240px;
position: relative;
font-size: 30px;
text-align: center;
vertical-alignment: middle;
}
.item-1 {
background-color: red;
}
.item-2 {
position: relative;
transition: transform linear 1s;
background-color: green;
}
.slideUp
{
transform: translate(0,-100%);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button onclick="slideUp()">
SlideUp!
</button>
<button onclick="slideDown()">
SlideDown!
</button>
<div class="items-container">
<div class="item item-1">
1
</div>
<div class="item item-2">
2
</div>
</div>
.slideUp() works by changing the height of the element. As that element gets shorter, following elements will move up the page.
As seen in the documentation:
The .slideUp() method animates the height of the matched elements. This causes lower parts of the page to slide up, appearing to conceal the items.
In your fiddle, item1 slides up as expected and as defined by the doc :
Description: Hide the matched elements with a sliding motion.
So your div slides up and disappears, and item2 doesn't "move", just fills the space in the DOM after item1 has been hidden.
I'm trying to do what many have asked before, but even after trying everything I still can't get the results I want.
I have an image 600px by 1600px, 4 images of 600px by 400px in a vertical line. I want to show 600px by 400px of the image at any one time. Ideally I would be able to hover over an element somewhere on my page and move the image upwards to reveal the other portions of the 600px by 400px image. In effect, I'd have 4 images viewable by hovering over 4 the elements.
I've tried various css3 and jquery solution but none have worked. I would appreciate any help with this.
HTML
<div class="mainimage">
<div class="buttonsection">
<div class="button1">Button 1</div>
<div class="button2">Button 2</div>
<div class="button3">Button 3</div>
<div class="button4">Button 4</div>
</div><!--end of buttonsection-->
<div class="rollingimage">
<img src="IMG/four-pics.png">
</div><!--end of rollingimage-->
</div><!--end of mainimage-->
</div><!--end of main content-->
CSS
.mainimage {
position: relative;
top: 0px;
left: 0px;
width: 900px;
height: 400px;
border: 2px solid #E78F25;
margin: 0 10px 20px 0;
}
.buttonsection {
width: 290px;
height: 400px;
position: relative;
float: left;
}
.button1,
.button2,
.button3,
.button4 {
display: inline;
height: 98px;
width: 290px;
border: 1px solid #E78F24;
text-align: center;
float: left;
}
.rollingimage {
width: 598px;
height: 400px;
position: relative;
overflow: hidden;
top: 0px;
left: 0px;
float: right;
}
jquery
$(document).ready(function(){
$(".button1").hover(function(){
$('.rollingimage').stop().animate({'top': '-200px'}, 1500);
});
});
Here is the jsfidle: http://jsfiddle.net/dirtyd77/jCvYm/1/
Thanks yet again
Gary
Just for fun, no JS:
http://jsfiddle.net/coma/MTWdb/5/
HTML
<div id="foo">
Button 1
Button 2
Button 3
Button 4
<div></div>
</div>
CSS
#foo {
width: 400px;
border: 2px solid #E78F25;
position: relative;
}
#foo > div {
position: absolute;
top: 0;
right: 0;
bottom: 0;
width: 200px;
background: #fff url(http://placekitten.com/600/1600) no-repeat 0 0;
transition: background-position .5s;
}
#foo > a {
display: block;
width: 200px;
line-height: 100px;
text-align: center;
text-decoration: none;
}
#foo > a + a {
border-top: 1px solid #E78F25;
}
#foo > a:nth-child(1):hover ~ div {
background-position: 0 0;
}
#foo > a:nth-child(2):hover ~ div {
background-position: 0 -400px;
}
#foo > a:nth-child(3):hover ~ div {
background-position: 0 -800px;
}
#foo > a:nth-child(4):hover ~ div {
background-position: 0 -1200px;
}
You need to change the positioning of the image inside the div, not the div itself. To animate my example, you could add CSS transitions for better performance than JS animations.
http://jsfiddle.net/jCvYm/8/
$('.rollingimage').find('img')
As Dom mentioned, the jsFiddle you provided didn't reference the jQuery library. It also didn't included any actual images, and only contained code for one of the three buttons. I doubt those were the original problems you were having, though. (The missing reference to jQuery might have been.)
Once I had those straightened out, I noticed that hovering the button caused the picture to slide out of the screen, instead of scrolling. The simplest way to fix that is to move the img element, instead of moving the div. (The more natural way would be to change the scroll position of the div, but I don't recall how to do that off the top of my head.)
Added CSS:
.rollingimage img {
position: relative;
}
New JS:
$(document).ready(function(){
$(".button1").hover(function(){
$('.rollingimage img').stop().animate({'top': '0px'}, 1500);
});
$(".button2").hover(function(){
$('.rollingimage img').stop().animate({'top': '-400px'}, 1500);
});
$(".button3").hover(function(){
$('.rollingimage img').stop().animate({'top': '-800px'}, 1500);
});
$(".button4").hover(function(){
$('.rollingimage img').stop().animate({'top': '-1200px'}, 1500);
});
});
jsFiddle: http://jsfiddle.net/jCvYm/6/