In-N-Out Animation using sibling-index()

ibobev1 pts0 comments

In-N-Out Animation using sibling-index() – Master.dev Blog

/ BLOG

AnimationCSSsibling-index()

In-N-Out Animation using sibling-index()

Temani Afif<br>on<br>July 13, 2026

Chris shared a nice series of articles focused on animating elements in and out of view. The first two articles were about popups & dialogs that required no JavaScript. CSS gives us native ways to open/close those elements while having cool animations. The third article was about view transitions, and while it’s a powerful CSS feature, some JavaScript code is still required to make it work.

Here is the original demo where you can add/remove items and everything adjusts smoothly:

CodePen Embed Fallback

All the effects are managed with CSS, and the JavaScript is just the basic code to trigger the view transitions. Compared to some heavy JS libraries, it’s pretty minimal, and that’s cool.

In this article, I will explore another CSS-only idea that doesn’t require JavaScript (except for the one to add/remove DOM elements).

At the time of writing, only Chrome and Edge fully support the features we will be using.

Here is my version of the same demo:

CodePen Embed Fallback

It’s not exactly the same as the original demo, but the CSS code required to achieve that effect is pretty small and relies mainly on one feature: sibling-index().

I suppose you are curious to know how it works, right? Let’s get started!

The Technique

The sibling-index() function in CSS returns the index of an element among its siblings. We generally consider the index to be static/fixed, which is the case in most situations, but what if we add/remove elements? The index gets updated to match the new HTML structure.

Take the following example:

div class="container"><br>div>reddiv><br>div>greendiv><br>div>bluediv><br>div>yellowdiv><br>div>Code language: HTML, XML (xml)

If we remove the “green” element, the structure becomes:

div class="container"><br>div>reddiv><br>div>bluediv><br>div>yellowdiv><br>div>Code language: HTML, XML (xml)

The index of “blue” and “yellow” have changed. If I use the index within a property and I apply a transition to that property, I will get an animation.

Here is a basic demo. Click remove and see what happens:

CodePen Embed Fallback

The CSS code is as simple as:

.container {<br>display: grid;<br>.container div {<br>grid-area: 1/1;<br>width: 150px;<br>translate: calc((sibling-index() - 1)*160px);<br>transition: .4s;<br>}Code language: CSS (css)

All the elements are placed on top of each other (using grid-area: 1/1), then translated using their indexes.

If an element is removed/added, the indexes are updated, and the translate values are recalculated, creating a nice animation thanks to the transition. With that simple trick, we can create in-and-out animations!

The Demo

Let’s get back to our demo and understand what’s going on. Here is the main CSS code:

ul {<br>display: grid;<br>ul > li {<br>--g: .5rem; /* gap between items */

grid-area: 1/1;<br>translate: 0 calc((sibling-index() - 1)*(100% + var(--g)));<br>transition: .5s;

@starting-style {<br>opacity: 0;<br>transform: translatex(-80%);<br>}Code language: CSS (css)

I simply added a @starting-style declaration. That’s what controls the entry effect when a new element is added to the DOM. I am using opacity combined with a left translation to match the demo created by Chris, but it can be anything.

Here is a different entry effect using scale and opacity:

CodePen Embed Fallback

That’s all. With less than 10 lines of CSS, I managed to get a cool effect.

The Drawbacks

Now, let’s talk about the drawbacks of this method. I am using translate to place the elements, which means we are working with out-of-flow content. In our case, the width of the list is good, but the height is not, and the items are overflowing their container. In some situations, it’s fine, but in others, we may need to find some workarounds to avoid this overflow.

About the height, all the items need to have the same height, otherwise we cannot apply this technique. Even if the items don’t have the same height, I am forcing that by using grid-area: 1/1. By placing all the items in the same grid area, I will get an area with a height equal to the tallest item and all items will, by default, get stretched inside that area.

Here is the previous demo where I made the second item bigger:

CodePen Embed Fallback

All the items will follow that height (unless you change the alignment). It’s still a drawback, but at least the layout is not broken, and everything works fine.

In our demo, it was about height, but in other demos, it can be width, so let’s say there is a fixed size to respect (either the height, the width, or both).

The last drawback is that we don’t really have an out animation. Removing an element will adjust all the others perfectly, but the removed element has no animation. It’s not really a drawback because we don’t have a native CSS mechanism to do this like @starting-style (maybe an @ending-style in the future?). For this reason, Chris explored the view...

index using code demo items height

Related Articles