0

I have a code, which looks like this:

<div ng-repeat="row in rows" class="my">
  <img ng-src="{{row.pictureUrl}}">
  {{row.text}}
</div>

The current implementation looks like this (it is CSS in Stylus format), supposed to look like slide down effect:

$slowAnimationDuration = 100ms
.my
&.ng-animate
    transition:all
    animation-iteration-count 1
    animation-duration $slowAnimationDuration
&.ng-enter
    animation-name fadeInQuick
    animation-timing-function ease-out
&.ng-leave
    animation-name fadeOutQuick
    animation-timing-function ease-in

@keyframes fadeInQuick 
  0% 
    height 0
    opacity  0
  20%
    height calc(0.5em + 1vh + 1px)
  50%
    opacity 0.05
  100%
    height calc(1em + 2vh + 2px)
    opacity 1

@keyframes fadeOutQuick
  0%
    height calc(1em + 2vh + 2px)
    opacity 1
  100%
    height 0
    opacity 0

This code works, but quality of animation so far so good. The issue is related to the absence of animation to height: auto in CSS. I'm using AngularJS 1.5 and have ngAnimate injected. I can fix the height of the image, but I cannot change or cut the text.

How to make rows animation nicer? Is it even possible?

Update: tried this answer, looks really ugly, for some time page remains empty and after content appears. Also, this squeezing effect doesn't look appealing.

Community
  • 1
  • 1
zoonman
  • 1,116
  • 1
  • 12
  • 30

2 Answers2

0

I believe that most 'collapsible' elements that animate open/close, suffer the same issue.

The way they go about it, is they add two extra states that are applied for the length of the animation. ie. .my would become .my.animatingIn for 100ms, then be changed to .my.animatedIn. The animatingIn class animates to a fixed height.. say 100px.. then the animatedIn class sets it to auto. This gives the illusion of the box expanding, when in fact its animating a bit.. then snapping.

Fortunately, angular has this sort of setup for ng-animate out-of-the-box. Using the name of the animation, and then a -active version.

For example, if you have an animation named animate, during the ngRepeat enter phase, the Angular will attach the class "animate-enter" and them the class "animate-enter-active". Docs

As a result, you should see this working using something like

$slowAnimationDuration = 100ms
.my
&.ng-animate
    transition:all
    animation-iteration-count 1
    animation-duration $slowAnimationDuration
&.ng-enter
    animation-name fadeInQuick
    animation-timing-function ease-out
&.ng-enter-active
    height auto
&.ng-leave
    animation-name fadeOutQuick
    animation-timing-function ease-in
&.ng-leave-active
    height 0

@keyframes fadeInQuick 
  0% 
    height 0
    opacity  0
  20%
    height calc(0.5em + 1vh + 1px)
  50%
    opacity 0.05
  100%
    height calc(1em + 2vh + 2px)
    opacity 1

@keyframes fadeOutQuick
  0%
    height calc(1em + 2vh + 2px)
    opacity 1
  100%
    height 0
    opacity 0

You may also benefit from specifying the way that you want the animate to behave by updating your html to include the ng-animate property

<div ng-repeat="row in rows" class="my" ng-animate="{enter: 'animate-enter', leave: 'animate-leave'}">
  <img ng-src="{{row.pictureUrl}}">
  {{row.text}}
</div>

This would event let you change the current classnames to something like animate-quick-enter so you still retain access to the defaults

haxxxton
  • 6,422
  • 3
  • 27
  • 57
-1

If you know roughly what the height of the element should be, you can animate or transition max-height instead.

div {
  max-height: 50px;
  width: 100px;
  overflow: hidden;
  animation: height .5s forwards;
  animation-delay: 1s;
}

@keyframes height {
  to {
    max-height: 200px;
  }
}
<div>
  <p>asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asd fasdf asdf asdf asd fasd fasdf asdf asdf asdf asdf</p>
</div>
Michael Coker
  • 52,626
  • 5
  • 64
  • 64
  • I saw this trick, but I like this one http://stackoverflow.com/a/17260048/669493 more except the fact of content squeezing during animation. – zoonman Feb 01 '17 at 05:05