I've seen something similar and have been trying to refactor the JS. I have two columns of content, which when scrolled move in opposite directions. This should loop continuously.
The issue is if I remove the height from the .project
element. The content will scroll smoothly when scrolling down but not up. The height/length of content will vary so I can't really have a fixed value here.
This seems to depends on viewport height. If the UI behaves as intended and I reduce the width of the viewport it can stop working like described above. But if I then reduce the height - it can begin to behave correctly again. So maybe it's down to how much content is visible in the viewport on load?
Example (also in code snippet):
I will add a 'media query' so that this is only visible on tablet/desktop views and on mobile devices the JS is removed and the content just stacked.
$(document).ready(function() {
var num_children=$('.split-loop__left').children().length;
var child_height=$('.split-loop__right').height() / num_children;
var half_way=num_children * child_height / 2;
$(window).scrollTop(half_way);
function crisscross() {
var parent=$(".split-loop"); //.first();
var clone=$(parent).clone();
var leftSide=$(clone).find('.split-loop__left');
var rightSide=$(clone).find('.split-loop__right');
if (window.scrollY > half_way) {
//We are scrolling up
$(window).scrollTop(half_way - child_height);
var firstLeft=$(leftSide).children().first();
var lastRight=$(rightSide).children().last();
lastRight.appendTo(leftSide);
firstLeft.prependTo(rightSide);
}
else if (window.scrollY < half_way - child_height) {
var lastLeft=$(leftSide).children().last();
var firstRight=$(rightSide).children().first();
$(window).scrollTop(half_way);
lastLeft.appendTo(rightSide);
firstRight.prependTo(leftSide);
}
$(leftSide).css('bottom', '-'+ window.scrollY + 'px');
$(rightSide).css('bottom', '-'+ window.scrollY + 'px');
$(parent).replaceWith(clone);
}
$(window).scroll(crisscross);
}
);
/* Hide Scroll Bars */
::-webkit-scrollbar {
display: none;
}
html,
body {
margin: 0;
padding: 0;
-ms-overflow-style: none;
/* IE and Edge */
scrollbar-width: none;
/* Firefox */
}
/* Basic Styling */
img {
border: 1px solid black;
margin-bottom: 24px;
width: 100%;
max-width: 100%;
}
h2 {
font-size: 14px;
font-weight: normal;
margin-bottom: 4px;
font-family: 'Inter', sans-serif;
}
p {
color: black;
font-size: 11px;
font-family: 'Inter', sans-serif;
}
/* Content will be in these eventually */
.bar-left,
.bar-right {
border-right: 1px solid black;
box-sizing: border-box;
height: 100vh;
position: fixed;
top: 0;
left: 0;
width: 48px;
z-index: 10000;
}
.bar-right {
border: none;
border-left: 1px solid black;
left: auto;
right: 0;
}
/* Split Loop */
.split-loop {
position: relative;
margin: 0 48px;
}
.split-loop__left {
// position: absolute;
// left: 0%;
// top: 0%;
// right: auto;
// bottom: auto;
// z-index: 4;
width: 50%;
}
.split-loop__right {
border-left: 1px solid black;
box-sizing: border-box;
position: fixed;
right: 48px;
bottom: 0;
z-index: 5;
width: calc(50% - 48px);
}
.project {
box-sizing: border-box;
border-bottom: 1px solid black;
height: 600px;
padding: 48px;
}
<script src=".3.0/jquery.min.js"></script>
<header class="bar-left">
</header>
<div class="bar-right">
</div>
<div class="view">
<div class="grid split-loop">
<div class="split-loop__left">
<div class="grid__item project">
<img src="" alt="" class="project__media" />
<h2 class="project__title">Project Title</h2>
<p class="project__desc">Short Description</p>
</div>
<div class="grid__item project">
<img src="" alt="" class="project__media" />
<h2 class="project__title">Project Title</h2>
<p class="project__desc">Short Description</p>
</div>
<div class="grid__item project">
<img src="" alt="" class="project__media" />
<h2 class="project__title">Project Title</h2>
<p class="project__desc">Short Description</p>
</div>
</div>
<div class="split-loop__right">
<div class="grid__item project">
<img src="" alt="" class="project__media" />
<h2 class="project__title">Project Title</h2>
<p class="project__desc">Short Description</p>
</div>
<div class="grid__item project">
<img src="" alt="" class="project__media" />
<h2 class="project__title">Project Title</h2>
<p class="project__desc">Short Description</p>
</div>
<div class="grid__item project">
<img src="" alt="" class="project__media" />
<h2 class="project__title">Project Title</h2>
<p class="project__desc">Short Description</p>
</div>
</div>
</div>
</div>
I've seen something similar and have been trying to refactor the JS. I have two columns of content, which when scrolled move in opposite directions. This should loop continuously.
The issue is if I remove the height from the .project
element. The content will scroll smoothly when scrolling down but not up. The height/length of content will vary so I can't really have a fixed value here.
This seems to depends on viewport height. If the UI behaves as intended and I reduce the width of the viewport it can stop working like described above. But if I then reduce the height - it can begin to behave correctly again. So maybe it's down to how much content is visible in the viewport on load?
Example (also in code snippet): https://jsfiddle/rdowb0y5/1
I will add a 'media query' so that this is only visible on tablet/desktop views and on mobile devices the JS is removed and the content just stacked.
$(document).ready(function() {
var num_children=$('.split-loop__left').children().length;
var child_height=$('.split-loop__right').height() / num_children;
var half_way=num_children * child_height / 2;
$(window).scrollTop(half_way);
function crisscross() {
var parent=$(".split-loop"); //.first();
var clone=$(parent).clone();
var leftSide=$(clone).find('.split-loop__left');
var rightSide=$(clone).find('.split-loop__right');
if (window.scrollY > half_way) {
//We are scrolling up
$(window).scrollTop(half_way - child_height);
var firstLeft=$(leftSide).children().first();
var lastRight=$(rightSide).children().last();
lastRight.appendTo(leftSide);
firstLeft.prependTo(rightSide);
}
else if (window.scrollY < half_way - child_height) {
var lastLeft=$(leftSide).children().last();
var firstRight=$(rightSide).children().first();
$(window).scrollTop(half_way);
lastLeft.appendTo(rightSide);
firstRight.prependTo(leftSide);
}
$(leftSide).css('bottom', '-'+ window.scrollY + 'px');
$(rightSide).css('bottom', '-'+ window.scrollY + 'px');
$(parent).replaceWith(clone);
}
$(window).scroll(crisscross);
}
);
/* Hide Scroll Bars */
::-webkit-scrollbar {
display: none;
}
html,
body {
margin: 0;
padding: 0;
-ms-overflow-style: none;
/* IE and Edge */
scrollbar-width: none;
/* Firefox */
}
/* Basic Styling */
img {
border: 1px solid black;
margin-bottom: 24px;
width: 100%;
max-width: 100%;
}
h2 {
font-size: 14px;
font-weight: normal;
margin-bottom: 4px;
font-family: 'Inter', sans-serif;
}
p {
color: black;
font-size: 11px;
font-family: 'Inter', sans-serif;
}
/* Content will be in these eventually */
.bar-left,
.bar-right {
border-right: 1px solid black;
box-sizing: border-box;
height: 100vh;
position: fixed;
top: 0;
left: 0;
width: 48px;
z-index: 10000;
}
.bar-right {
border: none;
border-left: 1px solid black;
left: auto;
right: 0;
}
/* Split Loop */
.split-loop {
position: relative;
margin: 0 48px;
}
.split-loop__left {
// position: absolute;
// left: 0%;
// top: 0%;
// right: auto;
// bottom: auto;
// z-index: 4;
width: 50%;
}
.split-loop__right {
border-left: 1px solid black;
box-sizing: border-box;
position: fixed;
right: 48px;
bottom: 0;
z-index: 5;
width: calc(50% - 48px);
}
.project {
box-sizing: border-box;
border-bottom: 1px solid black;
height: 600px;
padding: 48px;
}
<script src="https://cdnjs.cloudflare./ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<header class="bar-left">
</header>
<div class="bar-right">
</div>
<div class="view">
<div class="grid split-loop">
<div class="split-loop__left">
<div class="grid__item project">
<img src="https://www.fillmurray./600/400" alt="" class="project__media" />
<h2 class="project__title">Project Title</h2>
<p class="project__desc">Short Description</p>
</div>
<div class="grid__item project">
<img src="https://www.fillmurray./g/600/400" alt="" class="project__media" />
<h2 class="project__title">Project Title</h2>
<p class="project__desc">Short Description</p>
</div>
<div class="grid__item project">
<img src="https://www.fillmurray./600/400" alt="" class="project__media" />
<h2 class="project__title">Project Title</h2>
<p class="project__desc">Short Description</p>
</div>
</div>
<div class="split-loop__right">
<div class="grid__item project">
<img src="https://www.fillmurray./g/600/400" alt="" class="project__media" />
<h2 class="project__title">Project Title</h2>
<p class="project__desc">Short Description</p>
</div>
<div class="grid__item project">
<img src="https://www.fillmurray./600/400" alt="" class="project__media" />
<h2 class="project__title">Project Title</h2>
<p class="project__desc">Short Description</p>
</div>
<div class="grid__item project">
<img src="https://www.fillmurray./g/600/400" alt="" class="project__media" />
<h2 class="project__title">Project Title</h2>
<p class="project__desc">Short Description</p>
</div>
</div>
</div>
</div>
Edit
On closer inspection this is pretty broken when resizing the viewport. It stops working or on narrow windows and the scroll is super super fast.
Share edited Jul 8, 2024 at 22:47 halfer 20.4k19 gold badges109 silver badges202 bronze badges asked Dec 12, 2021 at 11:59 user1406440user1406440 1,6653 gold badges35 silver badges74 bronze badges 4- 2 I believe CodeReview would possibly be a better place to post this question for three reasons. 1) It's almost working fine 2) Guys there enjoy more spending time to debug interesting concepts. 3) CodeReview is less busy so your question won't get lost from the sight as esaily as it does here. – Redu Commented Dec 12, 2021 at 12:37
- Thanks @Redu! If people think that's best I can do that - or would an admin need to move? Whatever people think is best! :) – user1406440 Commented Dec 12, 2021 at 13:09
- 1 No big deal just repost there. – Redu Commented Dec 12, 2021 at 13:12
- Thanks - didn't know it existed! – user1406440 Commented Dec 12, 2021 at 18:21
2 Answers
Reset to default 5This example is a bit sloppy and without using jQuery, but it works with two interdependent scrolls (left and right blocks). I hope this will somehow help you in solving your problem.
const rootElement = document.querySelector(".split-loop");
const leftLoop = document.querySelector(".split-loop__left");
const rightLoop = document.querySelector(".split-loop__right");
const scrollHeight = leftLoop.scrollHeight;
const offsetBoundary = 200; //the offset from the borders at which the element reordering event is triggered
const lastScrollPos = new WeakMap();
const linkedLoops = new Map([
[leftLoop, rightLoop],
[rightLoop, leftLoop],
]);
let scrollLockElement = null;
let scrollLockTimeout = null;
// the function sets handlers to scrolling for infinite scrolling
function infiniteScrollHandler(loop) {
const virtualLoop = Array.from(loop.children);
virtualLoop.forEach(
(el) => (el.style.top = scrollHeight / 2 + el.offsetHeight + "px")
);
loop.addEventListener("scroll", () => {
if (virtualLoop.length < 2) return; // not enough items to scroll
const topBound = loop.scrollTop;
const bottomBound = loop.scrollTop + loop.offsetHeight;
const firstEl = virtualLoop[0];
const lastEl = virtualLoop[virtualLoop.length - 1];
if (firstEl.offsetTop >= topBound - offsetBoundary) {
lastEl.style.top = firstEl.offsetTop - lastEl.offsetHeight + "px";
virtualLoop.unshift(lastEl);
virtualLoop.pop();
} else if (
lastEl.offsetTop + lastEl.offsetHeight <
bottomBound + offsetBoundary
) {
firstEl.style.top = lastEl.offsetTop + lastEl.offsetHeight + "px";
virtualLoop.push(firstEl);
virtualLoop.shift();
}
});
}
// the function sets handlers to scrolling for reverse interaction with the linked loop
function reverseLinkLoopHandler(loop) {
loop.addEventListener("scroll", () => {
const delta = lastScrollPos.get(loop) - loop.scrollTop;
lastScrollPos.set(loop, loop.scrollTop);
// this is blocked to prevent deadlock when events of two blocks are called each other.
{
if (scrollLockElement !== null && scrollLockElement !== loop)
return;
scrollLockElement = loop;
clearTimeout(scrollLockTimeout);
scrollLockTimeout = setTimeout(
() => (scrollLockElement = null),
300
);
}
linkedLoops
.get(loop)
.scrollTo(0, linkedLoops.get(loop).scrollTop + delta);
});
}
// set scroll handlers on all loops
linkedLoops.forEach((loop) => {
infiniteScrollHandler(loop);
loop.scrollTo(0, scrollHeight / 2);
lastScrollPos.set(loop, scrollHeight / 2);
reverseLinkLoopHandler(loop);
});
/* Hide Scroll Bars */
::-webkit-scrollbar {
display: none;
}
html,
body {
margin: 0;
padding: 0;
-ms-overflow-style: none;
/* IE and Edge */
scrollbar-width: none;
/* Firefox */
}
/* Basic Styling */
img {
border: 1px solid black;
margin-bottom: 24px;
width: 100%;
max-width: 100%;
}
h2 {
font-size: 14px;
font-weight: normal;
margin-bottom: 4px;
font-family: "Inter", sans-serif;
}
p {
color: black;
font-size: 11px;
font-family: "Inter", sans-serif;
}
/* Content will be in these eventually */
.bar-left,
.bar-right {
border-right: 1px solid black;
box-sizing: border-box;
height: 100vh;
position: fixed;
top: 0;
left: 0;
width: 48px;
z-index: 10000;
}
.bar-right {
border: none;
border-left: 1px solid black;
left: auto;
right: 0;
}
/* Split Loop */
.split-loop {
position: relative;
margin: 0 48px;
}
.split-loop__left {
width: 50%;
overflow: auto;
position: relative;
max-height: 100vh;
}
.split-loop__right:before,
.split-loop__left:before {
display: block;
content: "";
z-index: -1;
height: 9999999px;
}
.split-loop__right {
border-left: 1px solid black;
box-sizing: border-box;
position: fixed;
right: 48px;
bottom: 0;
z-index: 5;
width: calc(50% - 48px);
overflow: auto;
max-height: 100vh;
}
.project {
box-sizing: border-box;
border-bottom: 1px solid black;
height: 600px;
padding: 48px;
position: absolute;
}
.project__media {
/* height: 100px; */
}
<header class="bar-left"></header>
<div class="bar-right"></div>
<div class="view">
<div class="grid split-loop" style="max-height: 100vh">
<div class="split-loop__left">
<div class="grid__item project">
<img src="https://www.fillmurray./600/400" alt="" class="project__media" />
<h2 class="project__title">Project Title</h2>
<p class="project__desc">Short Description</p>
</div>
<div class="grid__item project">
<img src="https://www.fillmurray./g/600/400" alt="" class="project__media" />
<h2 class="project__title">Project Title</h2>
<p class="project__desc">Short Description</p>
</div>
<div class="grid__item project">
<img src="https://www.fillmurray./600/400" alt="" class="project__media" />
<h2 class="project__title">Project Title</h2>
<p class="project__desc">Short Description</p>
</div>
</div>
<div class="split-loop__right">
<div class="grid__item project">
<img src="https://www.fillmurray./g/600/400" alt="" class="project__media" />
<h2 class="project__title">Project Title</h2>
<p class="project__desc">Short Description</p>
</div>
<div class="grid__item project">
<img src="https://www.fillmurray./600/400" alt="" class="project__media" />
<h2 class="project__title">Project Title</h2>
<p class="project__desc">Short Description</p>
</div>
<div class="grid__item project">
<img src="https://www.fillmurray./g/600/400" alt="" class="project__media" />
<h2 class="project__title">Project Title</h2>
<p class="project__desc">Short Description</p>
</div>
</div>
</div>
</div>
Familytype.co has following constrains:
- There needs to be one more scrolling container. They are using scrollbar on body.
- Both lanes need to be of equal height. Their slides have different heights but they are all multiples of 50vh. And they managed to have same height lanes. Heights are still based on viewports see their
.block--50
and.block--100
style rules. - You need to repeat first two items in same lane to see smooth shift to first slide.
In Following, familytype.co style, approach I've repeated first two elements in left lane. And then cloned all elements of left lane to right in javascript. Also added a media query to show only one lane if viewport width gets below 576px.
let view, parent, leftSide, rightSide;
$(document).ready(function() {
view = $('#view');
parent = $(".split-loop");
leftSide = $(parent).find('.split-loop__left');
rightSide = $(parent).find('.split-loop__right');
centerScrollPosition();
window.onresize = function(event) {
centerScrollPosition();
};
//repeat first 2
$(leftSide).append($($(leftSide).children()[0]).clone());
$(leftSide).append($($(leftSide).children()[1]).clone());
//clone left lane to right
let arr = [];
$(leftSide).children().each((index, elm) => {
arr.push($(elm).clone());
});
//shift right lane by half
//arr.push.apply(arr, arr.splice(0, arr.length / 2));
//arr.push(arr[0].clone());
//arr.push(arr[1].clone());
$(rightSide).append(arr);
//listen to scroll events
//incase you want movement to happen on user scroll
$(view).add(window).scroll(function() {
//$(view).on('wheel', function (event) {
handleScroll();
});
handleScroll();
});
function centerScrollPosition() {
//center the content
var vh = $(window).height();
var lh = leftSide.height();
var half_way = (lh - vh) / 2;
$(window).scrollTop(half_way);
}
function handleScroll() {
var scroll = $(window).scrollTop();
var sh = $(leftSide).height() - window.innerHeight;
if (scroll >= (sh - 1)) {
$(window).scrollTop(2);
} else if (scroll == 0) {
$(window).scrollTop(sh - 1);
}
$(rightSide).css({
"transform": "translate3d(0, " + ((((sh) - scroll * 2) * -1)) + "px, 0)"
});
}
* {
box-sizing: border-box;
}
::-webkit-scrollbar {
display: none;
}
html,
body {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
background-color: white;
}
body {
overflow-y: scroll
}
/* Basic Styling */
img {
max-width: 90%;
object-fit: fill;
margin-top: 1rem;
align-self: center;
border: 1px solid black;
}
h2 {
font-size: 14px;
font-weight: normal;
margin-bottom: 4px;
font-family: 'Inter', sans-serif;
text-align: center;
}
p {
color: black;
font-size: 11px;
font-family: 'Inter', sans-serif;
text-align: center;
}
/* center line for debugging */
.center {
position: fixed;
width: 100vw;
top: 50%;
left: 0%;
z-index: 100000;
transform: translateY(-50%);
border-bottom: 2px dashed gray;
}
/* Content will be in these eventually */
.view {
overflow: hidden;
position: relative;
width: 80vw;
margin: 0 auto;
}
.bar-left,
.bar-right {
/*border-right: 1px solid black;*/
box-sizing: border-box;
height: 100vh;
position: fixed;
top: 0;
left: 0;
width: 5vw;
z-index: 10000;
}
.bar-right {
border: none;
/*border-left: 1px solid black;*/
left: auto;
right: 0;
}
/* Split Loop */
.split-loop {
position: relative;
width: 100%;
height: 100%;
}
.split-loop>div {
max-width: 50%;
float: left;
height: auto;
transform-style: preserve-3d;
display: flex;
flex-flow: column;
}
.split-loop__right {
will-change: transform;
perspective: 1000;
backface-visibility: hidden;
}
.project {
border: 1px solid black;
min-height: auto;
background-color: lightskyblue;
display: flex;
flex-flow: column nowrap;
}
@media(max-width: 576px) {
.split-loop>div {
max-width: 100%;
}
.split-loop__right {
display: none;
}
}
<script src="https://cdnjs.cloudflare./ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- span class="center"></span -->
<header class="bar-left"></header>
<div class="bar-right"></div>
<div id=view class="view">
<div class="grid split-loop">
<div class="split-loop__left">
<div class="grid__item project">
<img src="https://www.fillmurray./600/400" alt="" class="project__media" />
<h2 class="project__title">Project Title 1</h2>
<p class="project__desc">Short Description Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequuntur, id?Short Description Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequuntur, id?</p>
</div>
<div class="grid__item project">
<img src="https://www.placecage./c/460/300" alt="" class="project__media" />
<h2 class="project__title">Project Title 2</h2>
<p class="project__desc">Short Description Lorem ipsum dolor sit amet.</p>
</div>
<div class="grid__item project">
<img src="https://www.placecage./g/155/300" alt="" class="project__media" />
<h2 class="project__title">Project Title 3</h2>
<p class="project__desc">Short Description Lorem ipsum dolor sit amet consectetur, adipisicing elit. Aspernatur nostrum in obcaecati itaque explicabo voluptatibus corporis cumque praesentium eaque beatae!</p>
</div>
<div class="grid__item project">
<img src="https://www.placecage./140/100" alt="" class="project__media" />
<h2 class="project__title">Project Title 4</h2>
<p class="project__desc">Short Description Lorem, ipsum dolor sit amet consectetur adipisicing elit. Dolores nobis eius, minus optio ab earum. Lorem ipsum dolor sit amet consectetur adipisicing elit. Architecto, at. Fuga nisi nulla laborum explicabo possimus repellendus
amet quidem eos.</p>
</div>
<div class="grid__item project">
<img src="https://www.stevensegallery./460/300" alt="" class="project__media" />
<h2 class="project__title">Project Title 5</h2>
<p class="project__desc">Short Description Lorem ipsum dolor sit amet consectetur adipisicing elit. Nihil?</p>
</div>
<div class="grid__item project">
<img src="https://www.fillmurray./g/600/400" alt="" class="project__media" />
<h2 class="project__title">Project Title 6</h2>
<p class="project__desc">Short Description Lorem ipsum dolor, sit amet consectetur adipisicing elit. Quia iste distinctio doloremque facere!</p>
</div>
</div>
<div class="split-loop__right">
</div>
</div>
</div>
More clever placement is needed in second lane.
Old Answer: Instead of using scrollbar we can do it with transform. Explanation is in the code:
//variables to track left and right container scrolls
var leftX = 0, rightX = 0;
//how quickly shifts will happen
//depends on how many images are in a column
//range 1.0 - 5.0
var shiftingThreshold = 1.7;
var isAnimating = false;
var parent, leftSide, rightSide;
$(document).ready(function () {
parent = $(".split-loop");
leftSide = $(parent).find('.split-loop__left');
rightSide = $(parent).find('.split-loop__right');
centerScrollPosition();
window.onresize = function (event) {
centerScrollPosition();
};
document.querySelector('.split-loop__left').addEventListener('transitionend', () => {
isAnimating = false;
//positive value means clockwise
//negative means counter clockwise
//remove if you don't want to run loop
//handleScroll(-125);
});
//listen to scroll events
//incase you want movement to happen on user scroll
$('#view').on('wheel', function (event) {
handleScroll(event.originalEvent.deltaY);
});
//initiate continuous loop
setTimeout(function () {
//handleScroll(-125);
}, 3000);
});
function centerScrollPosition() {
//center the content
var vh = $('#view').height();
var slh = $('.split-loop__left').height();
var half_way = (slh - vh) / 2;
$('#view').scrollTop(half_way);
}
function handleScroll(deltaY) {
//handle next scroll event only after last transition ends.
if (isAnimating) {
return;
}
isAnimating = true;
var isUpShifted = true;
var isJumped = true;
leftX -= deltaY;
rightX += deltaY;
if (deltaY !== 0) {
var childHeight = $('.split-loop__left').children().first().height();
if ((leftX + childHeight / shiftingThreshold) <= 0) { //clockwise shift
isUpShifted = true;
var firstLeft = $(leftSide).children().first();
var lastRight = $(rightSide).children().last();
//shift left-first to right
firstLeft.prependTo(rightSide);
//shift right-last to left
lastRight.appendTo(leftSide);
leftX += childHeight + deltaY;
rightX -= childHeight + deltaY;
} else if ((leftX - childHeight / shiftingThreshold) > 0) { //anti clockwise shift
isUpShifted = false;
var lastLeft = $(leftSide).children().last();
var firstRight = $(rightSide).children().first();
//shift right-first to left
firstRight.prependTo(leftSide);
//shift left-last to right
lastLeft.appendTo(rightSide);
leftX -= childHeight - deltaY;
rightX += childHeight - deltaY;
} else {
isJumped = false;
}
//if we've moved projects to other container then
//adjust position before smooth scrolling effect
if (isJumped) {
$('.split-loop__left').css('transform', 'translateY(' + leftX + 'px)');
$('.split-loop__right').css('transform', 'translateY(' + rightX + 'px)');
$('.split-loop__left').css('transition-duration', '0s');
$('.split-loop__right').css('transition-duration', '0s');
if (isUpShifted) {
leftX -= deltaY;
rightX += deltaY;
} else {
leftX -= deltaY;
rightX += deltaY;
}
}
//do smooth scroll effect
setTimeout(function () {
$('.split-loop__left').css('transition-duration', '1.5s');
$('.split-loop__right').css('transition-duration', '1.5s');
$('.split-loop__left').css('transform', 'translateY(' + leftX + 'px)');
$('.split-loop__right').css('transform', 'translateY(' + rightX + 'px)');
}, 5);
}
}
* {
box-sizing: border-box;
}
html,
body {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
background-color: wheat;
}
/* Basic Styling */
img {
max-width: 80%;
aspect-ratio: 6/4;
object-fit: fill;
margin-top: 10%;
align-self: center;
border: 1px solid black;
}
h2 {
font-size: 14px;
font-weight: normal;
margin-bottom: 4px;
font-family: 'Inter', sans-serif;
text-align: center;
}
p {
color: black;
font-size: 11px;
font-family: 'Inter', sans-serif;
text-align: center;
}
/* center line for debugging */
.center {
position: fixed;
width: 100vw;
top: 50%;
left: 0%;
z-index: 100000;
transform: translateY(-50%);
border-bottom: 2px dashed gray;
}
/* Content will be in these eventually */
.view {
overflow: hidden;
position: relative;
width: 80vw;
height: 100vh;
margin: 0 auto;
}
.bar-left,
.bar-right {
/*border-right: 1px solid black;*/
box-sizing: border-box;
height: 100vh;
position: fixed;
top: 0;
left: 0;
width: 5vw;
z-index: 10000;
}
.bar-right {
border: none;
/*border-left: 1px solid black;*/
left: auto;
right: 0;
}
/* Split Loop */
.split-loop {
position: relative;
width: 100%;
height: 100%;
}
.split-loop>div {
max-width: 50%;
float: left;
transition-timing-function: linear;
height: auto;
will-change: transform;
}
.project {
border: 1px solid black;
min-height: 70vh;
background-color: lightskyblue;
display: flex;
flex-flow: column nowrap;
}
<script src="https://cdnjs.cloudflare./ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- span class="center"></span -->
<header class="bar-left"></header>
<div class="bar-right"></div>
<div id=view class="view">
<div class="grid split-loop">
<div class="split-loop__left">
<div class="grid__item project">
<img src="https://www.fillmurray./600/400" alt="" class="project__media" />
<h2 class="project__title">Project Title 1</h2>
<p class="project__desc">Short Description Lorem ipsum dolor sit amet consectetur adipisicing elit.
Consequuntur, id?</p>
</div>
<div class="grid__item project">
<img src="https://www.fillmurray./g/600/400" alt="" class="project__media" />
<h2 class="project__title">Project Title 2</h2>
<p class="project__desc">Short Description Lorem ipsum dolor sit amet.</p>
</div>
<div class="grid__item project">
<img src="https://www.fillmurray./600/400" alt="" class="project__media" />
<h2 class="project__title">Project Title 3</h2>
<p class="project__desc">Short Description Lorem ipsum dolor sit amet consectetur, adipisicing elit.
Aspernatur nostrum in obcaecati itaque explicabo voluptatibus corporis cumque praesentium eaque beatae!</p>
</div>
</div>
<div class="split-loop__right">
<div class="grid__item project">
<img src="https://www.fillmurray./g/600/400" alt="" class="project__media" />
<h2 class="project__title">Project Title 4</h2>
<p class="project__desc">Short Description Lorem, ipsum dolor sit amet consectetur adipisicing elit. Dolores
nobis eius, minus optio ab earum.</p>
</div>
<div class="grid__item project">
<img src="https://www.fillmurray./600/400" alt="" class="project__media" />
<h2 class="project__title">Project Title 5</h2>
<p class="project__desc">Short Description Lorem ipsum dolor sit amet consectetur adipisicing elit. Nihil?</p>
</div>
<div class="grid__item project">
<img src="https://www.fillmurray./g/600/400" alt="" class="project__media" />
<h2 class="project__title">Project Title 6</h2>
<p class="project__desc">Short Description Lorem ipsum dolor, sit amet consectetur adipisicing elit. Quia iste
distinctio doloremque facere!</p>
</div>
</div>
</div>
</div>
Three items per column are very few to smoothly shift on small viewports. You need to play with
shiftingThreshold
.