o_O
o_O

Reputation: 5747

How to animate CSS transition effect via a scroll?

I have an element I want to "expand" and change the background color for a page background. As the user scrolls, a dot in the center will expand to fill the page with a new background color. I see examples of how to change the background but not how to "expand" it. I have attached a jsfiddle of the CSS animation effect I'm looking for. This example shows how it will look but only works on the hover. You can see what it's supposed to look like if you scroll the example and hover the white dot.1

Preferably I'd like to accomplish this with css animation but I'm not opposed to trying it out with javascript. I've been fiddling around with that here.

Second, I've been using a fake element to get the example but is there a way I can do this effect without needing the element and just using the container's background-color?

Here's the HTML of the example of the effect I'm trying to achieve.

<div class="container">
        <span class="white"></span>
</div>

And here's the CSS:

.container {height:500px;width:100%;background:#ed565d;position:relative;}
.container span {display:block;}
.white {background:#ffffff;height:10px;width:10px;margin:auto;border-radius:100%;position:absolute;top:50%;left:50%;}
.container:hover .white {
    width:300%;
    height:300%;
    -moz-transition: all 0.5s ease-out;
    -o-transition: all 0.5s ease-out;
    -webkit-transition: all 0.5s ease-out;
    transition:all 0.5s ease-out;
    top:-100%;
    left:-100%;
}

Upvotes: 3

Views: 17997

Answers (2)

Mister Jojo
Mister Jojo

Reputation: 22392

It's a mix of different ideas that I have sinned here and there ... with a small part JS, to be piloted in CSS

PS :transition command must be set on element

const storeScroll=()=>{
  document.documentElement.dataset.scroll = window.scrollY;
}

window.onscroll=e=>{  // called when the window is scrolled.  
  storeScroll()
}

storeScroll()   // first attempt
.container {
  position   : relative;
  height     : 500px;
  width      : 100%;
  background : #ed565d;
  overflow   : hidden;  /* added */
}
.white {
  display       : block;
  position      : absolute;
  background    : #fff;
  height        : 10px;
  width         : 10px;
  margin        : auto;
  border-radius : 100%;
  top           : 50%;
  left          : 50%;
  -moz-transition    : all 0.5s ease-out;
  -o-transition      : all 0.5s ease-out;
  -webkit-transition : all 0.5s ease-out;
  transition         : all 0.5s ease-out;
}
html:not([data-scroll='0']) .white {
  width              : 300%;
  height             : 300%;
  top                : -100%;
  left               : -100%;
}
<div class="container">
  <span class="white"></span>
</div>

Upvotes: 1

Toby Mellor
Toby Mellor

Reputation: 8215

If you want the animation to correlate directly to the percentage that the user has scrolled on the page, JavaScript will be needed.

First, get the scroll percentage. Here's a great answer on how to do that: https://stackoverflow.com/a/8028584/2957677

const scrollTop = $(window).scrollTop();
const documentHeight = $(document).height();
const windowHeight = $(window).height();
const scrollPercent = (scrollTop / (documentHeight - windowHeight)) * 100;

Then you can define an animation function that takes in the percent the user has scrolled, and will set the style on the circle to be a percentage between the CSS values at the start of the animation, and the CSS values at the end of the animation.

function growAnimation($element, animationPercentage) {
  const animationDecimal = animationPercentage / 100;

  // Your existing .grow CSS values
  const startPositionPercent = 50; // top/left at start of animation
  const finishSizePercent = 300; // width/height at end of animation
  const finishPositionPercent = -100; // top/left at end of animation

  // The current CSS values, based on how far the user has scrolled
  const currentSizePercent = getProgressFromTo(0, finishSizePercent, animationDecimal);
  const currentPositionPercent = getProgressFromTo(startPositionPercent, finishPositionPercent, animationDecimal);


  $element.css({
    width: `${currentSizePercent}%`,
    height: `${currentSizePercent}%`,
    top: `${currentPositionPercent}%`,
    left: `${currentPositionPercent}%`
  });
}

// A util function to get the progress between two values
// e.g. 50% between 0 and 10 is 5
function getProgressFromTo(from, to, animationDecimal) {
  return from + (to - from) * animationDecimal;
}

Here's a fiddle: https://jsfiddle.net/owazk8y1

Animation Curves

You can look into animation curves to make the animation look a lot smoother. Surround animationDecimal in a bezier curve function. Here's some example functions: https://gist.github.com/gre/1650294 https://jsfiddle.net/owazk8y1/1

Upvotes: 2

Related Questions