Changing CSS parameters based on scroll position - javascript

In the example below, I have two invisible buttons – button in the right half, on click, horizontally scrolls to the next section, and the button in the left half to the previous section. Buttons show left and right arrow cursors when user hovers over them for displaying scroll direction.
I would like to toggle the cursor of goToPreviousSectionButton to default when scrollPosition === 0, and same for goToNextSectionButton when scrollPosition === maxScrollPosition.
To put it plainly: when you run the code snippet, hover your mouse cursor to the left of number 1. You can see that it’s a left arrow cursor now. I would like it to be a default cursor, since you can’t go left because you’re at the beginning. Same when you reach to the number 3, but this time for the right arrow, since you can’t go any further, so it’s pointless for the right arrow to be shown.
I’m having trouble getting this to work. Any help would be greatly appreciated.
let scrollPosition = 0
const maxScrollPosition = document.body.scrollWidth - window.innerWidth
const goToPreviousSectionButton = document.createElement("button")
const goToNextSectionButton = document.createElement("button")
document.body.appendChild(goToPreviousSectionButton)
document.body.appendChild(goToNextSectionButton)
if (scrollPosition === 0) {
// If scroll position is at the beginning
}
if (scrollPosition === maxScrollPosition) {
// If scroll position at the end
}
goToPreviousSectionButton.addEventListener("click", () => {
window.scrollBy(-window.innerWidth, 0)
})
goToNextSectionButton.addEventListener("click", () => {
window.scrollBy(window.innerWidth, 0)
})
* {
margin: 0;
padding: 0
}
html { height: 100% }
html, body, main {
display: flex;
flex-grow: 1
}
section {
display: grid;
place-items: center;
flex: 1 0 100%
}
section:nth-of-type(1) { background: orange }
section:nth-of-type(2) { background: limeGreen }
section:nth-of-type(3) { background: royalBlue }
h2 { color: white }
button {
background: transparent;
position: fixed;
top: 0;
width: 50%;
height: 100%;
border: none;
touch-action: manipulation;
-webkit-tap-highlight-color: transparent
}
:focus { outline: none }
button:nth-of-type(1) { /* Left button */
left: 0;
cursor: w-resize
}
button:nth-of-type(2) { /* Right button */
right: 0;
cursor: e-resize
}
<main>
<section>
<h2>1</h2>
</section>
<section>
<h2>2</h2>
</section>
<section>
<h2>3</h2>
</section>
</main>

One idea is to add extra elements using pseudo-element that you will cover your invisible buttons and disable the action on them:
const goToPreviousSectionButton = document.createElement("button")
const goToNextSectionButton = document.createElement("button")
document.body.appendChild(goToPreviousSectionButton)
document.body.appendChild(goToNextSectionButton)
goToPreviousSectionButton.addEventListener("click", () => {
window.scrollBy(-window.innerWidth, 0)
})
goToNextSectionButton.addEventListener("click", () => {
window.scrollBy(window.innerWidth, 0)
})
* {
margin: 0;
padding: 0
}
html,body { height: 100% }
body, main {
display: flex;
flex-grow: 1
}
section {
display: grid;
place-items: center;
flex: 1 0 100%
}
section:nth-of-type(1) { background: orange }
section:nth-of-type(2) { background: limeGreen }
section:nth-of-type(3) { background: royalBlue }
h2 { color: white }
button {
background: transparent;
position: fixed;
top: 0;
width: 50%;
height: 100%;
border: none;
touch-action: manipulation;
-webkit-tap-highlight-color: transparent
}
:focus { outline: none }
button:nth-of-type(1) { /* Left button */
left: 0;
cursor: w-resize
}
button:nth-of-type(2) { /* Right button */
right: 0;
cursor: e-resize
}
/* Added */
main:before,
main:after{
content:"";
z-index:9;
position:relative;
flex: 1 0 50%;
}
main:before {
margin-right:-50%;
}
main:after {
margin-left:-50%;
}
/**/
<main>
<section>
<h2>1</h2>
</section>
<section>
<h2>2</h2>
</section>
<section>
<h2>3</h2>
</section>
</main>

if (scrollPosition === 0) {
goToPreviousSectionButton.classList.add('default')
}
if (scrollPosition === maxScrollPosition) {
goToPreviousSectionButton.classList.add('default')
}
css:
.default {
cursor: default
}

Related

Move DIV using CSS Grid

