Animating Anchors

02 April 2026

Updated: 02 April 2026

I was playing around a bit with position-anchor and wondered how easy it would be to animate. The answer: relatively.

Using Transitions

It was relatively automatic using CSS Transitions, as you can see below:

anchor-positioning/transition.html
1
<section class="demo-transition">
2
<div class="container">
3
<animate-initial>
4
<animate-item onclick="this.toggleAttribute('docked')">Item</animate-item>
5
</animate-initial>
6
</div>
7
8
<animate-target>Box for Items</animate-target>
9
</section>
anchor-positioning/transition.css
1
.demo-transition {
2
height: 200px;
3
padding-top: 100px;
4
position: relative;
5
6
.container {
7
gap: 10px;
8
padding: 20px;
9
}
10
11
animate-initial {
12
anchor-name: --anchor-initial;
13
}
14
15
animate-item {
16
position-anchor: --anchor-initial;
17
position: fixed;
18
top: anchor(top);
19
left: anchor(left);
20
z-index: 1;
21
22
width: 100px;
23
24
background-color: cadetblue;
25
padding: 10px;
26
display: inline-block;
27
28
transition: top 1s, left .3s;
29
30
&[docked] {
31
position-anchor: --animate-target;
32
position: fixed;
33
top: calc(anchor(top) + 10px);
34
left: calc(anchor(left) + 10px);
35
}
36
}
37
38
animate-target {
39
anchor-name: --animate-target;
40
41
background-color: lightblue;
42
opacity: 0.3;
43
padding: 20px;
44
width: 100px;
45
46
position: absolute;
47
bottom: 20px;
48
right: 20px;
49
}
50
}

Using Animations

Animations were a little more fiddly but eventually using the anchor(--anchor-name) function directly instead trying to implicily get it via anchor() and position-anchor worked:

anchor-positioning/animation.html
1
<section class="demo-animation">
2
<div class="container">
3
<animate-initial>
4
<animate-item onclick="this.toggleAttribute('docked')">Item</animate-item>
5
</animate-initial>
6
</div>
7
8
<animate-target>Box for Items</animate-target>
9
</section>
anchor-positioning/animation.css
1
@keyframes move-to-target {
2
0% {
3
position: fixed;
4
top: anchor(--anchor-initial top);
5
left: anchor(--anchor-initial left);
6
}
7
8
20% {
9
position: fixed;
10
top: calc(anchor(--anchor-initial top) - 50px);
11
left: anchor(--anchor-initial left);
12
}
13
14
100% {
15
position: fixed;
16
top: calc(anchor(--anchor-target top) + 10px);
17
left: calc(anchor(--anchor-target left) + 10px);
18
}
19
}
20
21
.demo-animation {
22
padding-top: 100px;
23
height: 200px;
24
position: relative;
25
26
.container {
27
gap: 10px;
28
padding: 20px;
29
}
30
31
animate-initial {
32
anchor-name: --anchor-initial;
33
}
34
35
animate-item {
36
--animate-intial: --anchor-initial;
37
--animate-target: --anchor-target;
38
39
z-index: 1;
40
41
width: 100px;
42
43
background-color: cadetblue;
44
padding: 10px;
45
display: inline-block;
46
47
&[docked] {
48
animation: move-to-target 1s forwards;
49
}
50
}
51
52
animate-target {
53
anchor-name: --anchor-target;
54
55
background-color: lightblue;
56
opacity: 0.3;
57
padding: 20px;
58
width: 100px;
59
60
position: absolute;
61
bottom: 20px;
62
right: 20px;
63
}
64
}

Additional Reading

And that’s about it, I suppose this could use further explanation but there aren’t too many concepts explained here that hasn’t been covered already in my post about CSS Anchor Positioning and my talk on Web Animation so take a look at those if you’re interested