Jump to content
GreenSock

failure13

GSAP + pseudo-selectors

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts

Long time ago Jamie answered me some interesting solutiion for CSS plugin:
http://forums.greensock.com/topic/7752-just-started-cant-get-it-to-work-at-all/?view=findpost&p=29850

But now i have to work with Bootstrap 3 framework, so it has of course it's own default CSS, and then i customize it with my own css, and leave default untouched.
So for example in default Bootstrap .btn-primary have blue background, and i changed it for red, and then animated this button with TweenMax and body .nojs trick, like Jamie teached:
 

MY CSS:

.btn-primary.hover, .nojs .btn-primary:hover {
	background: #A21D20;
	border: 1px solid rgba(162,39,32,0.3);
}

JS:

// allow class animation
$(document.body).removeClass('nojs');

// button hover
$('button.btn, a.btn').hover(function() {
	var span = $(this).find('span');
	var rset = span[0].rset;
	TweenMax.to(this, 0.35, {className:'+=hover'});
	for(var i = 0; i < rset.length; i++) {
		TweenMax.to(rset[i], 0.35, {raphael:{fill: lavkaRed}});
	}
}, function() {
	var span = $(this).find('span');
	var rset = span[0].rset;
	TweenMax.to(this, 0.3, {className:'-=hover'});
	for(var i = 0; i < rset.length; i++) {
		TweenMax.to(rset[i], 0.3, {raphael:{fill: '#2b2b2b'}});
	}
});

I got is at first when hover in i got very fast blink of blue, and then it animates red like usual.

 

Of course it's obvious why it happens, coz i haven't and absolutely don't want to change default Bootstrap 3 CSS to add .nojs before all :hover s everywhere, it's just very bad practice in my case i guess..

 

Do you guys see any other ways it could be done right and easy?

Link to comment
Share on other sites

hi... inside your hover events.. why not just animate backgroundColor and border in the tween instead of changing classes..

 

this way when GSAP animates those values, they will be inline on the tag... which will override any style rules in any style sheet, even Bootstrap 3, unless the CSS property has !Important declared on it in the style sheet.

  • Like 1
Link to comment
Share on other sites

jonathan

Yep, that would be cool solution, but project is big and i have a lot of elements with very different css rules, some have box-shadows, some radius, some borders etc..

Therefore, for example if i call things like .btn or a, i would ideally love to use className on such unified elements to call different rules, that's exactly why className was born i guess..

 

I thought maybe of something like function that would get all minimum necessary parameters from this, and then if they exist - animate them one by one with usual tween, as you said for backgroundColor example.

But something tells me this ain't right and not very fast..

 

P.S. I haven't know about !important, nice that you've mentioned, could save some time!))

But for my case it's not very elegant, too many rules i'd have to override with !important

Link to comment
Share on other sites

