skrollr icon indicating copy to clipboard operation
skrollr copied to clipboard

Add/Remove Class (also allowing for native css animations)

Open t22james opened this issue 12 years ago • 31 comments

At a basic level, I desire this for simple selected/active states which would use my pre-existing css styles rather than relying on the effectively inline styles of skrollr.

At a more advanced level, (and in response to issue#89 expressing the desire for triggering non-skrollr/scroll-based animations), if we have the ability to add and remove css classes, then we at the least can make use of css animations (maintaing designer focus and avoiding jquery etc).

I could imagine it very simply along the lines of: data-center-top-addclass="selected highlight" data-center-bottom-removeclass="selected highlight"

(In love with your plugin, many thanks)

t22james avatar Nov 29 '12 20:11 t22james

I had this in mind as well. But I couldn't think of a nice syntax. I'm not sure if this should be possible using data-attributes, because things start getting really messy then.

Prinzhorn avatar Nov 29 '12 20:11 Prinzhorn

Alas, my designer's eyes only see the simple surface! Wish I could be of any use :) I hope someone has a way forward for it as I feel this would really blow open this plugin's scope (hopefully) without adding too much weight to it.

t22james avatar Nov 29 '12 21:11 t22james

I had no problem layering waypoints over skrollr, which is more designed for this type of functionality. Maybe this functionality should just stay extracted.

iabw avatar Nov 30 '12 16:11 iabw

Something like waypoints could probably be added very easily to skrollr. It would allow much more sophisticated stuff with JavaScript. If I then additionally expose the currently private method updateClass everyone could add/remove classes the way they want.

But waypoints should probably be added as data-attributes. I'm not sure how it should look like. But on the JS part you would pass named waypoint-functions to the init-function and they get execute when you scroll over them and they get a parameter which tells you the direction.

Prinzhorn avatar Dec 01 '12 10:12 Prinzhorn

So is there a version with waypoints style functionality added into skrollr available now?

chrisgrimshawjones avatar Apr 03 '13 23:04 chrisgrimshawjones

So is there a version with waypoints style functionality added into skrollr available now?

No. Here's something to get you started for now https://github.com/Prinzhorn/skrollr/issues/168#issuecomment-15249026

Prinzhorn avatar Apr 04 '13 05:04 Prinzhorn

As an implementation, I might expect something similar to the render() option, a onKeyframe() event, that triggers anytime a keyframe is passed. It could receive a reference to the element(s) that defined the keyframe. Its easy to implement something similar with the render() event, but could be more efficient.

commonpike avatar Nov 30 '13 14:11 commonpike

As an implementation, I might expect something similar to the render() option, a onKeyframe() event, that triggers anytime a keyframe is passed. It could receive a reference to the element(s) that defined the keyframe. Its easy to implement something similar with the render() event, but could be more efficient.

There's this PR #284 which I don't have time to look at.

Prinzhorn avatar Dec 02 '13 09:12 Prinzhorn

Just wanted to give my +1 for this.

I started out with a similiar approach like in PR #284. But then I thought it would be very handy to have a solution that solely relies on data- attributes, but couldn't get my head around it. Guess I'll build it separated from skrollr.

medoingthings avatar Feb 26 '14 15:02 medoingthings

I started out with a similiar approach like in PR #284. But then I thought it would be very handy to have a solution that solely relies on data- attributes, but couldn't get my head around it.

I actually started to write code last week for exactly this. Just add data-emit-events to the element and it will trigger event for every keyframe (enter/leave), not just for before/between/after.

But it turned out to be harder than I thought, but I almost got there. It didn't had time to finish it so far, but it's planned!

Prinzhorn avatar Feb 26 '14 17:02 Prinzhorn

hi, I want add class "active" for tag with a parameter transform: translate(0px; 0%); There are "skrollable-between" class in your plugin, but this class have two tag. I need to identify only the current block (which I see full). and this class should change only when I see full different block. Sorry for my English and thank for the help!

librisius avatar May 10 '14 09:05 librisius

to some extend you can use attribute-"animations" for this, e.g.

<div data-center-top="@class:active;" data-center-bottom="@class:active" data-edge-strategy="reset"></div>

Prinzhorn avatar May 10 '14 17:05 Prinzhorn

Hi all, I have the same problem - need some functional for adding class to DOM node. For example sometime i need to activate CSS3 Animations because i want to perform some action while user watch page without scroll. Like this

<div data-7700="height:0px; @addClass:MyNewClass" data-8700="height:1000px; @removeClass:MyNewClass" />

and u can use it for calling js function

<div data-7700="height:0px; @evalIn:myFunction1; @evalOut:myFunction2" data-8700="height:1000px; @evalInOut:myFunction3" />

evalIn call function when we scroll from top, evalOut - from bottom to top and evalInOut - both directions

Areks avatar Jun 20 '14 07:06 Areks

To do CSS3 Animations you can try setting an easing on the div you want to animate and then trigger the animation with a 1px scroll difference, it get's a little messy if you want to do complex chains but it works well.

But yes JS triggers would make this perfect

chrisgrimshawjones avatar Jun 22 '14 21:06 chrisgrimshawjones

for example i have lamp and want that when i scroll to some position, it start glowing even if visitor just stay and read text without scroll the page

Areks avatar Jun 22 '14 21:06 Areks

so you can go

div class="lamp" data-7700="opacity:0; data-7701="opacity:1;

.lamp{ transition: all 500ms cubic-bezier(0.420, 0.000, 1.000, 1.000); }

chrisgrimshawjones avatar Jun 22 '14 21:06 chrisgrimshawjones

But... will be this animation infinity?

Just adding css class at some point will be very useful

Areks avatar Jun 22 '14 21:06 Areks

I want to take my words back, calling js function from attribute as i wrote above "

@evalIn:Function1; @evalOut:myFunction" 

is a bullshit, because as the author wrote we have events and this solve all our problem with calling js

Areks avatar Jun 26 '14 12:06 Areks

Hey Alex, there is a bug with the implementation of your suggested code for classes...

<div data-center-bottom="@class:active;" data-end="@class:active" data-edge-strategy="reset"></div>

using this results in expected functionality in that the class is added at "center-bottom", and persists right to "end", however in chrome and safari the class is again removed while "overscrolling" (where the browser/os physically shifts the page up to reveal the browser background itself to intimate that the page has ended). things seem fine in firefox however which doesn't use 'overscrolling'. I wonder if the browser is returning a NAN or something at that point which is confusing your implementation of data-end ..... any ideas for a fix?

t22james avatar Aug 13 '14 01:08 t22james

Hey Alex, there is a bug with the implementation of your suggested code for classes...

It works as intended basically. You're using data-edge-strategy="reset" telling skrollr to remove the class after end. And overscrolling results in a larger offset than the end of the page.

Prinzhorn avatar Aug 13 '14 09:08 Prinzhorn

Right- I suppose conceptually you would imply that data-end would last, well, to the very end... but I appreciate that the 'end' for skrollr is likely stored as a pixel co-ordinate, making it difficult to account for overscroll. My solution in case anyone else encounters issues with overscroll is to add a large offset to the end value, along the lines of data--1000-end="your-stuff-here"

Cheers Alex :)

