{"id":6042,"date":"2021-05-17T02:00:00","date_gmt":"2021-05-17T00:00:00","guid":{"rendered":"https:\/\/alvarotrigo.com\/epa\/scroll-horizontally-with-mouse-wheel-vanilla-java\/"},"modified":"2024-07-25T20:05:12","modified_gmt":"2024-07-25T18:05:12","slug":"scroll-horizontally-with-mouse-wheel-vanilla-java","status":"publish","type":"post","link":"https:\/\/alvarotrigo.com\/blog\/scroll-horizontally-with-mouse-wheel-vanilla-java\/","title":{"rendered":"Scroll horizontally with mouse wheel: Vanilla JavaScript"},"content":{"rendered":"\n<p>Imagine scrolling down with the mouse-wheel or trackpad and that your page scrolls horizontally instead. Isn\u2019t that cool? In this article we will take a look at how you could use vanilla Javascript to create such an interesting effect.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"creating-some-scrollable-content\">Creating some scrollable content<\/h2>\n\n\n\n<p>To start, we will write some HTML to set in place some content that requires some horizontal scroll.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">main<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">section<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h1<\/span>&gt;<\/span>Beep<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h1<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">section<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">section<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h1<\/span>&gt;<\/span>Boop<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h1<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">section<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">section<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h1<\/span>&gt;<\/span>Boooom<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h1<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">section<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">main<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The <code>main<\/code> element will be the scroll container. It is a going to be the element that a scrollbar is bound to as long as there is content that overflow it. As it is right now, there isn&#8217;t enough content to produce an overflow. So let\u2019s fix this.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"making-sure-the-content-overflows\">Making sure the content overflows<\/h2>\n\n\n\n<p>We will place each section aligned next to each other so the content overflows horizontally. We are trying to create something like this, where elements are overflowing the container and therefore we can create a horizontal scrollbar for them. You can have as many sections as you want.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" data-src=\"https:\/\/alvarotrigo.com\/blog\/assets\/imgs\/elements-horizontal-overflowing-demo.jpeg\" alt=\"elements horizontal overflowing demo\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" class=\"lazyload\" \/><\/figure>\n\n\n\n<p>For the purpose of this demo we will make the elements full-screen. To do this, we will use viewport units like <code>vh<\/code> and <code>vw<\/code> to set the <code>min-width<\/code> and <code>min-height<\/code> properties to scale to both the edges of the screen. Then we can center the content using <code>justify-content<\/code> and <code>align-items<\/code>.<\/p>\n\n\n\n<p>We use <code>display:flex<\/code> making the <code>main<\/code> element the flex container. We will also be hiding the scrollbar for this demo by using <code>overflow-x: hidden<\/code>. There\u2019s no need for this but we\u2019ll be doing it for our demo. If you decide not to hide it, make sure to change it for <code>overflow-x: scroll<\/code>.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">main<\/span> {\n  <span class=\"hljs-attribute\">overflow-x<\/span>: hidden; <span class=\"hljs-comment\">\/*or overflow-x:scroll *\/<\/span>\n  <span class=\"hljs-attribute\">display<\/span>: flex;\n}\n\n<span class=\"hljs-selector-tag\">h1<\/span> {\n  <span class=\"hljs-attribute\">margin<\/span>: <span class=\"hljs-number\">0<\/span>;\n}\n\n<span class=\"hljs-selector-tag\">section<\/span> {\n  <span class=\"hljs-attribute\">min-width<\/span>: <span class=\"hljs-number\">50vw<\/span>;\n  <span class=\"hljs-attribute\">min-height<\/span>: <span class=\"hljs-number\">100vh<\/span>;\n  <span class=\"hljs-attribute\">display<\/span>: flex;\n  <span class=\"hljs-attribute\">justify-content<\/span>: center;\n  <span class=\"hljs-attribute\">align-items<\/span>: center;\n  <span class=\"hljs-attribute\">font-size<\/span>: <span class=\"hljs-number\">4ch<\/span>;\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>And why not, we will also give each section a different background:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">section<\/span><span class=\"hljs-selector-pseudo\">:nth-child(even)<\/span> {\n  <span class=\"hljs-attribute\">background-color<\/span>: teal;\n  <span class=\"hljs-attribute\">color<\/span>: white;\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\" id=\"using-the-mouse-wheel-or-trackpad-to-scroll-horizontally\">Using the mouse wheel or trackpad to scroll horizontally<\/h2>\n\n\n\n<p>Here\u2019s where the fun part comes. Now we will subscribe to the <code>mousewheel<\/code> event by attaching an event listener to our scrollable element, which in this case is the element with the tag <code>main<\/code>.<\/p>\n\n\n\n<p>What does this means? It means that now we will be able to gather information through JavaScript about the scrolling event, which is exactly what we need.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">const<\/span> scrollContainer = <span class=\"hljs-built_in\">document<\/span>.querySelector(<span class=\"hljs-string\">'main'<\/span>);\n\nscrollContainer.addEventListener(<span class=\"hljs-string\">'wheel'<\/span>, (evt) =&gt; {\n  <span class=\"hljs-comment\">\/\/ The magic happens here.<\/span>\n});\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>We need to know the direction the user is scrolling to and the amount they scrolled. So, how do we do it?<\/p>\n\n\n\n<p>We will be using the <code>deltaY<\/code> property of the event object we get on the parameter (<code>evt<\/code>).<\/p>\n\n\n\n<p>The <code>wheel<\/code> event has 4 properties, and <code>deltaY<\/code> represents the vertical scroll amount. So we will use exactly that same value to scroll the exact same amount but this time horizontally.<\/p>\n\n\n\n<p>We will be updating the <code>scrollLeft<\/code> property of the scrollable container (<code>main<\/code>) so it scrolls it horizontally.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">const<\/span> scrollContainer = <span class=\"hljs-built_in\">document<\/span>.querySelector(<span class=\"hljs-string\">\"main\"<\/span>);\n\nscrollContainer.addEventListener(<span class=\"hljs-string\">\"wheel\"<\/span>, (evt) =&gt; {\n    evt.preventDefault();\n    scrollContainer.scrollLeft += evt.deltaY;\n});\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The <code>deltaY<\/code> property can be positive ore negative.  When it is positive it means the user is scrolling up and when it is negative the user is scrolling down. So, in our case, when they scroll up we want to scroll left and when they scroll down we want to scroll right.<\/p>\n\n\n\n<p>The <code>scrollLeft<\/code> property works exactly with the same idea in mind. When applied to a scrollable element, a negative value means we will be scrolling the scrollable element to the left and a positive one means we will be doing it on the opposite direction, to the right. So we basically assign the <code>deltaY<\/code> value to the <code>scrollLeft<\/code> property and we are ready to go!<\/p>\n\n\n\n<p>Just one note. Do not confuse the <code>wheel<\/code> event with the <code>mousewheel<\/code> event, the latter of which has been deprecated.<\/p>\n\n\n\n<p>Take a look at the following codepen, fork it and play around with the code to see if you can build a neat horizontally scrollable layout:<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_gOmgRzL\" data-src=\"\/\/codepen.io\/anon\/embed\/gOmgRzL?height=450&amp;theme-id=1&amp;slug-hash=gOmgRzL&amp;default-tab=css,result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed gOmgRzL\" title=\"CodePen Embed gOmgRzL\" class=\"cp_embed_iframe lazyload\" style=\"width:100%;overflow:hidden\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" data-load-mode=\"1\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"stick-to-horizontal-scrolling-and-resume-normal-scroll-when-finished\">Stick to horizontal scrolling and resume normal scroll when finished<\/h2>\n\n\n\n<p>Perhaps you are wondering if you can apply the same technique with content before and after the horizontal scrollable element. So the horizontal scrolling element will <strong>stick on the viewport until we finish scrolling horizontally<\/strong>.<\/p>\n\n\n\n<p>The answer is YES, you can. This way, the <strong>vertical scroll will seem to pause<\/strong> while we keep on scrolling horizontally. Once we are done scrolling <strong>vertical scroll will resume<\/strong>.<\/p>\n\n\n\n<p>The trick is creating a sticky container with the height of the horizontal scrollable width. This will serve as a placeholder. It will stick to the top while the page scrolls the placeholder vertically without the user noticing, as we have a stick element taking the whole viewport.<\/p>\n\n\n\n<p>We will then use that scroll to apply it in our sticky element.<\/p>\n\n\n\n<p>There&#8217;s a bit more JavaScript involved here. Here&#8217;s the full example:<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_VwWMjVp\" data-src=\"\/\/codepen.io\/anon\/embed\/VwWMjVp?height=450&amp;theme-id=1&amp;slug-hash=VwWMjVp&amp;default-tab=js,result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed VwWMjVp\" title=\"CodePen Embed VwWMjVp\" class=\"cp_embed_iframe lazyload\" style=\"width:100%;overflow:hidden\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" data-load-mode=\"1\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"you-like-scrolling-effects%3F\">You like scrolling effects?<\/h2>\n\n\n\n<p>Love exploring the different ways you can make users interact with your page? Then you are going to have to try out <a href=\"https:\/\/alvarotrigo.com\/fullPage\/\">fullPage<\/a>, it is one of those libraries that comes with a whole box of neat tricks and ways to implement commonly implemented scrolling effects.<\/p>\n\n\n\n<p>Whether it&#8217;s snap scrolling both horizontally or vertically, neatly triggering animations or conditionally changing styles it&#8217;s got you covered on all fronts.<\/p>\n\n\n\n<p>\n  <a href=\"https:\/\/alvarotrigo.com\/fullPage\/extensions\/scroll-horizontally.html\">\n      <video width=\"680\" height=\"382\" controls muted autoplay loop playsinline>\n      <source src= \"https:\/\/cdn.jsdelivr.net\/gh\/alvarotrigo\/blog-assets\/videos\/scroll-horizontally.mp4\" type=\"video\/mp4\" \/>\n      Your browser does not support the video tag.\n      <\/source><\/video>\n  <\/a>\n<\/p>\n\n\n\n<div class=\"wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/alvarotrigo.com\/fullPage\/extensions\/scroll-horizontally.html\" title=\"Scroll Horizontal demo\" target=\"_blank\" rel=\"noopener\">Scroll Horizontal demo<\/a><\/div>\n<\/div>\n\n\n\n<p>With cross-browser compatibility (all the way back to IE11), superb documentation, and well-tested code it comes with support for your favorite front-end frameworks like React, Vue, or Angular and popular WordPress web builders like Gutenberg or Elementor.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"related-articles\">Related articles<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/alvarotrigo.com\/blog\/css-snap-scroll-horizontally\/\">Scroll horizontally with CSS snap scroll<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/alvarotrigo.com\/blog\/prevent-scroll-on-scrollable-element-js\/\">Prevent Scroll On Scrollable Elements<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/alvarotrigo.com\/blog\/wait-1-second-javascript\/\">Wait 1 second in JavaScript<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/alvarotrigo.com\/blog\/css-animations-scroll\/\">Create CSS animations on scroll<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Learn how to create horizontal scrolling when using the mousewheel or trackpad. Pure vanilla Javascript, no frameworks!<\/p>\n","protected":false},"author":1,"featured_media":6041,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[107],"tags":[9,25,10],"class_list":["post-6042","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-javascript","tag-css","tag-html","tag-javascript"],"acf":[],"_links":{"self":[{"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/posts\/6042","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/comments?post=6042"}],"version-history":[{"count":5,"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/posts\/6042\/revisions"}],"predecessor-version":[{"id":15610,"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/posts\/6042\/revisions\/15610"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/media\/6041"}],"wp:attachment":[{"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/media?parent=6042"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/categories?post=6042"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/tags?post=6042"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}