惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Engineering at Meta
Engineering at Meta
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
腾讯CDC
宝玉的分享
宝玉的分享
量子位
Recent Announcements
Recent Announcements
Martin Fowler
Martin Fowler
J
Java Code Geeks
V
Visual Studio Blog
阮一峰的网络日志
阮一峰的网络日志
Blog — PlanetScale
Blog — PlanetScale
大猫的无限游戏
大猫的无限游戏
博客园 - 叶小钗
S
SegmentFault 最新的问题
B
Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 【当耐特】
小众软件
小众软件
The Cloudflare Blog
Y
Y Combinator Blog
I
InfoQ
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
GbyAI
GbyAI
IT之家
IT之家

Anthony Fu

Anthony Fu Anthony Fu Anthony Fu Anthony Fu Anthony Fu Anthony Fu Anthony Fu Anthony Fu Anthony Fu Anthony Fu Anthony Fu Anthony Fu Anthony's Roads to Open Source - The Set Theory (React ver.) Mental Health in Open Source The Evolution of Shiki v1.0 The Magic in Shiki Magic Move Anthony's Roads to Open Source - The Progressive Path Anthony Fu Anthony Fu Anthony Fu Anthony's Roads to Open Source - The Set Theory Now, and the Future of Nuxt Devtools Anthony's Roads to Open Source - The Set Theory Anthony Fu Anthony Fu Stable Diffusion QR Code 101 Refining AI Generated QR Code Stylistic QR Code with Stable Diffusion Anthony Fu How I Manage GitHub Notifications
Anthony Fu
Anthony Fu · 2023-05-07 · via Anthony Fu

As you might notice, I recently added a sliding enter effect to almost all the pages in my blog. And I quite like it. If you missed it, refresh the page to see it in action.

This effect is inspired by paco.me - the portfolio of Paco Coursey, one of my favorite developer-designers.

In this blog post, let’s break it down and implement one our own.

Breakdown

If you go inspecting the source code of paco.me, you will find that it’s implemented with CSS animation, and it’s quite concise:

@keyframes enter {
  0% {
    opacity: 0;
    transform: translateY(10px);
  }

  to {
    opacity: 1;
    transform: none;
  }
}

[data-animate] {
  --stagger: 0;
  --delay: 120ms;
  --start: 0ms;
}

@media (prefers-reduced-motion: no-preference) {
  [data-animate] {
    animation: enter 0.6s both;
    animation-delay: calc(var(--stagger) * var(--delay) + var(--start));
  }
}

[data-animation-controller='false'] [data-animate] {
  animation: none;
}

And in the HTML usage, we have:

<p style="--stagger: 1" data-animate>Block 1</p>
<p style="--stagger: 2" data-animate>Block 2</p>

It defines a keyframe animation enter that slides the element up by 10px and fades, creating the gentle "floating" effect. The key point is the animation-delay property - assigning a different delay to each element/block, making them have the effect of enter one by one. Then, some CSS variables are used to make the the delay sequence easier to control.

Applying to Contents

Now with it, we should be able to add nice sliding enter animation to our layout and homepage, etc. Even though it can be a bit verbose to add style to each element, it gives you full control of what and when those animations take place.

However, when it comes to content like a Markdown page, it will not be that pleasant to wrap each paragraph with a <p> tag and add the data-animate attribute. So I begin to wonder if there is an easier way to apply to all my posts.

I started messing up with the CSS Counters, an interesting way allowing you to store some numeric variables inside of CSS.

So it should be something like this, where you can add slide-enter-content class wrapping the generated content of a Markdown page:

.slide-enter-content {
  counter-reset: enter-count;
}

.slide-enter-content > p {
  --stagger: 0;
  --delay: 150ms;
  --start: 0ms;
  animation: slide-enter 1s both 1;
  animation-delay: calc(var(--start) + var(--stagger) * var(--delay));
}

.slide-enter-content > p {
  counter-increment: enter-count;
  --stagger: counter(enter-count);
}

It all seems to make sense, but it actually doesn’t work. The reason is that the counter() function returns a string instead of a number and currently there is no way to convert it to a number, in which the calc() function will fail to compute. There are some discussions & proposals about this, but it seems not going to happen very soon.

So as a workaround, which also been posted in the previous link, we can use the nth-child() selector to achieve the same effect, manually:

.slide-enter-content > * {
  --stagger: 0;
  --delay: 150ms;
  --start: 0ms;
  animation: slide-enter 1s both 1;
  animation-delay: calc(var(--start) + var(--stagger) * var(--delay));
}

.slide-enter-content > *:nth-child(1) { --stagger: 1; }
.slide-enter-content > *:nth-child(2) { --stagger: 2; }
.slide-enter-content > *:nth-child(3) { --stagger: 3; }
.slide-enter-content > *:nth-child(4) { --stagger: 4; }
.slide-enter-content > *:nth-child(5) { --stagger: 5; }
.slide-enter-content > *:nth-child(6) { --stagger: 6; }
.slide-enter-content > *:nth-child(7) { --stagger: 7; }
.slide-enter-content > *:nth-child(8) { --stagger: 8; }
.slide-enter-content > *:nth-child(9) { --stagger: 9; }
.slide-enter-content > *:nth-child(10) { --stagger: 10; }
.slide-enter-content > *:nth-child(11) { --stagger: 11; }
.slide-enter-content > *:nth-child(12) { --stagger: 12; }
.slide-enter-content > *:nth-child(13) { --stagger: 13; }
.slide-enter-content > *:nth-child(14) { --stagger: 14; }
.slide-enter-content > *:nth-child(15) { --stagger: 15; }
.slide-enter-content > *:nth-child(16) { --stagger: 16; }
.slide-enter-content > *:nth-child(17) { --stagger: 17; }
.slide-enter-content > *:nth-child(18) { --stagger: 18; }
.slide-enter-content > *:nth-child(19) { --stagger: 19; }
.slide-enter-content > *:nth-child(20) { --stagger: 20; }

The limitation is clear, that the animation only applies to a finite number of elements. You could add more CSS rules to support more, but in practice, I think 20 elements are already quite enough as we don’t usually have that many paragraphs fit in one screen.

So that’s it, I have applied this effect to most of the pages as well as the blog posts. Let me know what do you think! And you can find the source code here.