Exchanging seamlessly between Fixed and Relative position

Viewed 32

I'm developing a page where during the scroll, elements, at breakpoints, will stop on the screen and animate, once the final point in the scroll is reached they go back to normal scrolling page behavior.

Basically, once div X gets to the middle of the screen it position changes to fixed, and will stop at middle of the screen expanding, moving etc, as the user scrolls, and reached the final scroll point, it will stop and change from position fixed to relative staying in the same spot.

I did a prototype where once the element got to the point on the screen I wanted it to start animate, i would measure its position on the screen with the browser ruler and get the fixed position it should take from then on.

BUT this is a poor and ugly solution, with a lot of hand work.

We can get the scroll and sum up things to get the Y position, but the x position messes up for making the design responsive.

How to do with JS This change? How to get the Fixed equivalent position of a Relative element dynamically?

I dont have much experience with JS, but I'm sure there are good solutions for this.

2 Answers

I think that IS the solution, to use js for changing instantaneously the position (x,y) and the position (absolute/fixed). Also I think there's a library for that but here's a sketch of a solution.

var div = document.querySelector(".dog");
var div_status = document.querySelector("#div_status");
var start = 100;
var stop = 800;
var swap = false;
window.addEventListener("scroll", function() {
  var y = window.scrollY
  var rect = div.getBoundingClientRect();
  div_status.innerText = rect.top.toFixed() + " " + y.toFixed()
  if (y >= start && y <= stop) {

    div_status.style.background = "green"
    if (!swap) {
      div.style.position = "fixed";

      div.style.top = rect.top + "px"
      swap = true
    }
  } else {
    div_status.style.background = "red"
    if (swap) {

      div.style.position = "absolute";
      div.style.top = (y + rect.top) + "px"
      swap = false;
    }

  }
})
body {
  height: 2000px;
}

.dog {
  height: 50px;
  width: 200px;
  border: 1px solid gray;
  background: lightyellow;
  line-height: 50px;
  text-align: center;
  position: relative;
}

#div_status {
  background: red;
  color: white;
  position: fixed;
  right: 100px;
}
<body>
  <pre id="div_status">0 0</pre>
  <br>
  <br>
  <br>
  <br> keep scrolling
  <br>
  <br>
  <br>
  <br>
  <br>
  <br>
  <br>
  <div class="dog">Dog</div>

</body>

Answering my own question... But just learned about position:sticky, this seems to resolve the problem with just CSS, very easy and way more smooth.

#wrap{
    margin:15px;
    padding:10px;
}


.d1{
    
    width:400px;
    height:500px;
}


#d2{
    //background-color:red;
    height:900px;
}


#d3{
  width:100px;
    height:50px;
    border: 10px solid black;
    background-color:green;
    position: sticky;
    top: 70px;
}
<body>
    
<div id="wrap">
    <div class="d1"><div>Scroll Down</div></div>

    <div id="d2" >
        <div id="d3" class="content">I'm the guy...</div>
    </div>

    <div  class="d1"><div>
  <br/><br/><br/><br/><br/><br/><br/><br/><br/>
  <br/><br/><br/><br/><br/><br/><br/>
  Scroll Up</div></div>

</div>
</body>

Related