8

What is the contexte ?

I have a website, which is a single page, where I will present my activity and projects After scrolling few sections we have a projects in a row.

What I want to do ?

I wanna swap the vertical scroll to horizonta when we arrive to my projects row. When you are at the end of the row it just has to get back to normal with a vertical scroll.

The code

<div className="projectsContainer">     // <--- height 100vh
    <div className="row projects">     //  <--- Positioned in the middle of the parent ↑
        <project1  />
        <project2  />
        <project3  />
        <project4  />
        <project5  />
    </div>
</div>

What is my code ? And what I thought

I have a method inTheMiddle() which is boolean. If <div className="row projects"> is in the middle of the viewport it returns true else false.

A method scrollDirection() which is boolean too, true when scroll goes down false when it is goes up.

Many different method disableScroll() The last disableScroll() method cancel the scroll by re-calculating it

componentDidMount() {
     window.addEventListener('wheel', (this.handleScroll));
}
...
disableScroll() {
    // Get the current page scroll position 
    const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
    const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
    // if any scroll is attempted, set this to the previous value 
    window.onscroll = () => {
        window.scrollTo(scrollLeft, scrollTop);
    };
}

And my handleScroll() method which manage all that

handleScroll(event) {
    const rowProjects = document.querySelector(".row.projects")
    const projectsContainer = document.querySelector(".projectsContainer")
    const isSticky = rowProjects.classList.contains("sticky") 
// isSticky is useless now was try by adding position fixed and no need to use disableScroll()

    if (this.inTheMiddle() && this.state.scrollDown && this.state.count < 1400 ) {
        this.disableScroll()
        this.setState({ count: this.state.count + 10 })
        rowProjects.scroll(this.state.count, 0)
    } else if ((!this.state.scrollDown) && this.state.count > 0) {
        this.setState({ count: this.state.count - 10 })
        rowProjects.scroll(this.state.count, 0)
    }

}

What I cannot manage is to get back to normal. When you arrive at the end of the row I cannot re-able the scroll nor when I scroll up to the top of the page. It stuck on the projects row.

I managed it with isSticky I removed disableScroll() and add a class with position fixed but the problem was that it bounced. Because when it is in the middle i fixed in the middle of the viewport so the element is no longer in position relative so it bounced like a glitch (like taking off a block of a stack block) sorry for the bad exemple :')

If you have any idea to help me it would be very kind. I am scratching my head for 3 days and I still did not find the perfect solution.

7
  • morioh.com/p/7c097570ecd9 Commented Sep 27, 2020 at 2:21
  • so in simple words, you only want the scroll to horizontal and not vertical right? Commented Sep 27, 2020 at 10:49
  • oh, you want to be able to make the vertical scroll go away when you reach the projects' row is that it. Well, then you can use Javascript of that. Commented Sep 28, 2020 at 2:11
  • I'll try what you gave me diedu with some more code. Could work nice. Commented Sep 28, 2020 at 21:26
  • Nathan Wijayasekara Yes but not only, it has to go away vertically and to be horizontally for the time of the row. Then when the row is at the end it has to get back to vertical scroll. I almost made it but it's everytime with a small glitch or other Commented Sep 28, 2020 at 21:27

4 Answers 4

9
+50

This should work fine.You can do vertical scrolling and use window.scrollY value to displace the element horizontally by assigning its value in element.style.left thereby giving it a horizontal scroll effect.I did the same and it worked

(See the result in full screen).

var content = document.getElementById('content_2');
window.addEventListener('scroll', function() {
  var scrolledY = window.scrollY;
  var scrolledX = window.scrollX;

  if (scrolledY > 625 && scrolledY < 3112) {
    content.style.marginTop = 150 + 'px';
    content.style.position = "fixed";
    content.style.top = scrolledY * 0.001 + 'px';
    content.style.left = -(scrolledY - 625) * 0.55 + 'px';

  }
  if (scrolledY <= 625) {
    content.style.position = "initial";

  }
  if (scrolledY >= 3112) {

    content.style.position = "absolute";
    content.style.top = 3112 + 'px';

  }


});
* {
  margin: 0px;
  padding: 0px;
  font-family: 'Arial';
  overflow-x: hidden;
  scroll-behavior: smooth;
}

body {
  min-height: 4400px;
}

.content_1,
.content_2 {
  height: 100vh;
  width: 100vw;
}

.content_1 {
  background-color: black;
  color: white;
}

