electerious / basicScroll

Standalone parallax scrolling for mobile and desktop with CSS variables.
https://basicscroll.electerious.com
MIT License
3.63k stars 148 forks source link

More flexible viewport setting #26

Closed mikestempien closed 5 years ago

mikestempien commented 6 years ago

It would be great to be able to define viewport values in vh units (or percentage/fraction of window height) ex: from: 'top-bottom', to: 'top-75vh'. Use case example: to reveal elements as they scroll into view (with opacity and a bit of movement) and have the transition end as the element's top reaches 25% from the bottom. I could use calc and let the opacity go above 1 using top-middle, but the movement would continue.

electerious commented 6 years ago

It's possible using an absolute from and top value. I agree that it's not as nice as top-75vh, but it should do the job.

from: '0',
to: `${ (document.body.getBoundingClientRect().height / 100) * 25 }px`,

This would animate the element for a distance of 25vh.

mikestempien commented 6 years ago

I should have specified that I meant that it reaches 25% from the bottom of the viewport, not document. Absolute values won't work for me. I managed to work around that using from: 'top-bottom', to: 'top-middle' and timing function that speeds things up yet has a value limit, but it makes applying easing quite tricky.

Sorry, I don't feel that good with javascript to to dare and offer a PR, but from what I've seen adding something like:

if (viewportAnchor == 'vh') y -= viewportHeight * (1 - value.match(/([0-9]+)vh$/)[1] / 100)

to relativeToAbsoluteValue() and changing regexp pattern in isRelativeValue() to /^[a-z]+-[0-9a-z]+$/ could do the trick and allow us to use both top|middle|bottom keyword and vh values ex: 75vh

If you'll even find time to look into this that would be great, thanks!

electerious commented 5 years ago

Recommended solution

A custom anchor can be used to animate from and to a given viewport height.

.anchor {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 75vh;
    pointer-events: none;
}
basicScroll.create({
    elem: document.querySelector('.anchor'),
    from: 'top-top',
    to: 'bottom-top',
    direct: document.querySelector('.elem'),
    props: {
        '--opacity': {
            from: .01,
            to: .99
        }
    }
})

This will change --opacity from 0.01 to 0.99. It starts when the top of the anchor is at the top of the viewport and ends when the bottom of the anchor is at the top of the viewport. In other words: It scrolls 75vh.

See direct mode for more details.