I created a CSS Grid layout with global variables:
#app{
--width-l: 0.5fr;
--width-c: 0.5fr;
}
So I have a bar in the middle of my screen. On the other hand, in JavaScript I have two events that observe if the mouse is pressed (mousedown) and in motion (mousemove) that move the div. It has a problem, the movement is above the mouse position and at the height of the #app. So it works in parts, when I'm near the top, the div#bar doesn't go up anymore, and near the bottom, the same thing happens but at a greater distance.
I'm looking for a solution to make the transition smoothly, using the grid positions.
This is the code I created to try:
var split = document.querySelector(".split");
var app = document.querySelector("#app");
var position = app.getBoundingClientRect();
var isMouseMove = false;
split.addEventListener("mousedown", (e) => {
isMouseMove = true;
this.addEventListener("mouseup", (e) => {
isMouseMove = false;
});
});
split.addEventListener("mousemove", (e) => {
if (isMouseMove) {
let fullSize = app.offsetHeight;
let average = (100 * (e.y - position.top)) / fullSize;
let up = (average / 100).toFixed(4);
let down = (1 - average / 100).toFixed(4);
app.style.setProperty("--width-l", `${up}fr`);
app.style.setProperty("--width-c", `${down}fr`);
}
});
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
header {
background: aquamarine;
height: 50px;
}
footer {
background: aqua;
height: 50px;
}
#app {
--width-l: 0.5fr;
--width-c: 0.5fr;
height: calc(100vh - 100px);
display: grid;
grid-template: "aside up" var(--width-l) "aside split" 50px "aside down" var(
--width-c
) / 100px auto;
}
#app .aside {
grid-area: aside;
background: blue;
}
#app .up {
grid-area: up;
background: yellow;
resize: horizontal;
}
#app .split {
grid-area: split;
background: floralwhite;
display: flex;
justify-content: center;
align-items: center;
font-weight: 900;
color: tomato;
user-select: none;
}
#app .down {
grid-area: down;
background: green;
}
#app .split:active {
cursor: move;
}
<header></header>
<div id="app">
<div class="aside"></div>
<div class="up"></div>
<div class="split"> CLICK AND MOVE </div>
<div class="down"></div>
</div>
<footer></footer>

Convert vertical scrolling Website to a functional horizontal scrolling website

The current code is a responsive vertical webpage with a vertical navigation
I want to convert It to a responsive horizontal webpage with left-right arrow control.
Instances
When scrolling up or down with the mouse, the website should go left when scrolling up and right when scrolling down.
When right or left arrow keys are pressed the website should scroll right or left depending on the key pressed.
My HTML code
<body>
<div class="section" id="home" data-label="Home">Home</div>
<div class="section" id="about" data-label="About Me">About</div>
<div class="section" id="contact" data-label="Say Hi">Contact</div>
<script>
function activateNavigation() {
const sections = document.querySelectorAll(".section");
const navContainer = document.createElement("nav");
const navItems = Array.from(sections).map((section) => {
return `
<div class="nav-item" data-for-section="${section.id}">
<span class="nav-label">${section.dataset.label}</span>
</div>
`;
});
navContainer.classList.add("nav");
navContainer.innerHTML = navItems.join("");
const observer = new IntersectionObserver(
(entries) => {
document.querySelectorAll(".nav-link").forEach((navLink) => {
navLink.classList.remove("nav-link-selected");
});
const visibleSection = entries.filter((entry) => entry.isIntersecting)[0];
document
.querySelector(
`.nav-item[data-for-section="${visibleSection.target.id}"] .nav-link`
)
.classList.add("nav-link-selected");
},
{ threshold: 0.5 }
);
sections.forEach((section) => observer.observe(section));
document.body.appendChild(navContainer);
}
activateNavigation();
</script>
</body>
My CSS
.section{
height: 100vh;
.nav{
--nav-gap : 15px;
padding: var(--nav-gap);
position: fixed;
right: 0;
top:50%;
transform: translateY(-50%);
}
.nav-item{
align-items: center;
display: flex;
flex-direction: row-reverse;
margin-bottom: var(--nav-gap);
}
.nav-link:hover ~ .nav-label{
opacity: 1;
}
.nav-label{
color: black;
font-weight: bold;
opacity: 0;
transition: opacity 0.1s;
}
.nav-link{
background: rgba(0,0,0,0.5);
border-radius: 50%;
height: var(--nav-gap);
margin-left: var(--nav-gap);
width: var(--nav-gap);
transition: transform 0.3s;
}
.nav-link-selected{
background: #000000;
transform: scale(1.4);
}
The idea is to make a container div which will contain all the sections, and then make it display flex to handle sections as rows not columns.
Make sure to that the width and height of the container match the body's.
and then disable overflow-x on the container.
Now all we have to do is to get the current scroll Y position and transform it into a X one.
Since the browser does the job for us, we don't really need to calculate anything... just get paste the same Y position as an X one and it will work like a charm.
There is the script and explanations... All you have to do next is to challenge yourself to get the proper height of the website and use it as min-height for the body
A quick hint on your challenge: The height you'll need could be equal to the width of your container.
Good luck!
Example with your layout: jsfiddle link
const container = document.querySelector(".container")
window.addEventListener("scroll", horizontalScroll)
window.addEventListener("keydown", horizontalScroll)
function horizontalScroll(e, keyboadScrollingSpeed=30) {
let y = window.scrollY || window.pageYOffset
if( e.type == "keydown" ) {
if( (e.key == 'ArrowLeft' || e.key == 'ArrowRight') ) {
const direction = e.key == 'ArrowLeft' ? -1 : 1
y += keyboadScrollingSpeed * direction
window.scrollTo({
top: y
})
}
else e.preventDefault()
}
container.scrollTo({
left: y,
})
}
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
min-height: 300vh;
}
.container {
background-color: yellow;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
position: sticky;
top: 0;
left: 0;
width: 100vw;
overflow-x: hidden;
}
.section {
display: block;
flex: 1;
max-width: 100vw;
min-width: 100vw;
height: 100vh;
background-color: green;
}
<div class="container">
<div class="section">
<div class="content">
<h1>Section 1</h1>
<p>This is some text</p>
</div>
</div>
<div class="section">
<div class="content">
<h1>Section 2</h1>
<p>This is some text</p>
</div>
</div>
</div>