.content_1 h1 {
  font-size: 200px;
  text-align: center;
}

.content_2 {
  margin-top: 150px;
  top: 625px;
  white-space: nowrap;
  display: flex;
  height: 80vh;
  width: 200vw;
  position: fixed;
  flex-direction: row;
  flex-wrap: nowrap;
}

.content_3 {
  font-size: 20px;
  margin-top: 3050px;
}

.card {
  background-color: red;
  color: white;
  white-space: nowrap;
  text-align: center;
  height: 300px;
  width: 300px;
  margin: 10px 30px 10px 10px;
}
<div class="content_1">
  <h1>First Page</h1>
</div>
<div class="content_2" id="content_2">
  <div class="card" style="background-color: #FF7A7A;">Card-1</div>
  <div class="card" style="background-color: #FF3C3C;">Card-2</div>
  <div class="card">Card-3</div>
  <div class="card" style="background-color: #FF3600;">Card-4</div>
  <div class="card" style="background-color: #FF871C;">Card-5</div>
  <div class="card" style="background-color: #FFA91C;">Card-6</div>
  <div class="card" style="background-color: #FFC11D;">Card-7</div>
  <div class="card" style="background-color: #FFF81D;">Card-8</div>
</div>
<div class="content_3">
  <p>Senectus purus, molestie blandit sociis eu leo blandit platea commodo aptent scelerisque cursus. Hac vel himenaeos hendrerit eu pellentesque. Lorem natoque praesent dictum porta, aliquam bibendum laoreet class litora? Class nullam maecenas aliquet.
    Ligula, et enim vel rutrum luctus lorem orci fringilla in erat? Bibendum magnis nec volutpat non netus dignissim. Tempus tempor penatibus nulla egestas semper scelerisque cubilia. Nulla adipiscing per porta consequat et imperdiet posuere magna fringilla
    rhoncus conubia. Sapien proin euismod.
  </p>
  <p>Tempus luctus tempor donec pretium lectus leo facilisis leo, inceptos nostra lorem vel. Orci parturient urna etiam pharetra sit lacus volutpat id sed lacinia. Scelerisque ultrices nisi risus aenean tincidunt, amet arcu tempus id curabitur purus fringilla.
    Eros iaculis vitae vitae rutrum ultricies dolor sociis ante ante ut. Ut nibh primis himenaeos egestas dictumst congue scelerisque!
  </p>
  <p>Blandit sociis quisque ultrices montes tortor. Penatibus risus primis, senectus nam nostra. Egestas, nulla vitae penatibus cursus sed. Luctus, eget dignissim porttitor et curae; accumsan. Accumsan blandit ligula sollicitudin. Ligula mattis ad turpis
    arcu mus laoreet conubia risus accumsan quis lobortis. Nisi sollicitudin penatibus lacus nam justo id commodo sagittis. Leo orci.
  </p>

  <p>Fringilla sociosqu laoreet id, dui lobortis condimentum? Facilisis non, cubilia diam. Egestas aptent ornare et felis morbi senectus molestie, egestas donec himenaeos ultrices himenaeos. Condimentum conubia nisl urna lobortis pharetra adipiscing cras
    eget pellentesque sollicitudin faucibus. Scelerisque lobortis nascetur neque ac quam dignissim fames. Magnis pharetra dignissim nullam sapien eu curabitur, ridiculus dapibus. Aptent tempus nibh eget scelerisque magna ipsum turpis. Taciti nostra morbi
    pharetra montes sagittis posuere mollis.
  </p>
  <p>Taciti tortor phasellus placerat inceptos tristique consectetur accumsan vitae potenti sodales nulla eros. Dapibus scelerisque penatibus nisl accumsan ultricies ridiculus porta. Varius tellus erat laoreet morbi tempor tristique. Sapien, sem morbi libero
    dapibus curabitur. Facilisi habitasse feugiat semper magnis risus id tellus libero semper. Vehicula turpis elit lectus interdum metus ultrices mollis consectetur cubilia.
  </p>
  <p>Senectus purus, molestie blandit sociis eu leo blandit platea commodo aptent scelerisque cursus. Hac vel himenaeos hendrerit eu pellentesque. Lorem natoque praesent dictum porta, aliquam bibendum laoreet class litora? Class nullam maecenas aliquet.
    Ligula, et enim vel rutrum luctus lorem orci fringilla in erat? Bibendum magnis nec volutpat non netus dignissim. Tempus tempor penatibus nulla egestas semper scelerisque cubilia. Nulla adipiscing per porta consequat et imperdiet posuere magna fringilla
    rhoncus conubia. Sapien proin euismod.
  </p>

  <p>Tempus luctus tempor donec pretium lectus leo facilisis leo, inceptos nostra lorem vel. Orci parturient urna etiam pharetra sit lacus volutpat id sed lacinia. Scelerisque ultrices nisi risus aenean tincidunt, amet arcu tempus id curabitur purus fringilla.
    Eros iaculis vitae vitae rutrum ultricies dolor sociis ante ante ut. Ut nibh primis himenaeos egestas dictumst congue scelerisque!
  </p>
  <p>Blandit sociis quisque ultrices montes tortor. Penatibus risus primis, senectus nam nostra. Egestas, nulla vitae penatibus cursus sed. Luctus, eget dignissim porttitor et curae; accumsan. Accumsan blandit ligula sollicitudin. Ligula mattis ad turpis
    arcu mus laoreet conubia risus accumsan quis lobortis. Nisi sollicitudin penatibus lacus nam justo id commodo sagittis. Leo orci.
  </p>
  <p>Fringilla sociosqu laoreet id, dui lobortis condimentum? Facilisis non, cubilia diam. Egestas aptent ornare et felis morbi senectus molestie, egestas donec himenaeos ultrices himenaeos. Condimentum conubia nisl urna lobortis pharetra adipiscing cras
    eget pellentesque sollicitudin faucibus. Scelerisque lobortis nascetur neque ac quam dignissim fames. Magnis pharetra dignissim nullam sapien eu curabitur, ridiculus dapibus. Aptent tempus nibh eget scelerisque magna ipsum turpis. Taciti nostra morbi
    pharetra montes sagittis posuere mollis.
  </p>
  <p>Taciti tortor phasellus placerat inceptos tristique consectetur accumsan vitae potenti sodales nulla eros. Dapibus scelerisque penatibus nisl accumsan ultricies ridiculus porta. Varius tellus erat laoreet morbi tempor tristique. Sapien, sem morbi libero
    dapibus curabitur. Facilisi habitasse feugiat semper magnis risus id tellus libero semper. Vehicula turpis elit lectus interdum metus ultrices mollis consectetur cubilia.
  </p>
