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

仅用CSS实现4x4网格方块无限对角线翻转消失动画

纯CSS实现2x2网格方块对角线翻转+隐藏的无限循环动画

我正在制作一个2x2网格方块的对角线逐个翻转动画,目前已实现以下效果:

  • 方块可按需求单独翻转
  • 点击两个方块后它们会消失
  • 点击另外两个方块后,整个网格消失

现在需要实现无限循环动画,具体序列要求:

  1. 显示所有4个方块
  2. 将方块1和4顺时针对角线翻转,延迟后隐藏它们
  3. 对方块2和3重复上述翻转并隐藏的操作
  4. 所有方块隐藏后,重新显示未翻转的所有方块并重启序列

如何仅使用CSS实现这个带方块消失效果的无限循环动画?以下是我的现有代码:

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  font-family: system-ui, sans-serif;
  color: black;
  background-color: rgb(19, 18, 18);
}

@keyframes tileFlipShow {
  from {
    backface-visibility: hidden;
  }
  to {
    transform: rotateY(180deg);
    backface-visibility: visible;
  }
}

@keyframes tileFlipHide {
  from {
    transform: rotateY(180deg);
    backface-visibility: visible;
  }
  to {
    backface-visibility: hidden;
  }
}

@keyframes hideTile {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
  }
}

.grid-container {
  display: grid;
  justify-content: center;
  align-items: center;
  height: 100vh;
}

.tile-grid {
  display: grid;
  grid-gap: 1px;
  grid-template-columns: repeat(2, 1fr);
  max-width: fit-content;
}

.tile-grid>div:nth-child(1) {
  animation-delay: 1.5s;
}

.tile-grid>div:nth-child(1) .flip-card-inner {
  animation-delay: 0s;
}

.tile-grid>div:nth-child(4) {
  animation-delay: 1.5s;
}

.tile-grid>div:nth-child(4) .flip-card-inner {
  animation-delay: 1s;
}

.tile-grid>div:nth-child(2) {
  animation-delay: 3.5s;
}

.tile-grid>div:nth-child(2) .flip-card-inner {
  animation-delay: 2s;
}

.tile-grid>div:nth-child(3) {
  animation-delay: 3.5s;
}

.tile-grid>div:nth-child(3) .flip-card-inner {
  animation-delay: 3s;
}

.flip-card {
  perspective: 1000px;
  margin: 1px;
  cursor: pointer;
  height: 9.375rem;
  width: 9.375rem;
  min-width: 3.125rem;
  min-height: 3.125rem;
  max-height: 9.375rem;
  max-width: 9.375rem;
  font-size: 1em;
  transition: all 0.2s ease-in-out;
  animation: 0.5s hideTile both;
}

.flip-card-inner {
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
  transition: transform 0.5s;
  animation: 0.5s tileFlipShow both;
}

.flip-card-front {
  height: 100%;
  width: 100%;
  position: absolute;
  backface-visibility: hidden;
  background-color: #3498db;
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.2rem;
}

.flip-card-front * {
  padding: 0;
  margin: 0;
  max-width: 100%;
  max-height: 100%;
  color: #fff;
}

