I made a website that makes use of Bootstrap 4, horizontal scrolling (via jquery.mousewheel.js) and native CSS Snapping. I am using Chrome 81, and don't care about old/unsupported browsers.
When I apply scroll-snap-type: x mandatory;
to CSS, the horizontal scrolling stops working (no scrolling happens at all). If the CSS property is removed, the scrolling behaves normally. Here is my HTML structure:
<div class="portfolio_content container-fluid h-100">
<div class="row h-100 flex-row flex-nowrap scrollx long_content">
<div class="col-12 h-100 project d-table" id="project1">
<div class="project_title d-table-cell align-middle">
<p>
Project 1
</p>
</div>
</div>
<div class="col-12 h-100 project d-table" id="project2">
<div class="project_title d-table-cell align-middle">
<p>
Project 2
</p>
</div>
</div>
<div class="col-12 h-100 project d-table" id="project3">
<div class="project_title d-table-cell align-middle">
<p>
Project 3
</p>
</div>
</div>
<div class="col-12 h-100 project d-table" id="project4">
<div class="project_title d-table-cell align-middle">
<p>
Project 4
</p>
</div>
</div>
</div>
</div>
For CSS, the key entries are here:
html, body {
height: 100%;
}
.portfolio_content .scrollx {
overflow-x: scroll;
}
.portfolio_content .long_content {
scroll-snap-type: x mandatory; /* Comment this to make scrolling works */
}
.portfolio_content .project {
scroll-snap-align: start;
}
.portfolio_content .project_title {
display: block;
margin: auto;
text-align: center;
}
.portfolio_content .project_title h1 {
font-size: 96px;
line-height: 0.8;
}
Last, here is the JSFiddle demo. If you comment line 9 in CSS, the demo will be able to scroll.
My aim is to allow the "project" DIV to be snapped when scrolling, i.e. one "project" DIV will be fully shown after scrolling.
How should I change the codes?
The scroll container snaps to snap positions in both of its axes independently (potentially snapping to different elements in each axis). The visual viewport of this scroll container will rest on a snap point if it isn't currently scrolled. That means it snaps on that point when the scroll action finished, if possible.
To enable horizontal scrolling, we can use the CSS property overflow-x. If we assign the value scroll to the overflow-x property of the container element, the browser will hide horizontally overflowing content and make it accessible via horizontal scrolling.
For horizontal scrollable bar use the x and y-axis. Set the overflow-y: hidden; and overflow-x: auto; that will automatically hide the vertical scroll bar and present only the horizontal scrollbar. The white-space: nowrap; property is used to wrap text in a single line.
You dont need an external plugin when you can do it with a simple script.
$(".portfolio_content .project").on('wheel', function(e) {
e.preventDefault();
if (e.originalEvent.wheelDelta >= 0) {
if ($(this).prev().length) {
var prev = "#" + $(this).prev().attr("id");
document.querySelector(prev).scrollIntoView({behavior: 'smooth'});
}
} else {
if ($(this).next().length) {
var next = "#" + $(this).next().attr("id");
document.querySelector(next).scrollIntoView({behavior: 'smooth'});
}
}
});
html, body {
height: 100%;
}
.portfolio_content .scrollx {
overflow-x: scroll;
}
.portfolio_content .project {
scroll-snap-align: start;
}
.portfolio_content .project_title {
display: block;
margin: auto;
text-align: center;
}
.portfolio_content .project_title h1 {
font-size: 96px;
line-height: 0.8;
}
#project1, #project3 {
background-color: #EEE;
}
#project2, #project4 {
background-color: #CCC;
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
<div class="portfolio_content container-fluid h-100">
<div class="row h-100 flex-row flex-nowrap scrollx long_content">
<div class="col-12 h-100 project d-table" id="project1">
<div class="project_title d-table-cell align-middle">
<p>
Project 1
</p>
</div>
</div>
<div class="col-12 h-100 project d-table" id="project2">
<div class="project_title d-table-cell align-middle">
<p>
Project 2
</p>
</div>
</div>
<div class="col-12 h-100 project d-table" id="project3">
<div class="project_title d-table-cell align-middle">
<p>
Project 3
</p>
</div>
</div>
<div class="col-12 h-100 project d-table" id="project4">
<div class="project_title d-table-cell align-middle">
<p>
Project 4
</p>
</div>
</div>
</div>
</div>
You need to convert the mousewheel delta from X to Y and apply it to the element which has the scrollbar, also prevent default on the vertical mousewheel interaction of the container, but you need it to set it to the width of the container or it won't be enough to push.
// 'swipe' left or right with mouse wheel:
const container = document.querySelector('.long_content');
container.addEventListener('wheel', (evt) => {
evt.preventDefault();
//scroll deirection
let delta = evt.deltaY;
//take widht of container:
let contWidth = evt.target.offsetWidth;
// check direction and apply to contWidth
if(delta < 0){
contWidth = -contWidth;
}
container.scrollLeft += contWidth;
});
Here is the updated fiddle
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With