Horizontal scroll areas with buttons and gradients

This is my code so far:
// Show and hide gradients
$(document).ready(function() {
$(".scroll-area").each(function(index) {
if ($(this)[0].scrollWidth <= $(this)[0].clientWidth) {
$(this).closest(".container").find(".left").css("display", "none");
$(this).closest(".container").find(".right").css("display", "none");
} else {
$(this).scroll(function() {
if ($(this)[0].scrollWidth > $(this)[0].clientWidth) {
if ($(this).scrollLeft() > 0) {
$(this).closest(".container").find(".left").css("display", "block");
}
if ($(this).scrollLeft() == 0) {
$(this).closest(".container").find(".left").css("display", "none");
}
var fullWidth = $(this)[0].scrollWidth - $(this)[0].offsetWidth - 1;
if ($(this).scrollLeft() >= fullWidth) {
$(this).closest(".container").find(".right").css("display", "none");
}
if ($(this).scrollLeft() < fullWidth) {
$(this).closest(".container").find(".right").css("display", "block");
}
}
});
}
});
});
// Scroll buttons
let interval;
$('.scroll-btn').on('mousedown', ({
target
}) => {
const type = $(target).attr('id');
interval = setInterval(() => {
var x = $('#a').scrollLeft();
$('#a').scrollLeft(type === 'left-arrow' ? x - 10 : x + 10);
}, 50);
});
$('.scroll-btn').on('mouseup', () => clearInterval(interval));
* {
margin: 0;
padding: 0;
font-family: sans-serif;
font-size: 16px;
}
.container {
width: 550px;
height: 80px;
background-color: grey;
position: relative;
margin-bottom: 20px;
}
.scroll-area {
white-space: nowrap;
overflow-x: auto;
height: 100%;
}
.left,
.right {
width: 50px;
height: 100%;
position: absolute;
pointer-events: none;
top: 0;
}
.left {
background: linear-gradient(90deg, orange 0%, rgba(0, 0, 0, 0) 100%);
left: 0;
display: none;
}
.right {
background: linear-gradient(-90deg, orange 0%, rgba(0, 0, 0, 0) 100%);
right: 0;
}
.arrow {
display: block;
position: absolute;
display: flex;
align-items: center;
justify-content: center;
height: 100%;
width: 15px;
cursor: pointer;
}
.left-arrow {
left: 0;
}
.right-arrow {
right: 0;
}
.left-arrow div,
.right-arrow div {
font-size: 40px;
}
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<div class="container">
<div id="x" class="left"></div>
<div class="right"></div>
<div class="arrow left-arrow">
<div class="scroll-btn" id="left-arrow">
<</div>
</div>
<div class="arrow right-arrow">
<div class="scroll-btn" id="right-arrow">></div>
</div>
<div id="a" class="scroll-area">
<div class="text">Scroll to right. The gradients and arrows should appear and disappear based on the scroll position. It should work with more than one container. Lorem ipsum.</div>
</div>
</div>
The needs are:
The arrows should appear and disappear in the same way like the gradients.
If there is not enough text to cause a scrollable area, there should be no gradient and now arrow.
There should be more than one container in the end.
Can somebody help me to do that? I would be super thankful!
You can put your arrows inside the left/right gradient divs. That way they will show/hide same way as the gradients.
EDIT
I cleaned up the code a bit since the original answer was kinda messy. (or 'weird' as mstephen19 put it :)).
// Show gradient and left/right arrows only if scrollable
$(".scroll-area").each((i, el) => {
$(el).parent().find(".right")[el.scrollWidth > el.clientWidth ? "show" : "hide"]();
});
// Show/hide gradient and arrows on scroll
$('.scroll-area').scroll((e) => {
const fullWidth = $(e.target)[0].scrollWidth - $(e.target)[0].offsetWidth - 1;
const left = $(e.target).scrollLeft()
$(e.target).parent().find(".left, .left-arrow")[left > 0 ? "show" : "hide"]();
$(e.target).parent().find(".right, .right-arrow")[left < fullWidth ? "show" : "hide"]();
});
// Scroll on left/right arrow mouse down
let intervalId;
$(".left-arrow, .right-arrow").on("mousedown", (e) => {
const scroll = $(e.target).closest(".container").find(".scroll-area");
intervalId = setInterval(() => {
const left = scroll.scrollLeft();
scroll.scrollLeft(e.target.classList.contains("left-arrow") ? left - 10 : left + 10);
}, 50);
}).on("mouseup mouseleave", () => {
clearInterval(intervalId);
});
* {
margin: 0;
padding: 0;
font-family: sans-serif;
font-size: 16px;
}
.container {
width: 550px;
height: 80px;
background-color: grey;
position: relative;
margin-bottom: 20px;
margin-left: 20px;
}
.scroll-area {
white-space: nowrap;
overflow-x: auto;
height: 100%;
}
.left,
.right {
width: 50px;
height: 100%;
position: absolute;
top: 0;
}
.left {
background: linear-gradient(90deg, orange 0%, rgba(0, 0, 0, 0) 100%);
left: 0;
display: none;
}
.right {
background: linear-gradient(-90deg, orange 0%, rgba(0, 0, 0, 0) 100%);
right: 0;
text-align: right;
}
.left-arrow,
.right-arrow {
margin: 0 10px;
position: absolute;
top: 50%;
-ms-transform: translateY(-50%);
transform: translateY(-50%);
cursor: pointer;
user-select: none;
font-size: 40px
}
.left-arrow {
display: none;
left: -25px;
}
.right-arrow {
right: -25px;
}
<html>
<head>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head>
<body>
<div class="container">
<div class="left"></div>
<div class="right"></div>
<div class="left-arrow"><</div>
<div class="right-arrow">></div>
<div class="scroll-area">
<div class="text">Scroll to right. The gradients and arrows should appear and disappear based on the scroll position. It should work with more than one container. Lorem ipsum.</div>
</div>
</div>
<div class="container">
<div class="left"><span class="left-arrow"><</span></div>
<div class="right"><span class="right-arrow">></span></div>
<div class="scroll-area">
<div class="text">No scroll.</div>
</div>
</div>
</body>
</html>
Some things about your code:
Your original code would not work with multiple containers, because you had a hardcoded #a ID in the interval code. You should really only have IDs on one element ideally, anyways (they're unique identifiers, while classes can be placed on multiple elements). The .scroll-area element should be found based on the target clicked.
You should combine your gradient and arrow elements into one element. By that, I mean making the div in which the arrow lives should be a child of the gradient div. Why manage them both separately?
Use class adding/removing/toggling instead of directly setting the CSS. Remember - when you find yourself writing the same code multiple times, it usually means there is a way to condense it down and make your code more dry and easier to understand + read.
Don't use the literal < and > symbols, as it can confuse some browsers. Use < and > instead.
Rather than toggling display to none and block, it's better to use visibility in this specific case. In my example, we use opacity for a fun fading effect.
Don't forget to listen for both mouseup mouseout events :)
Here is the working solution. I've refactored the code a bit:
let interval;
$('.arrow').on('mousedown', ({ target }) => {
const type = target.classList[1];
const scrollArea = $(target).parent().find('.scroll-area');
interval = setInterval(() => {
const prev = scrollArea.scrollLeft();
scrollArea.scrollLeft(type === 'left-arrow' ? prev - 10 : prev + 10);
}, 50);
});
$('.arrow').on('mouseup mouseout', () => clearInterval(interval));
$('.scroll-area').on('scroll', ({ target }) => {
const left = $(target).parent().find('.left-arrow');
const right = $(target).parent().find('.right-arrow');
const scroll = $(target).scrollLeft();
const fullWidth = $(target)[0].scrollWidth - $(target)[0].offsetWidth;
if (scroll === 0) left.addClass('hide');
else left.removeClass('hide');
if (scroll > fullWidth) right.addClass('hide');
else right.removeClass('hide');
});
.container {
width: 550px;
height: 80px;
background: grey;
position: relative;
}
.right-arrow,
.left-arrow {
height: 100%;
width: 50px;
position: absolute;
display: flex;
justify-content: center;
align-items: center;
font-size: 2rem;
cursor: pointer;
transition: all 0.2s linear;
}
.scroll-area {
white-space: nowrap;
overflow-x: scroll;
height: 100%;
}
.right-arrow {
background: linear-gradient(-90deg, orange 0%, rgba(0, 0, 0, 0) 100%);
left: 500px;
}
.left-arrow {
background: linear-gradient(90deg, orange 0%, rgba(0, 0, 0, 0) 100%);
left: 0px;
}
.scroll-btn {
pointer-events: none;
}
.hide {
opacity: 0;
}
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<div class="container">
<div class="arrow left-arrow">
<div class="scroll-btn" id="left-arrow"><</div>
</div>
<div class="arrow right-arrow">
<div class="scroll-btn" id="right-arrow">></div>
</div>
<div class="scroll-area">
<div class="text">
Scroll to right. The gradients and arrows should appear and disappear based on the scroll position. It should work with more than one
container. Lorem ipsum.
</div>
</div>
</div>
PS: If you don't like the fade effect, remove the transition: all 0.2s linear; part of the CSS, and switch .hide's opacity: 0 to visibility: hidden.

