Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Horizontal Smooth Momentum Scrolling

THE PROBLEM: I need to apply some mouse wheel smooth horizontal scrolling to this layout: https://jsfiddle.net/38qLnzkh/.

ALTERNATIVE: I've found this Script that does exactly what I want but it seems to work only vertically: Butter.js. If you can make it work Horizontally it would probably solve all my problems.

IMPORTANT:

1. The Script should be disabled based on screen width and in touch devices.

2. It should accommodate a menu on top of everything like you seen in the fiddle.

Thank you in advance.

EDIT: In case it's not clear what I need, here are two examples with the effect I'm looking for:

https://nemesiscorporation.com/

https://www.tentwenty.me/about-us


MY LAYOUT:

HTML:

<main class="outer-wrapper">
    <div class="wrapper">
        <article class="section" id="a"><h2>01</h2></article>
        <article class="section" id="b"><h2>02</h2></article>
        <article class="section" id="c"><h2>03</h2></article>
        <article class="section" id="d"><h2>04</h2></article>
        <article class="section" id="e"><h2>05</h2></article>
        <article class="section" id="f"><h2>06</h2></article>
    </div>
</main>

CSS:

.outer-wrapper {
  width: auto;
  height: 100vw;
  transform: rotate(-90deg) translateX(-100vh);
  transform-origin: top left;
  overflow-y: scroll;
  overflow-x: hidden;
  position: absolute;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
::-webkit-scrollbar {
  display: none;
}

.wrapper {
  display: flex;
  flex-direction: row;
  width: auto;
  transform: rotate(90deg) translateY(-100vh);
  transform-origin: top left;
    margin: 0;
  padding: 0;
}

.section {
    color: #000;
  width: 100vw;
  height: 100vh;
}
like image 994
David Martins Avatar asked Dec 12 '20 19:12

David Martins


1 Answers

I've published an API on github that can easily solve this problem, below you'll find the code to do what you want.

Compared to yours I've just added the js code and the <script> in the HTML.

If you want to know more about it, here you can find the documentation.

EDIT
Since the requirements have changed a little bit and the API has been updated I've modified the example below so that it better fits the question.

Main changes to the answer:

  • Now the js is inside a init() method called onload
  • The css styles have been modified (transform:rotate brakes most of scrolling APIs)
  • The support for the navbar's smooth scroll has been added
  • The scrolling amount now depends on how much the user physically scrolls the mousewheel

/* UPDATED 2022 ANSWER */
function init() {
    /*
     * Variables preparation
     */
    let yourWrapperElement = document.getElementsByClassName("outer-wrapper")[0];
    let whateverEaseFunctionYouWant = remaningScrollDistance => { return remaningScrollDistance / 15 + 1 };

    //Added support for navbar menu's smooth scrolling
    uss.hrefSetup();

    /*
     * As you asked for, we only apply the custom scrolling for desktop devices
     * by using the "wheel" event instead of the "scroll" or "touchmove" events.
     */
    yourWrapperElement.addEventListener("wheel", event => {
      /*
       * We want to overwrite the default scrolling behaviour
       * of your outer-wrapper component.
       */
      event.preventDefault();
      event.stopPropagation();
      uss.scrollXBy(event.deltaY, yourWrapperElement, null, false);             
    }, {passive:false});

    /*
     * We apply a the custom ease function
     * which will be used whenever our component is scrolled by the API
     */
    uss.setXStepLengthCalculator(whateverEaseFunctionYouWant, yourWrapperElement);
}
body {
  margin: 0;
  padding: 0;
}

.outer-wrapper {
  width: auto;
  height: 100vh; /*  Changed to vh */
  width: 100vw; /* Added */
  /*transform: rotate(-90deg) translateX(-100vh); ROTATING containers brakes 90% of scrolling APIs
  transform-origin: top left;*/
  overflow-y: scroll;
  overflow-x: hidden;
  position: absolute;
  scrollbar-width: none;
  -ms-overflow-style: none;
  /*scroll-behavior: smooth; ISN'T NEEDED FOR MY API */
}

::-webkit-scrollbar {
  display: none;
}

.wrapper {
  display: flex;
  flex-direction: row;
  /*width: auto; NOT NEEDED IF WE USE FLEX-SHRINK 0
  transform: rotate(90deg) translateY(-100vh); ROTATING containers brakes 90% of scrolling APIs
  transform-origin: top left;*/
  margin: 0; /* not really needed */
  padding: 0; /* not really needed */
}

.section {
  color: #000;
  flex-shrink: 0; /* ADDED insted of the width/height of the wrapper */
  width: 100vw;
  height: 100vh;
}

#a { background-color: #ccc; }
#b { background-color: #fff; }
#c { background-color: #ccc; }
#d { background-color: #fff; }
#e { background-color: #ccc; }
#f { background-color: #fff; }


h2 {
  text-align: center;
  font-size: 200px;
  margin: 0;
}



/* MENU  _________________________ */



.logo {
  float: left;
}

nav {
  width: 100%;
}

/* HEADER */

header {
  float: left;
  width: 100%;
  position: absolute;
  z-index: 9999;
}


/* HEADER LARGE */

header.large {
  height: 50px;
}

header.large .logo {
  width: 225px;
  height: 50px;
  margin: 20px 0 0 20px;
  background: url('../images/logo-fireqa-green-500px.png');
  background-repeat: no-repeat;
  background-size: contain;

  transition: 0.7s all;
  -moz-transition: 0.7s all;
  -webkit-transition: 0.7s all;
  -o-transition: 0.7s all;
}


/* UNORDERED LIST */

header.large ul {
  list-style: none;
  float: right;
  margin-right: 25px;
}
header.small ul {
  list-style: none;
  float: right;
  margin: 0;
}

header.large li {
  display: inline;
  float: left;
  list-style-position: inside;
  height: 50px;
  -webkit-transition: all ease 0.3s;
  -moz-transition: all ease 0.3s;
  transition: all 0.3s ease-in-out;
}


header.large li a {
  display: block;
  padding: 20px;
  color: #0E6245;
  text-decoration: none;
  font-family: 'Montserrat', 'arial', sans-serif;
  font-weight: 600 !important;
  letter-spacing: -1px;
  font-size: 25px;

  background-image: linear-gradient(#0E6245, #0E6245);
  background-position: 50% 80%;
  background-repeat: no-repeat;
  background-size: 0% 4px;

  -moz-transition: all 0.3s ease-in-out 0s;
  -ms-transition: all 0.3s ease-in-out 0s;
  -o-transition: all 0.3s ease-in-out 0s;
  -webkit-transition: all 0.3s ease-in-out 0s;
  transition: all 0.3s ease-in-out 0s;
}

header.large li a:hover, a:focus {
  background-size: 60% 4px;
}
<script src = "https://cdn.jsdelivr.net/npm/universalsmoothscroll@latest/universalsmoothscroll-min.js"></script>

<body onload = init()>


<main class="outer-wrapper">
    <div class="wrapper">
        <article class="section" id="a"><h2>01</h2></article>
        <article class="section" id="b"><h2>02</h2></article>
        <article class="section" id="c"><h2>03</h2></article>
        <article class="section" id="d"><h2>04</h2></article>
        <article class="section" id="e"><h2>05</h2></article>
        <article class="section" id="f"><h2>06</h2></article>
    </div>
</main>


<!-- MENU _____________________ -->


<header class="large">
    <div class="container">
      <nav>
        <a><div class="logo"></div></a>
          <ul>
            <li><a href="#a">01</a></li>
            <li><a href="#b">02</a></li>
            <li><a href="#c">03</a></li>
            <li><a href="#d">04</a></li>
         </ul>
      </nav>
    </div>
  </header>

  </body>
</html>
like image 95
Cristian Davide Conte Avatar answered Sep 28 '22 20:09

Cristian Davide Conte