This question already has answers here:
Position absolute but relative to parent
(5 answers)
Closed 2 years ago.
There are at least 2000 questions about this but in my particular scenario nothing I've tried worked.
My page consists of 2 nested divs (external, contents)
contents is clickable and should cover 100% of the document
there's also a bunch of absolutely positioned divs inside contents: those are draggable by a user and can be in any position.
If there are enough of these divs, scrollbar appears. And my contents is limited by the current browser window height, so when I start to scroll it's cut:
Here's a codepen: https://codepen.io/sergey-kritskiy/pen/qBbqQJv
I've tried...
setting min-height of everything one by one and all together;
adding flex on everything; float like this, float like that;
use %, vh, vmax;
When the scrollbar is made by a bunch of 'normal' divs, min-height works fine, but with these absolute guys I'm not in luck. I probably miss something obvious and I'd appreciate solutions.
Update:
There was an answer from someone that suggested to add position: relative; overflow-y: auto to contents and it worked in my case! But the answer was removed before I was able to ask why exactly that worked.
Solution 1
wrap items in another div called sidebar.
i am appending items in .sidebar instead of #content.
you can use grid in #external like i have used in css
var target = document.querySelector(".sidebar");
for (var i = 1; i <= 30; i++)
{
(function(i)
{
var div = document.createElement('div');
target.appendChild(div);
div.innerHTML = 'el ' + i;
div.className = 'item';
div.style.left = '5px';
div.style.top = 5 + ((i-1) * 105) + 'px';
div.addEventListener('click', function (evt) {
console.log("clicked el " + i);
evt.stopPropagation()
});
})(i);
}
target.addEventListener('click', function () {
console.log("content click");
});
body,
html {
width: 100%;
height: 100%;
margin-right: auto;
margin-left: auto;
vertical-align: middle;
margin: 0px;
background-color: white;
}
.item {
position: absolute;
background-color: blue;
width: 200px;
height: 100px;
border: 1px solid black;
}
#external {
background-color: #5b6f59;
display: grid;
grid-template-columns: 230px 1fr;
}
#content {
background-color: #5b6f59;
position: relative;
}
#external,
#content {
width: 100%;
height: 100%;
}
/** Added CSS **/
.sidebar {
height: 100vh;
overflow-y: auto;
position: relative;
}
<div id="external">
<div class="sidebar"></div>
<div id="content"> </div>
</div>
Solution #2
var target = document.querySelector("#content");
for (var i = 1; i <= 30; i++)
{
(function(i)
{
var div = document.createElement('div');
target.appendChild(div);
div.innerHTML = 'el ' + i;
div.className = 'item';
div.style.left = (Math.random()*100) + 'px';
div.style.top = 5 + ((i-1) * 105 + Math.random()*100 - 50) + 'px';
div.addEventListener('click', function (evt) {
console.log("clicked el " + i);
evt.stopPropagation()
});
})(i);
}
target.addEventListener('click', function () {
console.log("content click");
});
body,
html {
width: 100%;
height: 100%;
margin-right: auto;
margin-left: auto;
vertical-align: middle;
margin: 0px;
background-color: white;
}
.item {
position: absolute;
background-color: blue;
width: 200px;
height: 100px;
border: 1px solid black;
}
#external {
background-color: red;
}
#content {
background-color: #5b6f59;
height: 100vh;
overflow-y: auto;
position: relative;
}
#external {
width: 100%;
height: 100%;
}
<div id="external">
<div id="content">
</div>
</div>
Related
I need to change the size of h1's top padding based on the height of h1 and it's parent.
Padding top would be (h1's height - h1's parent height) / 2
I still don't understand why the JavaScript code isn't working.
window.onload = function() {
const h1 = document.getElementsByTagName("h1")[0];
h1.innerHTML = document.title;
h1.style.paddingTop = (((h1.parentElement.clientHeight - h1.clientHeight) / 2).toString());
console.log(((h1.parentElement.clientHeight - h1.clientHeight) / 2).toString());
}
header {
border-bottom: solid 1px black;
position: fixed;
height: 10vh;
width: 100%;
}
h1 {
margin: 0px;
margin-top: auto;
}
<header>
<h1>Text</h1>
</header>
Simply because you have not used a unit to identify the value of evaluated padding. Additionally add display: block to the h1 style. Checkout this JSBin demo.
window.onload = function() {
const h1 = document.getElementsByTagName("h1")[0];
h1.innerHTML = document.title;
h1.style.paddingTop = (((h1.parentElement.clientHeight - h1.clientHeight) / 2).toString())+'vh'; // Use unit.
console.log(((h1.parentElement.clientHeight - h1.clientHeight) / 2).toString());
}
header {
border-bottom: solid 1px black;
position: fixed;
height: 10vh;
width: 100%;
}
h1 {
margin: 0px;
margin-top: auto;
display: block;
}
<header>
<h1>Text</h1>
</header>
I'm using 'mouseenter' and 'mouseleave' to change the visibility of an image when I enter and leave an element. My issue is these events keep firing even when I'm within the element. Using 'pointer-events = none' works but it turns off another animation I have on the image. Is there a solution to this that either doesn't use pointer-events nor mousenter/leave and allows me to have animations on my image? DEMO
HTML:
<img id="image" src=""/>
<div id='box' class="box"></div>
CSS:
.box {
border: 2px solid red;
height: 400px;
width: 60%;
margin: 10px auto;
}
#image {
position:absolute;
width: 60px;
height: 60px;
display: none;
}
JS:
$(document).mousemove(function(e){
const height = $('#image').height() / 2;
const width = $('#image').width() / 2;
$("#image").css({
left:e.pageX-width,
top:e.pageY-height
});
});
$('.box').mouseenter(_=> {
$('#image').show();
});
$('.box').mouseleave(_=> {
$('#image').hide();
});
I'm not sure if this accomplishes what you're looking for - but you could change the z-index of the image and the background of the parent container, like:
$(document).mousemove(function(e){
const height = $('#image').height() / 2;
const width = $('#image').width() / 2;
$("#image").css({
left:e.pageX-width,
top:e.pageY-height
});
});
let entries = 0;
let exits = 0
$('.box').mouseenter(_=> {
$('#image').show();
entries += 1;
document.getElementById("entries").textContent=entries;
});
$('.box').mouseleave(_=> {
$('#image').hide();
exits += 1;
document.getElementById("exits").textContent=exits;
});
.box {
border: 2px solid red;
height: 400px;
width: 60%;
margin: 10px auto;
background: transparent;
}
#image {
position:absolute;
width: 60px;
height: 60px;
display: none;
z-index: -1;
}
#display {
position: absolute;
top:0;
left: 0;
border: 1px solid black;
width: 100px;
height: 100px;
text-align: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<img id="image" src="https://i5.walmartimages.ca/images/Large/580/6_r/875806_R.jpg"/>
<div id='box' class="box"></div>
<div id= 'display'>
<div id= 'entries'>00</div>
<div id= 'exits'>00</div>
</div>
Which will cause the .box to always be on top, even though the image is under your cursor.
Have you tried maybe setting a value to indicate the current state of the image?
Something like this:
var showImage = false;
$(document).mousemove(function(e){
const height = $('#image').height() / 2;
const width = $('#image').width() / 2;
$("#image").css({
left:e.pageX-width,
top:e.pageY-height
});
});
$('.box').mouseenter(_=> {
if (showImage)
return;
showImage = true;
$('#image').show();
});
$('.box').mouseleave(_=> {
showImage = false;
$('#image').hide();
});
I have this pure JavaScript carousel that i have found from another question asked from here (Im not taking ownership of this code).
I need to make the carousel show the first image, it is showing the second image currently, (My knowledge of JavaScript isn't that great, so i have tried all that i can).
(This is just for a project at collage.)
var firstval = 0;
function Carousel() {
firstval += 2;
parent = document.getElementById('container');
parent.style.left = "-" + firstval + "%";
if (!(firstval % 100)) {
setTimeout(Carousel, 3000);
firstval = 0;
var firstChild = parent.firstElementChild;
parent.appendChild(firstChild);
parent.style.left= 0;
return;
}
runCarousel = setTimeout(Carousel, 20);
}
Carousel();
#wrapper {
position: relative;
width: 100%;
height: 300px;
margin: 0 auto;
overflow: hidden;
}
#container {
position: absolute;
width: 100%;
height: 300px;
}
.child {
width: 100%;
height: 300px;
padding-top: 35px;
float: left;
text-align: center;
font-size: 60px;
}
#a {
background: #FF0000;
}
#b {
background: #FFFF00;
}
#c {
background: #00FFFF;
}
<div id="wrapper">
<div id="container">
<div id="a" class="child">a</div>
<div id="b" class="child">b</div>
<div id="c" class="child">c</div>
</div>
</div>
JSFIDDLE
Here is a very simple solution
Just add a timeout to your initial call of Carousel():
setTimeout(function(){
Carousel();
}, 3000);
Working fiddle: https://jsfiddle.net/wzkLjh8s/6/
I started learning JavaScript about a few weeks ago, and I have a problem. I have here two functions that are meant to bring up a menu when a button is clicked. In theory the menu that pops up should bring up a small div element from the left side, and 6 div elements within that div element. The main div element has the id "pokemonswitch" and when I click the button with the related function it only brings up "pokemonswitch" the other div elements don't seem to want to appear inside "pokemonswitch". I have tinkered with the code and have gotten various results.
1: Div elements appear in "pokemonswitch as programmed but after I click another button that removes "pokemonwitch" the div elements remain there despite the parent element not being there.
2: The div elements do not appear at all within "pokemonswitch".
3: The div elements appear in random places and the rest of the function doesn't work.
My goal is to have a function that calls up "pokemonswitch" with six div elements inside of it. Is there something I am missing about structure that is causing my child div elements to act so crazy? I hope this is clear enough to be answered, if not I will be more than happy to append more details to the problem.
//MAKE DIV ELEMENT pokemonswitch VISIBLE AND ASSOCIATIVE SLOTS AS WELL
function pkmnFunction() {
var element = document.getElementById('pokemonswitch');
var cancel = document.getElementById('optionsdiv');
element.style.visibility = "visible";
document.getElementById('slot1').style.visibility = "visible";
document.getElementById('slot2').style.visibility = "visible";
document.getElementById('slot3').style.visibility = "visible";
document.getElementById('slot4').style.visibility = "visible";
document.getElementById('slot5').style.visibility = "visible";
document.getElementById('slot6').style.visibility = "visible";
cancel.innerHTML = "<input id='cancelbutton' type='button' value='cancel' onclick='canFunction()' style='position:absolute; top:95px; left:35px;'></input>";
element.innerHTML = "<div id='slot1'></div><div id='slot2'></div><div id='slot3'></div><div id='slot4'></div><div id='slot5'></div><div id='slot6'></div>";
}
//MAKE DIV ELEMENT pokemonswitch HIDDEN AND ASSOCIATED slot ELEMENTS AS WELL
function canFunction() {
var element = document.getElementById('pokemonswitch');
var cancel = document.getElementById('optionsdiv');
document.getElementById('slot1').style.visibility = "hidden";
document.getElementById('slot2').style.visibility = "hidden";
document.getElementById('slot3').style.visibility = "hidden";
document.getElementById('slot4').style.visibility = "hidden";
document.getElementById('slot5').style.visibility = "hidden";
document.getElementById('slot6').style.visibility = "hidden";
element.style.visibility = "hidden"
cancel.innerHTML = "<input id='b5' type='button' onclick='setSlots()' value='Check Slot' ></input><input id='b1' type='button' value='Fight!'></input><input id='b2' type='button' onclick='pkmnFunction()' value='Pkmn'></input><input id='b3' type='button' value='Items' onclick='itemFunction()'></input><input id='b4' type='button' value='Run'></input>";
}
////////////ASSOCIATED CSS STYLE CODE//////////////////
#pokemonswitch {
position: absolute;
width: 180px;
margin - left: -15px;
height: 100 % ;
border: solid;
border - color: black;
border - width: 2px;
border - radius: 25px;
background - color: 0099CC;
z - index: 3;
visibility: hidden;
}
#slot1 {
position: absolute;
top: 0px;
left: -10px;
padding: 5px;
text - align: center;
border: solid;
border - width: 1px;
background - color: red;
width: 170px;
height: 65px;
z - index: 4;
}
#slot2 {
position: absolute;
top: 65px;
left: -10px;
padding: 5px;
text - align: center;
border: solid;
border - width: 1px;
background - color: red;
width: 170px;
height: 65px;
z - index: 4;
visibility: hidden;
}
#slot3 {
position: absolute;
top: 130px;
left: -500px;
padding: 5px;
text - align: center;
border: solid;
border - width: 1px;
background - color: red;
width: 170px;
height: 65px;
z - index: 4;
visibility: hidden;
}
#slot4 {
position: absolute;
top: 195px;
left: -500px;
padding: 5px;
text - align: center;
border: solid;
border - width: 1px;
background - color: red;
width: 170px;
height: 65px;
z - index: 4;
visibility: hidden;
}
#slot5 {
position: absolute;
top: 260px;
left: -500px;
padding: 5px;
text - align: center;
border: solid;
border - width: 1px;
background - color: red;
width: 170px;
height: 65px;
z - index: 4;
visibility: hidden;
}
#slot6 {
position: absolute;
top: 325px;
left: -250px;
padding: 5px;
text - align: center;
border: solid;
border - width: 1px;
background - color: red;
width: 170px;
height: 65px;
z - index: 4;
visibility: hidden;
}
The issue is, you are trying to refer an element that isn't even created yet.
element.innerHTML = "<div id='slot1'></div><div id='slot2'></div><div id='slot3'></div><div id='slot4'></div><div id='slot5'></div><div id='slot6'></div>";//Place this first
document.getElementById('slot1').style.visibility = "visible";
document.getElementById('slot2').style.visibility = "visible";
document.getElementById('slot3').style.visibility = "visible";
document.getElementById('slot4').style.visibility = "visible";
document.getElementById('slot5').style.visibility = "visible";
document.getElementById('slot6').style.visibility = "visible";
cancel.innerHTML = "<input id='cancelbutton' type='button' value='cancel' onclick='canFunction()' style='position:absolute; top:95px; left:35px;'></input>";
Also few other things I noticed were:
Instead of using style.visibility use style.display. <input> isn't a container element, so remove </input> everywhere.
document.getElementById('slot1').style.visibility = "visible";
element.innerHTML = "<div id='slot1'></div>";
This is not right. The first line suggests that an element with id slot already exists. The second line adds a new div with that same id.
If the element should already exist, you can add the existing element
var slot1 = document.getElementById('slot1');
slot1.style.visibility = "visible";
element.appendChild(slot);
If not, you can create it first:
var slot1 = document.createElement('div');
slot1.id = 'slot1';
slot1.style.visibility = "visible";
element.appendChild(slot);
I do it this way! Create a div that contains the form you want and make this div display:none. Then on click make it visible where you want to
<div style="display:none">
<div id="mycontent">
content content
</div>
</div>
then use
document.getElementById('ID')..style.display="value"
I'm trying to create a page where a centrally placed div resizes to fit in the page both horizontally and vertically whilst retaining the ratio.
Currently I'm using a combination of JS and CSS although I'm not sure it's particularly efficient - it also seems a little hacky.
How would I either clean up this code or rewrite it to achieve this?
Javascript
function changesize(){
var $width = $(".aspectwrapper").height();
var $changewidth = $width * 1.5;
var $doc = $(document).width();
var $height;
if ($doc <= $changewidth){ $changewidth = ( $doc - 100 );
$height = ( ($doc - 100) / 1.5 );
$(".aspectwrapper").css('height', "" + $height + "");
};
$(".content").css('width', "" + $changewidth + "");
$(".aspectwrapper").css('width', "" + $changewidth + "");
};
$(document).ready(function(e) {
$(changesize);
});
$(window).resize(function(e) {
$(changesize);
});
CSS
html, body {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
.aspectwrapper {
display: inline-block;
position: relative;
margin: 0 auto;
height: 90%;
border: #F00 1px solid;
background-color: #F00;
}
.content {
position: absolute;
top: 0;
bottom: 0;
right: 0;
margin-top: 60px;
outline: thin dashed green;
overflow: hidden;
background-color: #09C;
}
#wrapper {
width: 100%;
height: 100%;
text-align: center;
background-color: #0F3;
float: left;
}
HTML
<div id="wrapper">
<div class="aspectwrapper">
<div class="content"> CONTENT GOES HERE</div>
</div>
<div style="clear:both;"></div>
</div>
I'd personally position my center div horizontally and vertically using positioning/margin combinations with a specific liquid width and height. It would resize based on page width without the use of javascript. Here's an example.
http://jsfiddle.net/9Aw2Y/