Applying CSS parameters based on scroll position with JavaScript

In the example below, I have two invisible buttons that fill the whole page. The button in the second half horizontally scrolls to the next section, and the button on left to the previous section.
const createButton = () => document.createElement("button")
const insertButton = button => {
document.body.append(button)
return button
}
const [goToPreviousSection, goToNextSection] = [
createButton(),
createButton()
].map(insertButton)
goToPreviousSection.addEventListener("click", () => {
window.scrollBy(-window.innerWidth, 0)
})
goToNextSection.addEventListener("click", () => {
window.scrollBy(window.innerWidth, 0)
})
* {
margin: 0;
padding: 0
}
html { height: 100% }
html,
body,
section {
display: flex;
flex-grow: 1
}
section {
flex: 1 0 100%;
justify-content: center;
align-items: center
}
section:nth-of-type(1) { background: orange }
section:nth-of-type(2) { background: limeGreen }
section:nth-of-type(3) { background: royalBlue }
h2 {
color: white
}
button {
background: transparent;
position: fixed;
top: 0;
width: 50%;
height: 100%;
border: none
}
button:nth-of-type(1) {
left: 0;
cursor: w-resize
}
button:nth-of-type(2) {
right: 0;
cursor: e-resize
}
<section><h2>1</h2></section>
<section><h2>2</h2></section>
<section><h2>3</h2></section>
How can I set the width of the second button to be 100% and z-index to 1 when it's at 0 page scroll position on the left, and same for the width of the first button when it's scrolled to the end of the page?
Here is an approach that works by toggling a class on both buttons to show them fullscreen when we reach one side or the other. It is important to increase the z-index of the fullscreen button since the left button is rendered before the next button.
const createButton = () => document.createElement("button")
const insertButton = button => {
document.body.append(button)
return button
}
const [goToPreviousSection, goToNextSection] = [
createButton(),
createButton()
].map(insertButton)
const previousButtonFullscreen = () => {
goToNextSection.classList.remove("fullscreen")
goToPreviousSection.classList.add("fullscreen")
}
const nextButtonFullscreen = () => {
goToPreviousSection.classList.remove("fullscreen")
goToNextSection.classList.add("fullscreen")
}
const noButtonFullscreen = () => {
goToPreviousSection.classList.remove("fullscreen")
goToNextSection.classList.remove("fullscreen")
}
const updateButtons = () => {
if (window.scrollX === 0) {
nextButtonFullscreen()
} else if (document.body.scrollWidth - window.scrollX === window.innerWidth) {
previousButtonFullscreen()
} else {
noButtonFullscreen()
}
}
goToPreviousSection.addEventListener("click", () => {
window.scrollBy(-window.innerWidth, 0)
updateButtons();
})
goToNextSection.addEventListener("click", () => {
window.scrollBy(window.innerWidth, 0)
updateButtons()
})
updateButtons()
* {
margin: 0;
padding: 0
}
html { height: 100% }
html,
body,
section {
display: flex;
flex-grow: 1
}
section {
flex: 1 0 100%;
justify-content: center;
align-items: center
}
section:nth-of-type(1) { background: orange }
section:nth-of-type(2) { background: limeGreen }
section:nth-of-type(3) { background: royalBlue }
h2 {
color: white
}
button {
background: transparent;
position: fixed;
top: 0;
width: 50%;
height: 100%;
border: none
}
button:nth-of-type(1) {
left: 0;
cursor: w-resize
}
button:nth-of-type(2) {
right: 0;
cursor: e-resize
}
.fullscreen {
width: 100%;
z-index: 10;
}
<section><h2>1</h2></section>
<section><h2>2</h2></section>
<section><h2>3</h2></section>