.flip-card-back {
  height: 100%;
  width: 100%;
  position: absolute;
  backface-visibility: hidden;
  background-image: linear-gradient(-45deg, #ffc796 0%, #ff6b95 100%);
  backdrop-filter: blur(10rem);
  transform: rotateY(180deg);
  display: flex;
  align-items: center;
  justify-content: center;
}

.flip-card-back * {
  padding: 0;
  margin: 0;
  max-width: 100%;
  max-height: 100%;
  color: #fff;
}

.flip-card-back img {
  width: auto;
  height: 90%;
}

.flip-card-back picture {
  width: auto;
  height: 90%;
}

.flip-card-matched {
  visibility: hidden;
}

.flip-counter {
  position: absolute;
  top: 0;
  right: 0;
  z-index: 1;
  font-size: 0.5rem;
  display: none;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <title>Bootstrap 5 example</title>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width" />
  <link rel="stylesheet" href="styles.css" />
</head>

<body>
  <div class="container">
    <div class="grid-container">
      <div class="tile-grid">
        <div class="flip-card">
          <div class="flip-card-inner not-matched">
            <div class="flip-card-front">1</div>
            <div class="flip-card-back">11</div>
          </div>
        </div>
        <div class="flip-card">
          <div class="flip-card-inner not-matched">
            <div class="flip-card-front">2</div>
            <div class="flip-card-back">22</div>
          </div>
        </div>
        <div class="flip-card">
          <div class="flip-card-inner not-matched">
            <div class="flip-card-front">3</div>
            <div class="flip-card-back">22</div>
          </div>
        </div>
        <div class="flip-card">
          <div class="flip-card-inner not-matched">
            <div class="flip-card-front">4</div>
            <div class="flip-card-back">11</div>
          </div>
        </div>
      </div>
    </div>
  </div>
</body>

</html>

解决方案

要实现纯CSS无限循环,需调整动画的时长、循环属性,将翻转和隐藏整合为连贯的循环序列,确保每个方块的动画周期与整体循环同步。

修改后的完整代码

CSS 代码

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  font-family: system-ui, sans-serif;
  color: black;
  background-color: rgb(19, 18, 18);
}

/* 整合翻转+隐藏的完整循环动画 */
@keyframes flipAndHide {
  0% {
    opacity: 1;
    transform: rotateY(0deg);
  }
  10% { /* 开始翻转 */
    transform: rotateY(180deg);
  }
  30% { /* 保持翻转状态 */
    transform: rotateY(180deg);
  }
  40% { /* 开始隐藏 */
    opacity: 0;
    transform: rotateY(180deg);
  }
  90% { /* 保持隐藏 */
    opacity: 0;
    transform: rotateY(180deg);
  }
  95% { /* 重置为初始状态(未翻转、显示) */
    opacity: 1;
    transform: rotateY(0deg);
  }
  100% {
    opacity: 1;
    transform: rotateY(0deg);
  }
}

.grid-container {
  display: grid;
  justify-content: center;
  align-items: center;
  height: 100vh;
}

.tile-grid {
  display: grid;
  grid-gap: 1px;
  grid-template-columns: repeat(2, 1fr);
  max-width: fit-content;
}

/* 方块1的动画:总周期8s,延迟0s */
.tile-grid > div:nth-child(1) .flip-card-inner {
  animation: flipAndHide 8s infinite both;
}

/* 方块4的动画:总周期8s,延迟0.5s(和方块1错开一点) */
.tile-grid > div:nth-child(4) .flip-card-inner {
  animation: flipAndHide 8s 0.5s infinite both;
}

/* 方块2的动画:总周期8s,延迟3s(等1、4隐藏后开始) */
.tile-grid > div:nth-child(2) .flip-card-inner {
  animation: flipAndHide 8s 3s infinite both;
}

/* 方块3的动画:总周期8s,延迟3.5s(和方块2错开一点) */
.tile-grid > div:nth-child(3) .flip-card-inner {
  animation: flipAndHide 8s 3.5s infinite both;
}

.flip-card {
  perspective: 1000px;
  margin: 1px;
  cursor: pointer;
  height: 9.375rem;
  width: 9.375rem;
  min-width: 3.125rem;
  min-height: 3.125rem;
  max-height: 9.375rem;
  max-width: 9.375rem;
  font-size: 1em;
  opacity: 1; /* 初始显示 */
}

.flip-card-inner {
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
}

.flip-card-front {
  height: 100%;
  width: 100%;
  position: absolute;
  backface-visibility: hidden;
  background-color: #3498db;
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.2rem;
}

.flip-card-front * {
  padding: 0;
  margin: 0;
  max-width: 100%;
  max-height: 100%;
  color: #fff;
}

.flip-card-back {
  height: 100%;
  width: 100%;
  position: absolute;
  backface-visibility: hidden;
  background-image: linear-gradient(-45deg, #ffc796 0%, #ff6b95 100%);
  backdrop-filter: blur(10rem);
  transform: rotateY(180deg);
  display: flex;
  align-items: center;
  justify-content: center;
}

.flip-card-back * {
  padding: 0;
  margin: 0;
  max-width: 100%;
  max-height: 100%;
  color: #fff;
}

.flip-card-back img {
  width: auto;
  height: 90%;
}

.flip-card-back picture {
  width: auto;
  height: 90%;
}

.flip-card-matched {
  visibility: hidden;
}

.flip-counter {
  position: absolute;
  top: 0;
  right: 0;
  z-index: 1;
  font-size: 0.5rem;
  display: none;
}

HTML 代码(无需修改)

<!DOCTYPE html>
<html lang="en">

<head>
  <title>Bootstrap 5 example</title>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width" />
  <link rel="stylesheet" href="styles.css" />
</head>

<body>
  <div class="container">
    <div class="grid-container">
      <div class="tile-grid">
        <div class="flip-card">
          <div class="flip-card-inner not-matched">
            <div class="flip-card-front">1</div>
            <div class="flip-card-back">11</div>
          </div>
        </div>
        <div class="flip-card">
          <div class="flip-card-inner not-matched">
            <div class="flip-card-front">2</div>
            <div class="flip-card-back">22</div>
          </div>
        </div>
        <div class="flip-card">
          <div class="flip-card-inner not-matched">
            <div class="flip-card-front">3</div>
            <div class="flip-card-back">22</div>
          </div>
        </div>
        <div class="flip-card">
          <div class="flip-card-inner not-matched">
            <div class="flip-card-front">4</div>
            <div class="flip-card-back">11</div>
          </div>
        </div>
      </div>
    </div>
  </div>
</body>

</html>

关键改动说明

  1. 整合动画关键帧:将翻转和隐藏合并为一个flipAndHide动画,定义完整循环周期,包含显示→翻转→保持翻转→隐藏→保持隐藏→重置显示的全过程。
  2. 设置无限循环:给动画添加infinite属性,实现自动重复。
  3. 同步动画周期:所有方块使用相同的总动画时长(8s),通过animation-delay控制触发时机,确保序列连贯:
    • 方块1和4先触发翻转,间隔0.5s错开,模拟逐个翻转效果
    • 方块2和3在1、4隐藏后(延迟3s)触发,同样间隔0.5s错开
  4. 移除冲突动画:删除原有的tileFlipShow、hideTile等独立动画,避免冲突,统一使用整合后的循环动画。
  5. 重置初始状态:在动画的95%-100%阶段将方块重置为未翻转、完全显示的状态,为下一轮循环做准备。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 07:29:52