1

I have a header that I fix to the top of the page after a set scroll amount, and want to perform a set of CSS transitions on multiple elements within the header when the header becomes fixed:

  1. the header height shrinks from 100px to 60px
  2. the header icons shrinks from 50x50 to 25x25
  3. the header font shrinks from 48px to 36px

#1 works as expected, but #2 and #3 instantaneously change, instead of animating their size, when the scroll target is hit.

I am adding/removing a class .page-header-fixed to fix/unfix header.

I am applying the following transition in all cases:

-webkit-transition: all 1s ease;
-moz-transition: all 1s ease;
-ms-transition: all 1s ease;
-o-transition: all 1s ease;
transition: all 1s ease;

For the header itself (#1), I am using the following selector to fix the header and change the height:

#page-header-wrapper .page-header-fixed {
    position: fixed;
    height: 60px;
    top: 0;
}

while for the other elements (#2 & #3) I am using this

.page-header-fixed .hd-icon {
    width: 25px;
    height: 25px;
}
.page-header-fixed .hd-center {
    font-size: 36px;
}

I expect the .hd-icon to animate from 50x50->25x25 and .hd-center to animate from 48px->36px when the header becomes fixed but both change instantaneously. The header height animates from 100px->60px though.

Is there something with multiple concurrent transitions that I'm not doing correctly, or the way I am targeting the elements?

JSFiddle demo here http://jsfiddle.net/9n90802j/

funkadelic
  • 183
  • 3
  • 14

2 Answers2

1

This one works: http://jsfiddle.net/Whre/9Lk5ym52/

I did the following changes:

JS:

window.setTimeout(function() {
    $("#page-header .hd-icon,#page-header .hd-center").addClass("scrolled");
},10);

respectively removeClass().

CSS:

.hd-icon.scrolled {
    width: 25px;
    height: 25px;
}

.hd-center.scrolled {
    font-size: 36px;
}

I actually don't know what the problem is. I think the browser isn't able to realise there are transitions to do for this child elements. I just know that your example doesn't work without the setTimeout(). If someone has an idea, please let me know!

SVSchmidt
  • 6,269
  • 2
  • 26
  • 37
  • thanks for the workaround. too bad a setTimeout() is needed, but at least it works. :) My fiddle seems to not work on Chrome or Firefox, so i'm thinking that it's something I'm doing incorrectly with the transitions or the structure of my markup...I'll update if I ever figure out what is going on or if I find a different workaround – funkadelic Aug 21 '14 at 16:46
0

I had this problem recently, and the solution was the same as yours: setTimeout() wrapping the jQuery.addClass() fixed it. My best guess at the time was that the browser didn't consider the transition to be necessary to the rendering algorithm, to save time like how multiple DOM changes will be combined into a single redraw, but setTimeout() gave the browser a forced "reset" to consider the transition separately.

I was partially right. It's by design, that a transition too soon after a DOM element is added or unhidden will be considered already in its transitioned state. Quoting MDN:

Care should also be taken when using a transition immediately after adding the element to the DOM using .appendChild() or removing its display: none; property. This is seen as if the initial state had never occurred and the element was always in its final state. The easy way to overcome this limitation is to apply a window.setTimeout() of a handful of milliseconds before changing the CSS property you intend to transition to.

I don't see your code appending or unhiding anything, like mine was, but I think the browser is believing your transition is unnecessary until setTimeout() forces it to calculate the initial state before the transition class is applied.

EDIT

In my case, I actually had to delay the initial state added when the page loads (for an initial animation of parts sliding in over a slideshow) by 400 ms for the browser to actually consider the transition worth honoring. Considering these CSS3 transitions feel unreliable by script (no user interaction that most examples demonstrate), more like a suggestion to the browser, it would probably be better to use CSS3 keyframes instead like this answer explains to have full control over when the transition occurs.

Community
  • 1
  • 1
jimp
  • 16,999
  • 3
  • 27
  • 36