You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在CSS Transform过渡后为字母添加浮动动画并保持位置

问题描述

我希望在.letter元素完成transform过渡后,为每个字母添加浮动动画,且动画过程中字母保持过渡后的指定位置。但我尝试添加动画后,所有字母都会回到初始位置。

原代码

CSS

@import url("https://fonts.googleapis.com/css2?family=Rubik:wght@400;500;600;700&display=swap");
body {
  background-color: black;
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
}

.word {
  transition: 0.3s;
  opacity: 1;
}

p,
a {
  color: #fff;
  font-size: 5vw;
  font-family: "Rubik", sans-serif;
  text-transform: uppercase;
  margin: 0;
  text-decoration: none;
  letter-spacing: 2px;
}

.line {
  display: flex;
  justify-content: space-between;
}

.fancy {
  cursor: pointer;
}

#txt:has(.fancy:hover) .word:not(.fancy:hover) {
  opacity: 0.2;
}

.letter {
  display: inline-block;
  transition: all 0.6s ease;
}

.fancy:hover .letter:nth-child(1) {
  transform: translate(-40%, 60%) rotate(8deg);
}

.fancy:hover .letter:nth-child(2) {
  transform: translate(20%, -60%) rotate(0deg);
}

.fancy:hover .letter:nth-child(3) {
  transform: translate(-70%, 80%) rotate(-3deg);
}

.fancy:hover .letter:nth-child(4) {
  transform: translate(-30%, -45%) rotate(3deg);
}

.fancy:hover .letter:nth-child(5) {
  transform: translate(0%, 20%) rotate(7deg);
}

.fancy:hover .letter:nth-child(6) {
  transform: translate(10%, 30%) rotate(2deg);
}

.fancy:hover .letter:nth-child(7) {
  transform: translate(20%, 60%) rotate(3deg);
}

.fancy:hover .letter:nth-child(8) {
  transform: translate(-20%, 30%) rotate(4deg);
}

.fancy:hover .letter:nth-child(9) {
  transform: translate(69%, 0%) rotate(-3deg);
}

.fancy:hover .letter:nth-child(10) {
  transform: translate(12%, 18%) rotate(5deg);
}

.fancy:hover .letter:nth-child(11) {
  transform: translate(15%, -10%) rotate(-5deg);
}

.fancy:hover .letter:nth-child(12) {
  transform: translate(0%, 60%) rotate(9deg);
}

HTML

<div id="txt">
  <div class="line">
    <p class="word">A</p>
    <p class="word">Person</p>
  </div>
  <div class="line">
    <p class="word">Youtube</p>
    <p class="word">&</p>
  </div>
  <div class="line">
    <a id="yt-link" href="www.youtube.com" class="word fancy" target="_blank"><span class="letter">C</span><span class="letter">o</span><span class="letter">d</span><span class="letter">e</span><span class="letter">p</span><span class="letter">e</span><span class="letter">n</span><span class="letter">d</span><span class="letter">e</span><span class="letter">n</span><span class="letter">c</span><span class="letter">e</span></a>
  </div>
  <div class="line">
    <a id="yt-link" href="www.youtube.com" class="word fancy" target="_blank"><span class="letter">@</span><span class="letter">h</span><span class="letter">y</span><span class="letter">p</span><span class="letter">e</span><span class="letter">r</span><span class="letter">p</span><span class="letter">l</span><span class="letter">e</span><span class="letter">x</span><span class="letter">e</span><span class="letter">d</span></a>
  </div>
</div>

解决方案

问题根源是CSS动画会直接覆盖transform属性,导致hover时设置的位置被重置。下面是具体的解决方法:

修改后的CSS代码

@import url("https://fonts.googleapis.com/css2?family=Rubik:wght@400;500;600;700&display=swap");
body {
  background-color: black;
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
}

.word {
  transition: 0.3s;
  opacity: 1;
}

p,
a {
  color: #fff;
  font-size: 5vw;
  font-family: "Rubik", sans-serif;
  text-transform: uppercase;
  margin: 0;
  text-decoration: none;
  letter-spacing: 2px;
}

.line {
  display: flex;
  justify-content: space-between;
}

.fancy {
  cursor: pointer;
}

#txt:has(.fancy:hover) .word:not(.fancy:hover) {
  opacity: 0.2;
}

.letter {
  display: inline-block;
  transition: all 0.6s ease;
}

/* 定义浮动动画:基于hover后的位置做小幅度偏移 */
@keyframes float {
  0%, 100% {
    transform: inherit; /* 继承hover时的transform值 */
  }
  25% {
    transform: inherit translate(5%, -5%); /* 在原有位置基础上叠加偏移 */
  }
  50% {
    transform: inherit translate(-3%, 3%);
  }
  75% {
    transform: inherit translate(2%, -2%);
  }
}

/* hover时先完成过渡,再启动浮动动画 */
.fancy:hover .letter {
  animation: float 2s ease-in-out infinite;
  animation-delay: 0.6s; /* 等待过渡完成(0.6s)后再触发动画 */
}

.fancy:hover .letter:nth-child(1) {
  transform: translate(-40%, 60%) rotate(8deg);
}

.fancy:hover .letter:nth-child(2) {
  transform: translate(20%, -60%) rotate(0deg);
}

.fancy:hover .letter:nth-child(3) {
  transform: translate(-70%, 80%) rotate(-3deg);
}

.fancy:hover .letter:nth-child(4) {
  transform: translate(-30%, -45%) rotate(3deg);
}

.fancy:hover .letter:nth-child(5) {
  transform: translate(0%, 20%) rotate(7deg);
}

.fancy:hover .letter:nth-child(6) {
  transform: translate(10%, 30%) rotate(2deg);
}

.fancy:hover .letter:nth-child(7) {
  transform: translate(20%, 60%) rotate(3deg);
}

.fancy:hover .letter:nth-child(8) {
  transform: translate(-20%, 30%) rotate(4deg);
}

.fancy:hover .letter:nth-child(9) {
  transform: translate(69%, 0%) rotate(-3deg);
}

.fancy:hover .letter:nth-child(10) {
  transform: translate(12%, 18%) rotate(5deg);
}

.fancy:hover .letter:nth-child(11) {
  transform: translate(15%, -10%) rotate(-5deg);
}

.fancy:hover .letter:nth-child(12) {
  transform: translate(0%, 60%) rotate(9deg);
}

关键修改说明

  1. 继承transform值:动画中用transform: inherit保留hover时设置的位置,避免覆盖。
  2. 叠加偏移效果:在关键帧里基于继承的transform添加小幅度偏移,实现浮动。
  3. 延迟启动动画:通过animation-delay: 0.6s让动画等过渡完成后再开始,确保字母先到位再浮动。
  4. 统一添加动画规则:给所有.fancy:hover .letter统一绑定动画,减少重复代码。

内容的提问来源于stack exchange,提问作者Ahmed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 02:54:58