</div>

Sign up to request clarification or add additional context in comments.

9 Comments

Thanks for your time. With position fixed I did exactly the same as yours, that was my best trie. But as yours it's glitchy in full screen. Blocks stick to top the top of the container because it's in the middle of the screen. :/
@crg what you mean is that due to position:fixed the block didn't retain its original top position after scrolling back to same coordinate of the block.That is why i have set some constraints in IF CONDITION based on the value of window.scrollY so that the position of the element changes the moment next paragraph starts or the first page block ends.
Yes, i made a record of the glitch imgur.com/a/nfpS1NJ. I had the same problem in my project. I'm looking forward a fluid solution :/ Or maybe I could do some hacks with the parent container. I will try and if it doesn't work i'll use @diedu solution in comment of the post.
@crg Send me your code so that i could rectify the issue
@crg i tried my code in firefox and chrome and its working fine and in your video the scrolling starts by pushing the element upward,to solve that issue you need to check the scrollY value when you want the horizontal scroll effect to commence and end,check it by console.log(window.scrollY) in inspect and put it in the constraints of IF CONDITION instead of mine
|
2

    $(window).scroll(function() {
        var sectionHeight = $(window).height();
        var sectionWidth = $(window).width();
        var section3Width = sectionWidth * 3;
        var totalHeight = sectionHeight * 2
        var totalSection3Width = section3Width * 2
        if ($(document).scrollTop() > totalHeight) {
            //alert("1");
            window.scrollBy(sectionWidth, 0);
            $("body").css("overflow-y", "hidden", "overflow-x", "scroll");
         }
           
    });
.section {
display: block;
width: 100%;
height: 100vh;
}
.section1 {
background: red;
}
.section2 {
background: yellow;
}
.section3 {
display: block;
overflow-x: scroll;
overflow-y: hidden;
}
.scroll-y {width: calc(100vw * 3);display: flex;}