On 13 August 2014 21:24, Alexander Prinzhorn [email protected] wrote:

Hey Alex, there is a bug with the implementation of your suggested code for classes...

It works as intended basically. You're using data-edge-strategy="reset" telling skrollr to remove the class after end. And overscrolling results in a larger offset than the end of the page.

— Reply to this email directly or view it on GitHub https://github.com/Prinzhorn/skrollr/issues/99#issuecomment-52026768.

t22james avatar Aug 13 '14 20:08 t22james

I've got some funny behavior with adding a class using

<div data-center-bottom="@class:active;" data-end="@class:active" data-edge-strategy="reset"></div>

My code generally looks like:

<nav>
    <ul>
        <li data-top-top="@class:active" data-top-bottom="@class:active" 
            data-anchor-target="#first" data-edge-strategy="reset"><a href="#first">First</a>
        </li>
        <li data-top-top="@class:active" data-top-bottom="@class:active" 
            data-anchor-target="#second" data-edge-strategy="reset">
            <a href="#second">First</a>
        </li>
    </ul>
</nav>

<div id="first" style="height: 100%"></div>
<div id="second" style="height: 100%"></div>

The class adds and removes perfectly for all li elements pointing to div's after "first", but the active class remains on that "first" li element. A workaround that fixes the problem is setting the first li's data attributes as follows:

