Solution 1 :

CSS transitions need a property to animate, and you need to change that property. Since there isn’t a height or opacity change in the rules, it can’t animate. The nested components that actually change in response to the data collection changing come in and out of the DOM which is a change.

So, you have a couple of options:

  • Set a height to your container and change that with C# so that it travels to the DOM and do a CSS animation on it. This is going to be tough – you need to somehow calculate how tall you want your container.

  • Hide all the content for a bit, then await Task.Delay(20); to let it render, then show it again (a simple if-block) – that can let initial css animation do its work. The caveat is that you will do a lot of DOM changes, maybe lose data (so you maybe need to do some state management) and the screen will flicker badly.

  • Do animations with JS – when you alter the collection, get the current content height (the parent must have some height set and maybe hidden overflow, there are a few ways to setup the container so you can get the actual content size), and use JS to animate to the new height. That’s the general way animations are done – with JS, when you need particular dimensions and settings.

  • Try toggling a class on the main wrapping element that will contain the desired animation (such as fade), something like the pseudocode below

<div class="my-card @AnimationClass">
 . . .
</div>

@code{
string AnimationClass {get;set;} = string.Empty;
ObservableCollection<TItem> MyList {get;set;} = new ObservableCollection<TItem>();
void OnInitialized()
{
  MyList.CollectionChanged += MyCollectionChangedHandler;
}

//I don't remember the exact syntax here, if it can't take a Task, use Task.Run in the body to do the async work
async Task MyCollectionChangedHandler(object sender, NotifyCollectionChangedEventArgs e)
{
  AnimationClass = "my-anination-class";
  await InvokeAsync(StateHasChanged);
  await Task.Delay(500); // about the time of your animation
  AnimationClass = "";
}

void Dispose()
{
  MyList.CollectionChanged -= MyCollectionChangedHandler;
}
}

Problem :

I have a container that displays input fields based on list. The user changes data in the displayed fields and more or less input will appear. The issue is that the container instantly changes to the size required and it is jarring. I would like an animation to ease the change in size.

body{
  background: lightblue;
}
.my-card{
    align-self: center;
    padding: 20px;
    margin: 0 auto;
    width: auto;
    border-radius: 4px;
    display: inline-block;
    background-color: #F2F2F2;
    color: black;
    box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
    border: 1px solid rgba(0,0,0,0);
    bottom: 1px;

-webkit-transform-origin:top;
    -moz-animation: fadein 2000ms; /* Firefox */
    -webkit-animation: fadein 2000ms; /* Safari and Chrome */
    -o-animation: fadein 2000ms; /* Opera */
}
.user-data{
    text-align: left;
    font-size: 18px;
    margin: 1px 5px 5px;
    -webkit-transform-origin:top;
    -moz-animation: fadein 2000ms; /* Firefox */
    -webkit-animation: fadein 2000ms; /* Safari and Chrome */
    -o-animation: fadein 2000ms; /* Opera */
}

@keyframes fadein {
    from {
        opacity:0;
    }
    to {
        opacity:1;
    }
}
@-moz-keyframes fadein { /* Firefox */
    from {
        opacity:0;
    }
    to {
        opacity:1;
    }
}
@-webkit-keyframes fadein { /* Safari and Chrome */
    from {
        opacity:0;
    }
    to {
        opacity:1;
    }
}
@-o-keyframes fadein { /* Opera */
    from {
        opacity:0;
    }
    to {
        opacity: 1;
    }
}
<div class="my-card">
  <div class="user-data">
    <div>header text</div>
    <input type="text" />
  </div>
</div>

The new user-data fades in nicely but the my-card makes the change with no animation. The my-card does animate on the first load.

Is there some event on the for my-card like hover for the change in size?

Note: The HTML of the snippet is not exact, as this is Blazor. The data is populated with a foreach and in the foreach there is logic to determine what gets displayed. A better idea of what the actual HTLM is is something like this:

<div class="my-card">
    @foreach (var x in MyList)
    {
        @if (x.Show == 1)
        {
            <div class="user-data">
                <div>@x.HeaderText</div>
                <input type="text" @bind="@x.StringValue" />
            </div>
        }
    }
</div>

By