.secitem {
display: inline-block;
height: 100vh;
width: 100vw;
}
.secitem1{
background: green;}
.secitem2 {
background: skyblue;
}
.secitem3 {
background: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="section section1"></div>
<div class="section section2"></div>
<div class="section section3">
<div class="scroll-y">
<div class="secitem secitem1"></div>
<div class="secitem secitem2"></div>
<div class="secitem secitem3"></div>
</div>
</div>

Comments

0

another version:

$(window).scroll(function() {
        var sectionHeight = $(window).height();
        var sectionWidth = $(window).width();
        var section3Width = sectionWidth * 3;
        var totalHeight = sectionHeight * 2
        var totalSection3Width = section3Width * 2
        if ($(document).scrollTop() > totalHeight) {
            //alert("1");
          if(window.scrollBy(0, 0)){
            window.scrollBy(sectionWidth, 0);
            $("body").css("overflow-y", "hidden", "overflow-x", "scroll");
          } 
            
         }
           
    });
.section {
display: block;
width: 100%;
height: 100vh;
}
.section1 {
background: red;
}
.section2 {
background: yellow;
}
.section3 {
display: block;
overflow-x: scroll;
overflow-y: hidden;
}
.scroll-y {width: calc(100vw * 3);display: flex;}


.secitem {
display: inline-block;
height: 100vh;
width: 100vw;
}
.secitem1{
background: green;}
.secitem2 {
background: skyblue;
}
.secitem3 {
background: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="section section1"></div>
<div class="section section2"></div>
<div class="section section3">
<div class="scroll-y">
<div class="secitem secitem1"></div>
<div class="secitem secitem2"></div>
<div class="secitem secitem3"></div>
  </div>
  
</div>

Comments

0

To make it work accros all navigator I finally did it using pageYOffset and getBoundingClientRect and other functions to detect where is exactly my row of projects, in X / Y of my window.

See the full result here cargouet.com

export default class ProjectsCards extends Component {
    constructor() {
        super();
        this.handleScroll = this.handleScroll.bind(this);
        this.heightIsSet = false
    }

    componentDidMount() {
        if (window.matchMedia("(max-width: 991px)").matches) return
        window.addEventListener('scroll', this.handleScroll, true)
        setTimeout(() => {
            this.offsetTop = window.pageYOffset + document.querySelector(".projectsContainer").getBoundingClientRect().top;
        }, 2000)
    }

    handleScroll() {
        const rowProjects = document.querySelector(".row.projects"),
            projectsContainer = document.querySelector(".projectsContainer"),
            wrapper = document.querySelector(".projectsWrapper"),
            projectsCard = document.querySelectorAll(".row.projects .pcard"),
            scrolledY = window.scrollY,
            lastCardFromRightSideOfTheScreen = projectsCard[projectsCard.length - 1].getBoundingClientRect().right + 100;
            rowProjects.style.willChange = 'transform';

        if ((scrolledY > this.offsetTop && lastCardFromRightSideOfTheScreen > rowProjects.offsetWidth) ||
            (projectsContainer.getBoundingClientRect().y > 0 && lastCardFromRightSideOfTheScreen <= rowProjects.offsetWidth)) {
            projectsContainer.classList.remove("absolute")
            projectsContainer.classList.add("sticky")
            // Get wrapper height
            if(!this.heightIsSet) this.childConainterFromParent = (this.offsetTop - wrapper.getBoundingClientRect().top) - (this.offsetTop - projectsContainer.getBoundingClientRect().top)
            // Set X scroll speed 
            rowProjects.style.transform = "translateX(" + -(scrolledY - this.offsetTop) * 0.55 + "px)"
        } else if (lastCardFromRightSideOfTheScreen <= rowProjects.offsetWidth) {
            this.heightIsSet = true
            // Set wrapper height
            wrapper.style.height = window.innerHeight + this.childConainterFromParent + 'px'
            projectsContainer.classList.remove("sticky")
            projectsContainer.classList.add("absolute")
        } else {
            if(projectsContainer.classList.contains("absolute") || projectsContainer.classList.contains("sticky")) {
                rowProjects.style.transform = "translateX(0)"
                projectsContainer.classList.remove("sticky")
                projectsContainer.classList.remove("absolute")
            }
        }
    }

    render() {
        return (
            <section id="project" className="d-flex align-items-center">
                <div className="projectsWrapper">
                    <div className="projectsContainer">
                        <div className="row projects">
                            <Project  />
                            <Project  />
                            <Project  />
                            <Project  />
                            <Project  />
                        </div>
                    </div>
                </div>
            </section>
        );
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.