<li data-top-top="@class:active" data-top-bottom="@class: " 
    data-anchor-target="#first" data-edge-strategy="set"><a href="#first">First</a>
</li>

The empty space in "@class: " is necessary, otherwise skrollr doesn't remove the class attribute.

nalourie avatar Aug 16 '14 00:08 nalourie

Also, as a side note, the above method removes the "skrollrable" class, I'm not familiar enough with the internals to know if that would affect anything.

nalourie avatar Aug 16 '14 00:08 nalourie

mm... I think it's wrong theme for discussing working of @class attribute, because it's generally functional for working with attributes . We discuss this new functionality by adding class using @addClass @removeClass methods. If u want try it (u can get updated library in my repository)

Areks avatar Aug 16 '14 10:08 Areks

One other option is to change a custom attribute - and add the proper selector in css. For example:

<div class="blah" data-100="@myAttr: 0;" data-200="@myAttr: 1;" data-300="@myAttr: 1;" data-400="@myAttr: 0;" ></div>

and in CSS:

.blah[myAttr="1"]{
/* your style */
}

This will only trigger from scroll range of 200 to 300.

OpherV avatar Dec 25 '14 13:12 OpherV

@OpherV this works great! Thank you!

Using this, you can have different styles for before, during, after:

.video-controls[show--video-btn="0"] & {
  opacity: 0;
  transform: translate(0, 5vh);
}

.video-controls[show--video-btn="1"] & {
  opacity: 1;
  transform: translate(0, 0);
}

.video-controls[show--video-btn="2"] & {
  opacity: 0;
}

andreimoment avatar Feb 27 '15 21:02 andreimoment

I love the option of adding/removing classes. But I, too, noticed that the "skrollable" and other related classes (like "skrollable-before" and "skrollable-after") are no longer being applied. Is there a way to make it so the custom classes don't remove the skrollable ones?

flyarrowplane avatar Sep 02 '15 20:09 flyarrowplane

@class doesn't have to be the attribute you wish to change, especially if you're afraid of overwriting your current, hardcoded classes... instead, you can use something like @active: true and then apply certain styling via .selector[active="true"] { ... }

daleyjem avatar Nov 04 '15 01:11 daleyjem

The next solution worked for me:

Adding class active: after scrolling 300px Removing class active: when almost on top of the page

<nav id="menu" class="fixed" role="navigation" data-300="@class:fixed active;" data-100="@class:fixed">

You don't need to remove the class.

jasperuitterhoeve avatar Dec 10 '15 08:12 jasperuitterhoeve

Hi guys,

Need help on how to correctly implement the @class method. see below my sample DOM.

<div id="refresh-bubble-back-1" class="pos-abs" data-0="top: 357px; left: -35px; opacity:0;" data-400="top: 0; opacity:1; @class: pos-abs bublesPop;" data-end="top: 357px; left: -35px; opacity:1; @class: pos-abs;" data-edge-strategy="set"> <img src="<?php echo $domain; ?>/assets/img/parallax/product_refresh_bubble_back_1.png" alt="" /> </div>

but, seems onload of the page it was already added on the element even its not yet scrolled to the assigned data-** was there anything i'm missing?

Thanks in advance hope anyone can help me with my problem.

Regards,

Sang02 avatar Mar 02 '16 02:03 Sang02