How do I check whether the right/left edge of an element is overlapping the side of it's container?

I'm trying to display a right / left navigation arrow within a container (the arrows replace the existence of a scrollbar) when the corresponding edge of the content overlaps the container's sides.
Also, when the content is scrolled all the way to the end and can't scroll any further, the arrow should disappear.
My problem is, I'm confused as to how I write the function to check whether the element's contents are overlapping one edge or the other to hide one arrow or the other.
I started writing logic like this:
function setArrows(elem){
if (elem.scrollLeft() > 0) { //scroll position is greater than zero
// show left arrow
}
if () { //scroll position is less than zero
//show right arrow
}
}
but that doesn't seem to be the right logic. It sounded simpler in my head before I went to actually write the function.
How do I check whether the right/left edge of an element is overlapping the side of it's container?
Here's a Stack Snippet:
$('#wrapper').scroll(function(){
//check edges
});
div {
padding: 0px;
margin: 0px;
}
#wrapper {
width: 500px;
height: 100px;
background-color: blue;
overflow-x: scroll;
overflow-y:hidden;
}
#content {
width: 1000px;
height: 100px;
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div id="wrapper">
<div id="content">
</div>
</div>
You need to check if the content width minus the scrollLeft is greater than the wrapper width. If it is show the right scroller..
Something like this
$(function() {
var content = $('#content'),
arrows = $('.arrow'),
wrapper = $('#wrapper').scroll(function() {
//check edges
// handle left arrow
if (this.scrollLeft > 0) {
arrows.filter('.left').addClass('visible');
} else {
arrows.filter('.left').removeClass('visible');
};
// handle right arrow
if (content.outerWidth() - this.scrollLeft > wrapper.width()) {
arrows.filter('.right').addClass('visible');
} else {
arrows.filter('.right').removeClass('visible');
};
});
arrows.on('click', function() {
if ($(this).is('.left')) {
wrapper[0].scrollLeft -= 100;
} else {
wrapper[0].scrollLeft += 100;
}
return false;
});
// initialize
wrapper.trigger('scroll');
});
div {
padding: 0px;
margin: 0px;
}
#wrapper {
width: 500px;
height: 100px;
background-color: blue;
overflow-x: hidden;
overflow-y: hidden;
position: relative;
}
#content {
width: 1000px;
height: 100px;
background: url('http://lorempixel.com/1000/100/abstract/2') 0 0 no-repeat;
}
#full-container {
position: relative;
display: inline-block;
}
.arrow {
position: absolute;
top: 0;
bottom: 0;
width: 40px;
background-color: black;
display: none;
z-index: 100;
cursor: pointer;
color: #fff;
text-align: center;
line-height: 100px;
}
.arrow.visible {
display: block;
}
.arrow.left {
left: 0
}
.arrow.right {
right: 0
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div id="full-container">
<div class="arrow left"><</div>
<div id="wrapper">
<div id="content"></div>
</div>
<div class="arrow right">></div>
</div>

Categories

Resources