Have you considered using a LESS precompiler to build the version of Bootstrap you actually want, instead of including the entire default CSS (which has the :hover styles it seems you don't want) and then having to override everything with more CSS and Javascript? A quick google seems to show that this is a best practice for making a customised Bootstrap site.

 

 

The reason you need to use something like the .nojs rule was mentioned in that exact post you linked, and hasn't changed since:

 

CSS :hover triggers before Javascript hover, so GSAP will see the starting values as the :hover ones

 

If you won't add "nojs" rules, maybe you could add "hasjs" rules to your custom CSS instead that set :hover to the same color as :link?

 

 

You could probably also pre-create the tweens for each element with immediateRender:true and play()/reverse() them in your hover event

var savedTween = TweenMax.to(foo, 0.35, {className:'+=hover', immediateRender:true, paused:true});
Link to comment
Share on other sites

jamiejefferson

Haven't worked with LESS yet, you meant like here http://getbootstrap.com/customize/

How would i remove all hovers at once?

They seem to have only colors, not whole rules..

 

Right now they have 133 hover rules, which is pretty massive..

 

 

If you won't add "nojs" rules, maybe you could add "hasjs" rules to your custom CSS instead that set :hover to the same color as :link?

 

Not sure i understood what you've meant here exactly, but sounds technically same, no?

 

About immideate render, i'd need to precreate them outside of hover function scope?

Will it force pseudo-elements to shut up? O_o

 

P.S. I've found this hardcore solution http://stackoverflow.com/a/19787258 doesn't seem to work (i haven't forgot to include underscore.js), but i really like the concept, any idea how it could be implemented as working solution?

Link to comment
Share on other sites

I didn't mean their customise tool which is just for modifying color values; I meant using the .less files provided by Bootstrap (maybe you have to get them from github) and making your own stylesheet from a mixture of imports, mix-ins and overrides. I don't use Bootstrap or .less much, but the web appears to be full of tutorials on this concept.

 

 

/* bootstrap */
.btn-primary {
  color: #0000FF;
}
.btn-primary:hover {
  color: #FF0000;
}

/* override */
.hasjs .btn-primary:hover {
  color: #0000FF; /* hover doesn't change color anymore */
}
.btn-primary.hover {
  color: #FF0000;
}
$(document.body).addClass('hasjs');

// etc
You don't even technically need to use .hasjs as you could just make :hover the same color in all instances.

 

 

Pre-created tweens would avoid the CSS :hover beating the Javascript mouseover and causing GSAP to use different start values than you intended. This concept was already explained here - you can make a timeline that holds all the hover effects (className, raphael, etc) for a single element.

 

 

Please ask the user on stackoverflow for help with their code. I don't know underscore.js, or care to learn it.

  • Like 2
Link to comment
Share on other sites

jamiejefferson

 

Pre-created tweens would avoid the CSS :hover beating the Javascript mouseover and causing GSAP to use different start values than you intended. This concept was already explained here - you can make a timeline that holds all the hover effects (className, raphael, etc) for a single element.

 

Wait, now this is very interesting, but i don't understand how to do this about className, could you make a simple example please?

 

Now i try this:

            // button hover
            $('button.btn, a.btn').each(function() {
                var buttonTL = new TimelineLite({paused:true});
                buttonTL.to(this, 0.95, {className: '+=hover'}, 0);
                this.hoverTween = buttonTL;
            });
            $('button.btn, a.btn').hover(function() {
                this.hoverTween.play();
            }, function() {
                this.hoverTween.reverse();
            });

And it still have those issues with blue at first

Link to comment
Share on other sites

You skipped adding immediateRender:true which would record the default color, and not the :hover color as the start value (unless the mouse was already hovering it when the page loads).

// button hover
$('button.btn, a.btn').each(function() {
    this.hoverTween = new TimelineLite({ paused:true })
          .to(this, 0.95, { className:'+=hover', immediateRender:true }, 0);
});
$('button.btn, a.btn').hover(function() {
    this.hoverTween.play();
}, function() {
    this.hoverTween.reverse();
});

It seems like you've provided your own example for className - what else do you need?

Link to comment
Share on other sites

Oh, that's exactly what was needed to fire, with immideateRender it works like charm!

Thanks! :)

 

Well, also for example if i want some custom ease or animation speed for hover out, can i pass it somehow through .reverse()?

And also, for example if i have some button with a lot of CSS and i animate it whole like now with +=hover, how would i properly animate some single parameter separately with some totally different animation parameteres, like for example button text color?

Should i just precreate some tween for this parameter only?

Link to comment
Share on other sites

Maybe I'm missing something, but nothing should be stopping you from just making another tween for whatever properties you want?

$('button.btn, a.btn').hover(function() {
    this.hoverTween.play();
    TweenLite.to(this, 1, { color:'red', backgroundColor:'green' });
}, function() {
    this.hoverTween.reverse();
    TweenLite.to(this, 1, { color:'blue', backgroundColor:'yellow' });
});

or you can use multiple tweens in one timeline

this.hoverTween = new TimelineLite({ paused:true })
      .to(this, 0.9, { className:'+=hover', immediateRender:true }, 0)
      .to(this, 0.3, { color:'red', backgroundColor:'green' }, 0.6);
      .to(this.rset, 0.6, { raphael:{ fill:'#000000' } }, 0.3);

 

The eases inside a timeline can't be easily changed on reverse (well, without causing mid-progress tweens to 'jump', which would be very common with mouse events), but instead you might create a linear timeline and control it with an eased tween.

this.hoverTween = new TimelineLite({ paused:true })
      .to(this, 0.9, { ease:Power0.easeNone, className:'+=hover', immediateRender:true }, 0)
      .to(this, 0.3, { ease:Power0.easeNone, color:'red', backgroundColor:'green' }, 0.6);
      .to(this.rset, 0.6, { ease:Power0.easeNone, raphael:{ fill:'#000000' } }, 0.3);
$('button.btn, a.btn').hover(function() {
    TweenLite.to(this.hoverTween, 0.1, { progress:1, ease:Power2.easeInOut });
}, function() {
    TweenLite.to(this.hoverTween, this.hoverTween.duration(), { progress:0, ease:Power1.easeOut });
});
  • Like 1
Link to comment
Share on other sites

Solution about eases works perfectly, very flexible!

One thing i'm not certain about progress: 1 and progress: 0 controls TimelineLite,s progress or TweenLite's?

 

 

Maybe I'm missing something, but nothing should be stopping you from just making another tween for whatever properties you want?

Well, about htis it ain't seem to be that simple, coz when i do this 2nd tween with color:'red' doesn't seem to override 1st, and it do immideately color of 1st...

Any ideas?

Link to comment
Share on other sites

TweenLite/Max and TimelineLite/Max both have progress(). The target of a progress tween is the 'owner' of that progress. You called your TimelineLite hoverTween, and hoverTween.progress() is what my sample is tweening.

 

 

Please provide a demo showing your issue of a tween not overriding a pre existing tween.

Link to comment
Share on other sites

See the Pen ziFJK by failure13 (@failure13) on CodePen

 

Well something like that!

Idea is just to do some parameter with separate tween settings, like for example i want this color: #FFFFFF; to animate later and with longer duration than everything else from +=hover

Link to comment
Share on other sites

Well I'm not sure what you were thinking should happen here - I just uncommented your red tween and it works exactly as I would expect it to, with color tweening to red and not white.

var buttonTL = new TimelineLite({ paused:true })
    .to(this, 0.9, { ease:Power0.easeNone, className:'+=hover', immediateRender:true }, 0)
    .to(this, 0.6, { color:'red' }, 0.3);

The first 0.3 seconds of that timeline will be a tween from #000000 to #FFFFFF due to the className tween, so the red tween will end up starting from a dark gray. Red will then overwrite the #000000 to #FFFFFF part of the className tween, so after red has played, you won't see a tween during that first 0.3 seconds again, and now the :hover style's #FFFFFF will apply during that time since you never removed that style. If you increase the duration of the progress tweens to 2+ seconds, you'll have adequate time to see all of this as it happens.

 

You would see the best result if you changed your hover style to not change the color if you are going to tween it individually at a different time etc

.btn-primary.hover, .nojs .btn-primary:hover {
    color: #000000; /* same as :link color */
    background: #A21D20;
    border: 1px solid rgba(162,39,32,0.3);
}
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×