I am trying to draw a vertical line across a whole div following the mouse. The problem is that other elements are over the line. I want the line go over all content.
Here is the fiddle: https://jsfiddle.net/9hzcm23q/
And here the code:
var element = document.getElementById('box');
var drawLines = function(event) {
var x = event.pageX;
var straightLine = element.querySelector('.straightLine');
var slTrans = 'translate(' + x + 'px, 0px)';
if(!straightLine) {
straightLine = document.createElement('div');
straightLine.classList.add('straightLine');
straightLine.style.height = "100%";
straightLine.style.width = '2px';
element.appendChild(straightLine);
}
straightLine.style.transform = slTrans;
}
element.addEventListener('mousemove', function(event) {
drawLines(event);
});
html, body{
height: 100%;
width: 100%;
margin: 0px;
}
.box {
height: 100%;
width: 100%;
background-color: white;
}
.straightLine {
z-index: 10;
position: fixed;
background-color: red;
}
<div class="box" id="box">
<h1>
Lorem
</h1>
<p>
dolor amet
</p>
</div>
You need to add top: 0 to straightLine class like below:
.straightLine {
z-index: 10;
position: fixed;
background-color: red;
top: 0;
}
Here is a working fiddle
You can append it as the first child of the element instead at the end.
var element = document.getElementById('box');
var drawLines = function(event) {
var x = event.pageX;
var straightLine = element.querySelector('.straightLine');
var slTrans = 'translate(' + x + 'px, 0px)';
if(!straightLine) {
straightLine = document.createElement('div');
straightLine.classList.add('straightLine');
straightLine.style.height = "100%";
straightLine.style.width = '2px';
element.insertBefore(straightLine, element.firstChild)
}
straightLine.style.transform = slTrans;
}
element.addEventListener('mousemove', function(event) {
drawLines(event);
});
html, body{
height: 100%;
width: 100%;
margin: 0px;
}
.box {
height: 100%;
width: 100%;
background-color: white;
}
.straightLine {
z-index: 10;
position: fixed;
background-color: red;
}
<div class="box" id="box">
<h1>
Lorem
</h1>
<p>
dolor amet
</p>
</div>
Related
I'm trying to change the colors of the divs from skyblue to yellow, when a specific div appears OR goes through the middle of the window. I have been building my own logic which works fine when I scroll the page up and down slowly. But it doesn't work when I scroll the page fast. I have inserted a button which takes the page to the fourth div (Box - 5) from the 100 divs. When the fourth div appears the background color does not switch, I have the keep scrolling up and down for my logic to change the fourth background color. The button is placed at the bottom of the page.
So I need help in making a better logic to changing the div's background color when the div is at or goes through the middle of the window, no matter the page is being scrolled fast or slow OR the page being
directly shifted to a specific div. Thanks
My index.html:
window.onbeforeunload = function() {
this.scrollTo(0, 0);
}
var content = document.getElementById("content"),
current = 0;
for (var y = 0; y < 100; y++) {
var box = document.createElement("div");
box.id = "box";
box.innerHTML = "Box - " + (y + 1);
content.appendChild(box);
}
content.children[current].style.backgroundColor = "yellow";
window.onscroll = function() {
if (this.oldScroll > this.scrollY) {
if (current >= 1) {
var previous_box = content.children[current - 1];
if ((this.scrollY + this.innerHeight / 2) < previous_box.offsetTop + previous_box.clientHeight) {
content.children[current].style.backgroundColor = "skyblue";
current--;
content.children[current].style.backgroundColor = "yellow";
}
}
} else {
if (current < 99) {
var next_box = content.children[current + 1];
if ((this.scrollY + this.innerHeight / 2) > next_box.offsetTop) {
content.children[current].style.backgroundColor = "skyblue";
current++;
content.children[current].style.backgroundColor = "yellow";
}
}
}
this.oldScroll = this.scrollY;
}
document.querySelector("button").onclick = function() {
var y = content.children[4].offsetTop - (content.children[4].clientHeight / 4);
window.scrollTo(0, y);
};
body {
margin: 0;
}
#navigation {
min-width: 620px;
background-color: blue;
width: 100%;
height: 50px;
z-index: 1;
position: fixed;
top: 0;
}
#box {
position: relative;
height: 75%;
width: 100%;
margin: 15% auto 15% auto;
color: black;
background-color: skyblue;
border: black 1px solid;
font-size: 50px;
text-align: center;
}
button {
margin: 0% auto 15% auto;
left: 50%;
}
<div id="navigation"></div>
<div id="content"></div>
<button>GO TO BOX 5</button>
window.onbeforeunload = function() {
this.scrollTo(0, 0);
}
var content = document.getElementById("content"),
current = 0;
for (var y = 0; y < 100; y++) {
var box = document.createElement("div");
box.id = "box";
box.innerHTML = "Box - " + (y + 1);
content.appendChild(box);
}
content.children[current].style.backgroundColor = "yellow";
window.onscroll = function() {
for(var i=0;i<content.children.length;i++){
var top = content.children[i]. getBoundingClientRect().top;
var height = top+content.children[i].clientHeight;
var halfWindow = window.innerHeight*0.5;
if(top<halfWindow&&height>halfWindow){
content.children[i].style.backgroundColor = "skyblue";
}
else{
content.children[i].style.backgroundColor = "yellow";
}
}
}
document.querySelector("button").onclick = function() {
var y = content.children[4].offsetTop - (content.children[4].clientHeight / 4);
window.scrollTo(0, y);
};
body {
margin: 0;
}
#navigation {
min-width: 620px;
background-color: blue;
width: 100%;
height: 50px;
z-index: 1;
position: fixed;
top: 0;
}
#box {
position: relative;
height: 75%;
width: 100%;
margin: 15% auto 15% auto;
color: black;
background-color: skyblue;
border: black 1px solid;
font-size: 50px;
text-align: center;
}
button {
margin: 0% auto 15% auto;
left: 50%;
}
<div id="navigation"></div>
<div id="content"></div>
<button>GO TO BOX 5</button>
I'm trying to make a gif img at the location my mouse clicked but for some reason the gif doesnt wanna go to the location i requested with style.top and style.left. Can someone help me?
here i try to create and place the gif img on a mouse click.
setInterval(checkCursor, 1);
function checkCursor(){
document.body.onclick = function(){
console.log(parseFloat(cursorX) + ', ' + cursorY);
var explo = document.createElement("img");
explo.src = "explosive.gif?" + new Date().getTime();
explo.style.position = "absolute";
explo.style.top = cursorY;
explo.style.left = cursorX;
explo.style.pointerEvents = "none";
document.body.appendChild(explo);
setTimeout(function(){explo.remove();}, 800);
}
}
here I search for the mouse location
var cursorX;
var cursorY;
document.onmousemove = function(e){
cursorX = e.pageX-100;
cursorY = e.pageY-100;
}
the -100 is to center the gif file on the mouse
this is all of the code:
<!DOCTYPE html>
<html>
<head>
<title> Menu </title>
<style>
#nav {
display: block;
position: fixed;
top: 0;
left: 0;
overflow-x: hidden;
transition: 0.5s;
background-color: grey;
color: black;
width: 0;
height: 100%;
}
nav a { text-decoration: none; cursor: pointer; display: block; color: white; padding-top: 5px; padding-bottom: 5px; padding-right: 50px; padding-left: 30px; }
nav a:hover { background-color: black; transition: 0.3s; }
#menu { transition: 0.3s; }
section { position: absolute; z-index: -1; width: 99%; height: 98%; }
#header {
background-color: red;
color: black;
text-align: center;
margin-left: 25%;
width: 50%;
}
</style>
</head>
<body bgcolor="black">
<video id="videoplayback" style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; opacity: 0.0;" src ="videoplayback.mp4" loop/></video>
<section id="body">
<nav id="nav">
<span id="menu">Menu</menu>
<a id="btncls"onclick="closeMenu()" style="float: right; padding: 5px; margin: 5px; font-size: 10px;">X</a>
<div style="top: 50px; position: fixed;" id="menu">
<a onclick="openIndex()">Home</a>
<a onclick="openClub()">Club</a>
Helenparkhurst
</div>
</nav>
<section id="index">
<header>
<button onclick="openMenu()">Open menu</button>
</header>
</section><section id="club">
<header>
<button onclick="openMenu()">Open menu</button>
</header><article>
<div id="choice" style="width: 100%; height: 100%;"><button onclick="join()">Join</button> | <button id="leave" onclick="leave()">Never</button></div>
<p id="header">
<span style="font-size: 32px">Welcome to the Megumin club !!!</span>
</p>
</article><footer>
</footer>
</section>
</section>
<script>
document.getElementById("menu").style.visibility = "hidden";
document.getElementById("club").style.visibility = "hidden";
function openIndex(){
document.getElementById("club").style.visibility = "hidden";
document.getElementById("index").style.visibility = "visible";
closeMenu();
}
function openClub(){
document.getElementById("index").style.visibility = "hidden";
document.getElementById("club").style.visibility = "visible";
closeMenu();
}
function openMenu(){
document.getElementById("nav").style.width = "17%";
document.getElementById("menu").style.opacity = "1.0";
document.getElementById("btncls").style.opacity = "1.0";
document.getElementById("menu").style.visibility = "visible";
}
function closeMenu(){
document.getElementById("nav").style.width = "0";
document.getElementById("menu").style.opacity = "0.0";
document.getElementById("btncls").style.opacity = "0.0";
setTimeout(function(){document.getElementById("menu").style.visibility = "hidden";}, 500);
}
var cursorX;
var cursorY;
document.onmousemove = function(e){
cursorX = e.pageX-100;
cursorY = e.pageY-100;
}
function join(){
var video = document.getElementById("videoplayback");
video.play();
document.getElementById('choice').remove();
setInterval(checkCursor, 1);
function checkCursor(){
document.body.onmouseup = function(){
console.log(parseFloat(cursorX) + ', ' + cursorY);
var explo = document.createElement("img");
explo.src = "explosive.gif?" + new Date().getTime();
explo.style.position = "absolute";
explo.style.top = cursorY;
explo.style.left = cursorX;
explo.style.pointerEvents = "none";
document.body.appendChild(explo);
setTimeout(function(){explo.remove();}, 800);
document.getElementById("videoplayback").style.opacity = "0.1";
setTimeout(function(){document.getElementById("videoplayback").style.opacity = "0.0";}, 1000);
}
}
}
function leave(){
document.getElementById("choice").style.position = "relative";
var rand1 = Math.floor(Math.random() * (600 - 30 + 1)) + 30;
document.getElementById("choice").style.top = rand1;
var rand2 = Math.floor(Math.random() * (1300 - 30 + 1)) + 30;
document.getElementById("choice").style.left = rand2;
console.log(rand1+', '+rand2);
}
</script>
</body>
</html>
You need to append px to the coordinates:
explo.style.top = cursorY + "px";
explo.style.left = cursorX + "px";
This looks like a CSS issue.
Add position: relative; to the body element.
body {
position: relative;
}
If your body element is empty, you'll also want to stretch it to the height of the window.
html,
body {
height: 100%;
}
I have five divs. Four of those divs you can click, which will run a function that moves the div you clicked on to the coordinate of the fifth div using div.offsetLeft and div.offsetTop. The first three divs all work fine, but if you click the right most div first, the transition effect isn't applied while moving to the coordinates. If you click any of the other divs first, and then the right most div, the transition will apply.
If you make it so there are only two or three divs, the problem still persists. (You must remove the corresponding id from the parties array, as well as the html element).
jsfiddle: https://jsfiddle.net/zjystr2u/
Apologies for the javascript in the html. Have never used jsfiddle, and couldn't figure out how to make it load the javascript after the html.
Something janky is going on when you getCurrentPosAll() changes position from the default static to absolute
You could run getCurrentPosAll() before changing the top and left to set their default values correctly.
var selected = document.getElementById("selected");
var selectedX = selected.offsetLeft;
var selectedY = selected.offsetTop;
parties = ['opt1', 'opt2', 'opt3', 'opt4'];
getCurrentPosAll(); // (NEW) Make sure their defaults are set.
function moreTest(e) {
var party = e.target
party.style.left = selectedX + "px";
party.style.top = selectedY + "px";
}
function getCurrentPosAll() {
for (var idx = 0; idx < parties.length; idx++) {
var currentDiv = document.getElementById(parties[idx]);
var x = currentDiv.offsetLeft;
var y = currentDiv.offsetTop;
currentDiv.style.left = x + "px";
currentDiv.style.top = y + "px";
}
for (var idx = 0; idx < parties.length; idx++) {
var currentDiv = document.getElementById(parties[idx]);
currentDiv.style.position = "absolute";
}
}
.wrapper {
display: flex;
justify-content: space-around;
width: 75%;
margin: 0 auto;
}
.selected {
width: 100px;
height: 150px;
position: absolute;
left: 0;
right: 0;
margin-left: auto;
margin-right: auto;
background-color: black;
opacity: 0.6;
z-index: 1;
}
.opt {
width: 100px;
height: 150px;
cursor: pointer;
transition: top 0.7s, left 0.7s;
}
.opt1 {
background-color: red;
}
.opt2 {
background-color: blue;
}
.opt3 {
background-color: orange;
}
.opt4 {
background-color: green;
}
<div class="wrapper">
<div class="selected" id="selected"></div>
<div class="opt opt1" id="opt1" onclick="moreTest(event)"></div>
<div class="opt opt2" id="opt2" onclick="moreTest(event)"></div>
<div class="opt opt3" id="opt3" onclick="moreTest(event)"></div>
<div class="opt opt4" id="opt4" onclick="moreTest(event)"></div>
</div>
I'm not sure why it behaves like this. I figure it has to do with how and when the browser calculates the initial value for the transition. where last elements CSS changes get batched into 1 update.
therefor it will immediately receive the updated top and left values, whereas the other elements will receive 2 updates, one with the default top and left and then one with the updated values. causing their transition to work properly.
Most likely because the the last elements CSS is changed, their css updates are applied in 2 updates instead of 1.
var selected = document.getElementById("selected");
var selectedX = selected.offsetLeft;
var selectedY = selected.offsetTop;
parties = ['opt1', 'opt2', 'opt3', 'opt4', 'opt5','opt6'];
function moreTest(e) {
var party = e.target
getCurrentPosAll();
party.style.left = selectedX + "px";
party.style.top = selectedY + "px";
}
function getCurrentPosAll() {
for (var idx = 0; idx < parties.length; idx++) {
var currentDiv = document.getElementById(parties[idx]);
var x = currentDiv.offsetLeft;
var y = currentDiv.offsetTop;
currentDiv.style.left = x + "px";
currentDiv.style.top = y + "px";
}
for (var idx = 0; idx < parties.length; idx++) {
var currentDiv = document.getElementById(parties[idx]);
currentDiv.style.position = "absolute";
}
}
.wrapper {
display: flex;
justify-content: space-around;
width: 100%;
margin: 0 auto;
}
.selected {
width: 100px;
height: 150px;
position: absolute;
left: 0;
right: 0;
margin-left: auto;
margin-right: auto;
background-color: black;
opacity: 0.6;
z-index: 1;
}
.opt {
width: 100px;
height: 150px;
cursor: pointer;
transition: 0.7s;
}
.opt1 {
background-color: red;
}
.opt2 {
background-color: blue;
}
.opt3 {
background-color: orange;
}
.opt4 {
background-color: green;
}
.opt5 {
background-color: violet;
}
.opt6 {
background-color: black;
}
<div class="wrapper">
<div class="selected" id="selected"></div>
<div class="opt opt1" id="opt1" onclick="moreTest(event)"></div>
<div class="opt opt2" id="opt2" onclick="moreTest(event)"></div>
<div class="opt opt3" id="opt3" onclick="moreTest(event)"></div>
<div class="opt opt4" id="opt4" onclick="moreTest(event)"></div>
<div class="opt opt5" id="opt5" onclick="moreTest(event)"></div>
<div class="opt opt6" id="opt6" onclick="moreTest(event)"></div>
</div>
I have been challenged with a website that requires me to make two images race at random across the screen to a finish line. I am required to make this happen using JavaScript. Unfortunately I have ran into some trouble here making this happen.
I have the script that allows a div container and an object "animate" (which is a small square) to move across the screen to the right as I am supposed to do. My question comes into play when trying to do this to two different images.
The goal is to have the animation I have created to apply to the images, I cannot figure out how to apply the functions to the images already placed on the page to make it seem as if they are racing on random intervals across the page to the finish line.
I understand the concept of the animation and the JavaScript behind it, I just dont understand how to make it apply to an image, and more than 1 image at that.
Please advise.
Here is my code that I am using: you can see that I left my demo animation on the page, and the two images I am looking to apply it to.
function myMove()
{
var elem = document.getElementById("animate");
var pos = 0;
var id = setInterval(frame, 5);
function frame()
{
if (pos == 350)
{
clearInterval(id);
}
else
{
pos++;
elem.style.left = pos + 'px';
}
}
}
<div id="traffic-light">
<div id="stopLight" class="bulb"></div>
<div id="yeildLight" class="bulb"></div>
<div id="goLight" class="bulb"></div>
</div>
<style>
body {
overflow: hidden;
}
#bluefish {
position: absolute;
top: 31pc;
width: 17pc;
left: -.5pc;
}
#turtle {
position: absolute;
width: 15pc;
top: 20pc;
}
body {
background-image: url("http://www.hpud.org/wp-content/uploads/2015/08/WaterBackground2.jpg")
}
.finishline {
position: absolute;
right: -12pc;
top: 18pc;
}
#traffic-light {
height: 10pc;
width: 4pc;
background-color: #333;
border-radius: 20pc;
position: absolute;
}
.bulb {
height: 2pc;
width: 2pc;
background-color: #111;
border-radius: 50%;
margin: 15px auto;
transition: background 500ms;
}
#container {
width: 400px;
height: 400px;
position: relative;
background: yellow;
}
#animate {
width: 50px;
height: 50px;
position: absolute;
background: red;
}
</style>
<img id="bluefish" src="http://clipartist.net/openclipart.org/2013/July/Blue_Fish_Goldfish.png">
<img id="turtle" src="http://www.clipartkid.com/images/386/turtle-free-stock-photo-illustration-of-a-green-sea-turtle-uPgZrm-clipart.png">
<img src="https://t1.rbxcdn.com/877010da8ce131dfcb3fa6a9b07fea89" class="finishline">
<p>
<button onclick="myMove()">Click Me</button>
</p>
<div id="container">
<div id="animate"></div>
</div>
Try this one:
function myMove()
{
var elemBluefish = document.getElementById("bluefish");
var elemBluefishWin = document.getElementById("bluefishwin");
var elemTurtle = document.getElementById("turtle");
var elemTurtleWin = document.getElementById("turtlewin");
var posBluefish = 0;
var posTurtle = 0;
var hasWinner = false;
elemBluefishWin.style.display = 'none';
elemTurtleWin.style.display = 'none';
var id = setInterval(frame, 5);
function frame()
{
if(posBluefish >= 350 && posTurtle >= 350)
{
clearInterval(id);
return;
}
if(posBluefish < 350)
{
posBluefish += Math.round(Math.random()*10);
if(posBluefish >= 350)
{
posBluefish = 350;
if(!hasWinner){
hasWinner = true;
elemBluefishWin.style.display = 'unset';
}
}
elemBluefish.style.left = posBluefish + 'px';
}
if(posTurtle < 350)
{
posTurtle += Math.round(Math.random()*10);
if(posTurtle >= 350)
{
posTurtle = 350;
if(!hasWinner){
hasWinner = true;
elemTurtleWin.style.display = 'unset';
}
}
elemTurtle.style.left = posTurtle + 'px';
}
}
}
<div id="traffic-light">
<div id="stopLight" class="bulb"></div>
<div id="yeildLight" class="bulb"></div>
<div id="goLight" class="bulb"></div>
</div>
<style>
body {
overflow: hidden;
}
#bluefish {
position: absolute;
top: 31pc;
width: 17pc;
left: -.5pc;
}
#turtle {
position: absolute;
width: 15pc;
top: 20pc;
}
#bluefishwin {
position: absolute;
right: 1pc;
top: 31pc;
display: none;
}
#turtlewin {
position: absolute;
right: 1pc;
top: 20pc;
display: none;
}
body {
background-image: url("http://www.hpud.org/wp-content/uploads/2015/08/WaterBackground2.jpg")
}
.finishline {
position: absolute;
right: -12pc;
top: 18pc;
}
#traffic-light {
height: 10pc;
width: 4pc;
background-color: #333;
border-radius: 20pc;
position: absolute;
}
.bulb {
height: 2pc;
width: 2pc;
background-color: #111;
border-radius: 50%;
margin: 15px auto;
transition: background 500ms;
}
/*#container {
width: 400px;
height: 400px;
position: relative;
background: yellow;
}
#animate {
width: 50px;
height: 50px;
position: absolute;
background: red;
}*/
</style>
<img id="bluefish" src="http://clipartist.net/openclipart.org/2013/July/Blue_Fish_Goldfish.png">
<img id="turtle" src="http://www.clipartkid.com/images/386/turtle-free-stock-photo-illustration-of-a-green-sea-turtle-uPgZrm-clipart.png">
<img src="https://t1.rbxcdn.com/877010da8ce131dfcb3fa6a9b07fea89" class="finishline">
<img id="bluefishwin" src="http://a.dryicons.com/images/icon_sets/coquette_part_3_icons_set/png/128x128/prize_winner.png">
<img id="turtlewin" src="http://a.dryicons.com/images/icon_sets/coquette_part_3_icons_set/png/128x128/prize_winner.png">
<p>
<button onclick="myMove()">Click Me</button>
</p>
<div id="container">
<div id="animate"></div>
</div>
It gets an element for each image and adds every 5ms a random amount of pixels (between 0 and 9) to each pos of image.
If both "racers" reached the target (350px) the interval is cleared and the race is over.
The winner gets an image displayed at the finish line.
an example:
function startRace() {
animateRacer("player1", true);
animateRacer("player2", true);
}
function animateRacer(playerId, reset) {
var elem = document.getElementById(playerId);
var pos = parseInt(elem.style.left, 10);
if (isNaN(pos) || reset) {
pos = 0;
}
//console.log(playerId + ': ' + pos);
if (pos < 450) {
pos += randStep(3);
elem.style.left = pos + 'px';
setTimeout('animateRacer("' + playerId + '")', randStep(5));
}
}
function randStep(max) {
var min = 1;
return Math.floor(Math.random() * (max - min)) + min;
}
body {
overflow: hidden;
}
#container {
width: 500px;
height: 160px;
position: relative;
background-color: yellow;
}
.player {
width: 50px;
height: 50px;
background-color: gray;
position: relative;
}
#player1 {
background-color: red;
top: 20px;
}
#player2 {
background-color: blue;
top: 40px;
}
<p>
<button onclick="startRace()">Start Race</button>
</p>
<div id="container">
<div id="player1" class="player"></div>
<div id="player2" class="player"></div>
</div>
function mover(obj) {
this.obj=obj;
this.pos = 0;
this.id = setInterval(this.frame, 5);
}
mover.prototype.frame=function() {
if (this.pos == 350) {
clearInterval(this.id);
} else {
this.pos++;
this.obj.style.left = this.pos + 'px';
}
}
}
Simply do:
img1=new mover(document.getElementById("pic1"));
You can repeat this with every image and you could store them into an array:
images=[];
function letsmove(){
images.push(new mover(someid));
...
}
And you can do this with all images on the site:
images=[];
function letsmove(){
domimages=document.getElementsByTagName("img");
domimages.forEach(function(img){
images.push(new mover(img));
});
}
}
See JS OOP and JS Prototyping for more explanation
This question already has answers here:
Why don't flex items shrink past content size?
(5 answers)
Closed 3 years ago.
I implemented my own split-pane with HTML/JS/CSS Flexbox.
I'm having trouble with the splitter in the following case- one of the panels has a fixed size (in px), and the other one is set to grow (flex-grow: 1).
In case the other panel has children with size, it won't scroll to the end. It gets stuck at the size of the children.
Can this be fixed with CSS on the split-pane panels but not on the children?
It's very important for me to use flex as I want to maintain responsiveness of my application, and want to avoid fixed sizes wherever I can.
This is a JSFiddle sample
of my question.
Code snippet given below. Thanks!
function startDrag() {
glass.style = 'display: block;';
glass.addEventListener('mousemove', drag, false);
}
function endDrag() {
glass.removeEventListener('mousemove', drag, false);
glass.style = '';
}
function drag(event) {
var splitter = getSplitter();
var panel = document.getElementById('c2');
var currentWidth = panel.offsetWidth;
var currentLeft = panel.offsetLeft;
panel.style.width = (currentWidth - (event.clientX - currentLeft)) + "px";
}
function getSplitter() {
return document.getElementById('splitter');
}
var con = document.getElementById('container');
var splitter = document.createElement('div');
var glass = document.getElementById('glass');
splitter.className = 'splitter';
splitter.id = 'splitter';
con.insertBefore(splitter, con.lastElementChild);
splitter.addEventListener('mousedown', startDrag, false);
glass.addEventListener('mouseup', endDrag, false);
.container {
display: flex;
border: 1px solid;
width: 500px;
height: 300px;
position: absolute;
}
.c1 {
background-color: blue;
flex: 1;
height: 100%;
}
.c2 {
background-color: green;
width: 150px;
}
.splitter {
width: 20px;
cursor: col-resize;
}
.glass {
height: 100%;
width: 100%;
cursor: col-resize;
display: none;
position: absolute;
}
.grandchild {
background-color: red;
width: 50px;
height: 50px;
}
<div id="container" class="container">
<div id="glass" class="glass"></div>
<div class="c1">
<div class="grandchild"></div>
</div>
<div id="c2" class="c2"></div>
</div>
In case the other panel has children with size, it won't scroll to the end. It gets stuck at the size of the children.
This is because an initial setting of a flex container is min-width: auto on the flex items. This means that a flex item, by default, cannot be smaller than the size of its content.
Can this be fixed with CSS on the split-pane panels but not on the children?
Yes. Override the default with min-width: 0 or with any overflow other than visible:
.c1 {
background-color: blue;
flex: 1;
height: 100%;
overflow: hidden; /* or min-width: 0 */
}
revised fiddle
function startDrag() {
glass.style = 'display: block;';
glass.addEventListener('mousemove', drag, false);
}
function endDrag() {
glass.removeEventListener('mousemove', drag, false);
glass.style = '';
}
function drag(event) {
var splitter = getSplitter();
var panel = document.getElementById('c2');
var currentWidth = panel.offsetWidth;
var currentLeft = panel.offsetLeft;
panel.style.width = (currentWidth - (event.clientX - currentLeft)) + "px";
}
function getSplitter() {
return document.getElementById('splitter');
}
var con = document.getElementById('container');
var splitter = document.createElement('div');
var glass = document.getElementById('glass');
splitter.className = 'splitter';
splitter.id = 'splitter';
con.insertBefore(splitter, con.lastElementChild);
splitter.addEventListener('mousedown', startDrag, false);
glass.addEventListener('mouseup', endDrag, false);
.container {
display: flex;
border: 1px solid;
width: 500px;
height: 300px;
position: absolute;
}
.c1 {
background-color: blue;
flex: 1;
height: 100%;
overflow: hidden;
}
.c2 {
background-color: green;
width: 150px;
}
.splitter {
width: 20px;
cursor: col-resize;
}
.glass {
height: 100%;
width: 100%;
cursor: col-resize;
display: none;
position: absolute;
}
.grandchild {
background-color: red;
width: 50px;
height: 50px;
}
<div id="container" class="container">
<div id="glass" class="glass"></div>
<div class="c1">
<div class="grandchild"></div>
</div>
<div id="c2" class="c2"></div>
</div>
It gets stuck at the size of the children
This is expected behavior when using a flexbox. I guess if you want to scroll to the end then you can use position: absolute for the grandchild relative to c1:
.grandchild {
background-color: red;
width: 50px;
height: 50px;
position: absolute;
top: 0;
left: 0;
}
Give overflow: hidden to c1 too:
.c1 {
background-color: blue;
flex: 1;
height: 100%;
position: relative;
overflow: hidden;
}
Cheers!
function startDrag() {
glass.style = 'display: block;';
glass.addEventListener('mousemove', drag, false);
}
function endDrag() {
glass.removeEventListener('mousemove', drag, false);
glass.style = '';
}
function drag(event) {
var splitter = getSplitter();
var panel = document.getElementById('c2');
var currentWidth = panel.offsetWidth;
var currentLeft = panel.offsetLeft;
panel.style.width = (currentWidth - (event.clientX - currentLeft)) + "px";
}
function getSplitter() {
return document.getElementById('splitter');
}
var con = document.getElementById('container');
var splitter = document.createElement('div');
var glass = document.getElementById('glass');
splitter.className = 'splitter';
splitter.id = 'splitter';
con.insertBefore(splitter, con.lastElementChild);
splitter.addEventListener('mousedown', startDrag, false);
glass.addEventListener('mouseup', endDrag, false);
.container {
display: flex;
border: 1px solid;
width: 500px;
height: 300px;
position: absolute;
}
.c1 {
background-color: blue;
flex: 1;
height: 100%;
position: relative;
overflow: hidden;
}
.c2 {
background-color: green;
width: 150px;
}
.splitter {
width: 20px;
cursor: col-resize;
}
.glass {
height: 100%;
width: 100%;
cursor: col-resize;
display: none;
position: absolute;
}
.grandchild {
background-color: red;
width: 50px;
height: 50px;
position: absolute;
top: 0;
left: 0;
}
<div id="container" class="container">
<div id="glass" class="glass"></div>
<div class="c1">
<div class="grandchild"></div>
</div>
<div id="c2" class="c2"></div>
</div>
Solution:
So I guess your strategy should be to use an absolute grandchild that fills the whole side-panel, and then put the content inside like:
<div class="grandchild">
<div class="content"></div>
</div>
and change these styles:
.grandchild {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.grandchild .content{
background-color: red;
width: 50px;
height: 50px;
}
Example below:
function startDrag() {
glass.style = 'display: block;';
glass.addEventListener('mousemove', drag, false);
}
function endDrag() {
glass.removeEventListener('mousemove', drag, false);
glass.style = '';
}
function drag(event) {
var splitter = getSplitter();
var panel = document.getElementById('c2');
var currentWidth = panel.offsetWidth;
var currentLeft = panel.offsetLeft;
panel.style.width = (currentWidth - (event.clientX - currentLeft)) + "px";
}
function getSplitter() {
return document.getElementById('splitter');
}
var con = document.getElementById('container');
var splitter = document.createElement('div');
var glass = document.getElementById('glass');
splitter.className = 'splitter';
splitter.id = 'splitter';
con.insertBefore(splitter, con.lastElementChild);
splitter.addEventListener('mousedown', startDrag, false);
glass.addEventListener('mouseup', endDrag, false);
.container {
display: flex;
border: 1px solid;
width: 500px;
height: 300px;
position: absolute;
}
.c1 {
background-color: blue;
flex: 1;
height: 100%;
position: relative;
overflow: hidden;
}
.c2 {
background-color: green;
width: 150px;
}
.splitter {
width: 20px;
cursor: col-resize;
}
.glass {
height: 100%;
width: 100%;
cursor: col-resize;
display: none;
position: absolute;
}
.grandchild {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.grandchild .content{
background-color: red;
width: 50px;
height: 50px;
}
<div id="container" class="container">
<div id="glass" class="glass"></div>
<div class="c1">
<div class="grandchild">
<div class="content"></div>
</div>
</div>
<div id="c2" class="c2"></div>
</div>