Vytalyi
Vytalyi

Reputation: 1695

Left/Top overflow with scrollbars

I am positioning my element inside container using transform: tranxlate(x, y) css property.

When I move element to right or bottom - scrollbars appeared because container has overflow: auto;. However if I move element to left or top - obviously scrollbars doesn't appear because overflow doesn't work that way.

Now I'm looking for some minimalistic approach with pure html/js/css to be able to scroll container keeping in mind that inner content may be moved randomly to any sides.

In short, I want scrollbar to appear if the yellow block goes beyond left edge, the same way it appears when it goes to right edge?

Here is a Codepen example which shows the problem.

var btns = document.querySelectorAll('button');
var inner = document.querySelector('.inner');
var offset = 0;

btns[0].addEventListener('click', function() {
  offset -= 25;
  inner.style.transform = `translate(${offset}px, 0px)`;
});

btns[1].addEventListener('click', function() {
  offset += 25;
  inner.style.transform = `translate(${offset}px, 0px)`;
});
button {
  margin: 0 auto;
  display: block;
}

.outer {
  outline: 1px dashed black;
  margin: 0 auto;
  width: 200px;
  height: 200px;
  overflow: auto;
}

.inner {
  width: 100px;
  height: 100px;
  background: yellow;
}
<button>Move Left</button>
<button>Move Right</button>

<div class="outer">
  <div class="inner"></div>
</div>

scrollbar appears scrollbar doesn't appears

Upvotes: 0

Views: 911

Answers (3)

Capitex
Capitex

Reputation: 133

Maybe this help... consider that the offset scroll cannot be negative; you can only go from 0 to infinite(I think lol); then, you can move your element through left and top negative values but it does not enable you to scroll to. So, You can augment the width and height based on the user requirement and scroll the same value to the inverse direction of the user move it will show the effect that the scroll able to go these posions that right now is unavailable (negative scrolls). When you go back, you have to reverse the augment and when the augment is null then you move your element as need.

I expect that my explanation was successful; excuse me for my english...

"use strcit";

var blank, container, yblock;

function bLeft() {
  if (yblock.offsetLeft <= 0) {
    blank.style.width = blank.offsetWidth + 16 + 'px';
    container.scrollTo(container.scrollLeft + 16, container.scrollTop);
  } else {
    yblock.style.left = `${yblock.offsetLeft - 16}px`;
  }
}

function bRight() {
  if (blank.offsetWidth > container.offsetWidth) {
    blank.style.width = blank.offsetWidth - 16 + 'px';
  } else {
    yblock.style.left = `${yblock.offsetLeft + 16}px`;
  }
}

function bUp() {
  if (yblock.offsetTop <= 0) {
    blank.style.height = blank.offsetHeight + 16 + 'px';
    container.scrollTo(container.scrollLeft, container.scrollTop + 16);
  } else {
    yblock.style.top = `${yblock.offsetTop - 16}px`;
  }
}

function bDown() {
  if (blank.offsetHeight > container.offsetHeight) {
    blank.style.height = blank.offsetHeight - 16 + 'px';
  } else {
    yblock.style.top = `${yblock.offsetTop + 16}px`;
  }
}

window.addEventListener("load", function() {
  blank = document.getElementById("blank");
  container = document.getElementById("container");
  yblock = document.getElementById("y-block");
  document.getElementById("left").addEventListener("click", bLeft);
  document.getElementById("right").addEventListener("click", bRight);
  document.getElementById("up").addEventListener("click", bUp);
  document.getElementById("down").addEventListener("click", bDown);
});
.container {
  position: relative;
  width: 20em;
  height: 20em;
  border: dashed 0.2em black;
  overflow: auto;
}

.blank {
  position: absolute;
  width: 100%;
  height: 100%;
}

.y-block {
  position: absolute;
  background-color: yellow;
  width: 3em;
  height: 3em;
}
<div class="container" id="container">
  <div class="blank" id="blank">
    <div class="y-block" id="y-block"></div>
  </div>
</div>
<div>
  <input type="button" value="left" id="left">
  <input type="button" value="right" id="right">
  <input type="button" value="down" id="down">
  <input type="button" value="up" id="up">
</div>

Upvotes: 3

Pedro Figueiredo
Pedro Figueiredo

Reputation: 2452

Here is a quick example of how you can achieve container horizontal scrolling, while moving the yellow box.

 var btns = document.querySelectorAll('button');
        var inner = document.querySelector('.inner');
        var outer = document.querySelector('.outer');
        var offset = 0;
        
        btns[0].addEventListener('click', function() {
            offset -= 25;
            inner.style.transform = `translate(${offset}px, 0px)`;
            outer.scroll({
                left: outer.scrollLeft -= 25
            });
        });
        
        btns[1].addEventListener('click', function() {
            offset += 25;
            inner.style.transform = `translate(${offset}px, 0px)`;
            outer.scroll({
                left: outer.scrollLeft += 25
            });
        });
button {
    margin: 0 auto;
    display: block;
  }
  
  .outer {
    outline: 1px dashed black;
    margin: 0 auto;
    width: 200px;
    height: 200px;
    overflow: auto;
  }
  
  .inner {
    width: 100px;
    height: 100px;
    background: yellow;
  }
    <button>Move Left</button>
    <button>Move Right</button>
    
    <div class="outer">
        <div class="inner"></div>
    </div>

Upvotes: -1

DAustin
DAustin

Reputation: 471

Instead of moving the object left or up, increase the height/width of the parent container when those properties go below 0, and scroll the window by the offset.

This will give the appearance of the object moving off canvas whilst giving you scrollbars, however the object never actually goes beyond (0,0)

Upvotes: 1

Related Questions