JIT
Grid - Untitled
Create a white candle with a single flame animated with realistic movement using only CSS and HTML (in one file). The sparks should also be animated with smooth movement.
<html> <head> <meta charset="UTF-8"> <title>CSS Candle Flame</title> <style> * { box-sizing: border-box; margin: 0; padding: 0; } html, body { width: 100%; height: 100%; overflow: hidden; font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; background: radial-gradient(circle at 50% 20%, #222 0%, #080808 40%, #000 100%); }
body {
  display: flex;
  align-items: center;
  justify-content: center;
}

.scene {
  position: relative;
  width: min(40vw, 260px);
  height: min(70vh, 700px);
  display: flex;
  align-items: center;
  justify-content: center;
}

.candle-wrapper {
  position: relative;
  width: 40%;
  max-width: 140px;
  min-width: 90px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
}

.candle-body {
  position: relative;
  width: 100%;
  height: 55vh;
  max-height: 420px;
  min-height: 270px;
  background: linear-gradient(180deg,
    #fefefe 0%,
    #f9f9f9 20%,
    #f2f2f2 55%,
    #ececec 100%);
  border-radius: 45% 55% 12% 18% / 8% 8% 20% 20%;
  box-shadow:
    0 0.7vh 2.5vh rgba(0,0,0,0.55),
    inset 0 0.4vh 1.2vh rgba(255,255,255,0.8),
    inset 0 -0.8vh 2vh rgba(0,0,0,0.1);
  overflow: visible;
}

.candle-body::before {
  content: "";
  position: absolute;
  top: -3.2vh;
  left: 50%;
  transform: translateX(-50%);
  width: 92%;
  height: 6vh;
  max-height: 55px;
  background: radial-gradient(circle at 50% 25%, #ffffff 0%, #f6f6f6 45%, #ececec 70%, #dcdcdc 100%);
  border-radius: 50%;
  box-shadow:
    0 0.4vh 0.9vh rgba(0,0,0,0.35),
    inset 0 0.3vh 0.7vh rgba(255,255,255,0.9);
  z-index: 2;
}

.candle-body::after {
  content: "";
  position: absolute;
  bottom: -1.8vh;
  left: 50%;
  transform: translateX(-50%);
  width: 110%;
  height: 4vh;
  max-height: 38px;
  background: radial-gradient(circle at 50% 0%, #b0b0b0 0%, #777 45%, #444 80%, #222 100%);
  border-radius: 50%;
  filter: blur(1px);
  opacity: 0.7;
}

.wick {
  position: absolute;
  top: -3.2vh;
  left: 50%;
  transform: translate(-50%, -40%);
  width: 6%;
  min-width: 4px;
  max-width: 6px;
  height: 2.3vh;
  min-height: 10px;
  max-height: 20px;
  background: linear-gradient(180deg, #333 0%, #000 60%, #2b1507 100%);
  border-radius: 50px;
  box-shadow: 0 -0.2vh 0.4vh rgba(0,0,0,0.5);
  z-index: 4;
}

.flame-wrapper {
  position: absolute;
  bottom: 104%;
  left: 50%;
  transform: translateX(-50%);
  width: 26%;
  min-width: 26px;
  max-width: 40px;
  height: 18vh;
  max-height: 140px;
  min-height: 95px;
  display: flex;
  align-items: center;
  justify-content: center;
  transform-origin: 50% 100%;
  animation: flame-sway 3s ease-in-out infinite;
  z-index: 5;
}

.flame-core {
  position: absolute;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 46%;
  height: 45%;
  background: radial-gradient(circle at 50% 10%, #fffde8 0%, #ffeec4 40%, #ffd08a 80%, rgba(255,185,90,0) 100%);
  border-radius: 50% 50% 60% 60%;
  filter: blur(2px);
  opacity: 0.95;
  animation:
    flame-core-pulse 1.4s ease-in-out infinite,
    flame-core-flicker 200ms linear infinite;
}

.flame {
  position: absolute;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 100%;
  height: 100%;
  background:
    radial-gradient(circle at 50% 18%, #fff9d8 0%, #ffeaa9 20%, transparent 65%),
    radial-gradient(circle at 50% 60%, #ffd26f 0%, #ff9f3b 40%, #f46b45 75%, transparent 100%);
  border-radius: 50% 50% 55% 45% / 80% 80% 30% 30%;
  filter: drop-shadow(0 0 14px rgba(255, 210, 120, 0.9))
          drop-shadow(0 0 26px rgba(255, 170, 60, 0.8));
  clip-path: polygon(50% 0%, 65% 20%, 75% 40%, 70% 65%, 60% 82%, 50% 100%, 40% 82%, 30% 65%, 25% 40%, 35% 18%);
  animation:
    flame-shape 2.8s ease-in-out infinite,
    flame-flicker 180ms linear infinite;
}

.flame-glow {
  position: absolute;
  bottom: -10%;
  left: 50%;
  transform: translateX(-50%);
  width: 250%;
  height: 260%;
  background:
    radial-gradient(circle at 50% 0%, rgba(255,239,200,0.85) 0%, rgba(255,210,120,0.7) 25%, rgba(255,170,60,0.0) 70%);
  opacity: 0.85;
  filter: blur(12px);
  mix-blend-mode: screen;
  animation: glow-pulse 3.6s ease-in-out infinite;
  pointer-events: none;
}

.inner-glow {
  position: absolute;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 120%;
  height: 120%;
  background: radial-gradient(circle at 50% 10%, rgba(255,255,255,0.7) 0%, rgba(255,255,180,0.35) 45%, rgba(255,200,120,0.0) 80%);
  opacity: 0.9;
  filter: blur(8px);
  animation: inner-glow-pulse 2.2s ease-in-out infinite;
  pointer-events: none;
}

.light-on-candle {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 120%;
  height: 40%;
  background: radial-gradient(circle at 50% -10%, rgba(255,250,220,0.95) 0%, rgba(255,243,200,0.7) 20%, rgba(255,240,200,0.0) 65%);
  mix-blend-mode: screen;
  opacity: 0.8;
  filter: blur(14px);
  pointer-events: none;
  animation: candle-light-flicker 2.3s ease-in-out infinite;
  z-index: 1;
}

.drip {
  position: absolute;
  width: 20%;
  background: linear-gradient(180deg, #fefefe 0%, #f1f1f1 50%, #e6e6e6 100%);
  border-radius: 30px;
  box-shadow: inset 0 0.2vh 0.5vh rgba(255,255,255,0.9);
  opacity: 0.95;
}

.drip.d1 {
  height: 14%;
  left: 20%;
  top: 10%;
  animation: drip-sway 5s ease-in-out infinite;
}

.drip.d2 {
  height: 18%;
  right: 18%;
  top: 18%;
  animation: drip-sway 4.5s ease-in-out infinite;
}

.drip.d3 {
  height: 10%;
  left: 55%;
  top: 6%;
  animation: drip-sway 5.6s ease-in-out infinite;
}

.drip::after {
  content: "";
  position: absolute;
  bottom: -10%;
  left: 50%;
  transform: translateX(-50%);
  width: 90%;
  height: 18%;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 40%, #e8e8e8 0%, #dcdcdc 45%, rgba(220,220,220,0) 100%);
  opacity: 0.9;
}

.sparks {
  position: absolute;
  bottom: 104%;
  left: 50%;
  width: 30vw;
  max-width: 400px;
  height: 35vh;
  max-height: 320px;
  transform: translateX(-50%);
  pointer-events: none;
  filter: blur(0.2px);
  z-index: 3;
}

.spark {
  position: absolute;
  width: 0.7vh;
  max-width: 6px;
  min-width: 3px;
  height: 0.7vh;
  max-height: 6px;
  min-height: 3px;
  background: radial-gradient(circle, rgba(255,255,255,0.95) 0%, rgba(255,231,180,0.9) 40%, rgba(255,180,60,0) 100%);
  border-radius: 50%;
  opacity: 0;
  mix-blend-mode: screen;
}

.spark::after {
  content: "";
  position: absolute;
  top: -200%;
  left: 50%;
  transform: translateX(-50%);
  width: 1px;
  height: 200%;
  background: linear-gradient(180deg, rgba(255,220,150,0.6) 0%, rgba(255,180,80,0.0) 100%);
  filter: blur(0.3px);
}

.spark.s1 { left: 0%;    animation: spark-rise-1 3s ease-out infinite; }
.spark.s2 { left: 18%;   animation: spark-rise-2 3.6s ease-out infinite; }
.spark.s3 { left: 35%;   animation: spark-rise-3 3.2s ease-out infinite; }
.spark.s4 { left: 52%;   animation: spark-rise-4 4s ease-out infinite; }
.spark.s5 { left: 68%;   animation: spark-rise-5 3.4s ease-out infinite; }
.spark.s6 { left: 84%;   animation: spark-rise-6 3.7s ease-out infinite; }
.spark.s7 { left: 25%;   animation: spark-rise-7 4.2s ease-out infinite; }
.spark.s8 { left: 60%;   animation: spark-rise-8 3.9s ease-out infinite; }

@keyframes flame-sway {
  0%   { transform: translateX(-50%) rotate(-1.5deg); }
  20%  { transform: translateX(-50%) rotate(1.8deg); }
  45%  { transform: translateX(-50%) rotate(-1deg); }
  65%  { transform: translateX(-50%) rotate(2.2deg); }
  85%  { transform: translateX(-50%) rotate(-0.8deg); }
  100% { transform: translateX(-50%) rotate(-1.5deg); }
}

@keyframes flame-shape {
  0% {
    border-radius: 50% 50% 60% 40% / 80% 85% 35% 35%;
    transform: translateX(-50%) scaleX(1) scaleY(1);
  }
  25% {
    border-radius: 48% 52% 62% 38% / 85% 80% 32% 38%;
    transform: translateX(-50%) scaleX(0.96) scaleY(1.05);
  }
  50% {
    border-radius: 52% 48% 58% 42% / 78% 82% 34% 34%;
    transform: translateX(-50%) scaleX(1.02) scaleY(0.97);
  }
  75% {
    border-radius: 47% 53% 63% 37% / 82% 83% 31% 37%;
    transform: translateX(-50%) scaleX(0.97) scaleY(1.03);
  }
  100% {
    border-radius: 50% 50% 60% 40% / 80% 85% 35% 35%;
    transform: translateX(-50%) scaleX(1) scaleY(1);
  }
}

@keyframes flame-flicker {
  0%   { filter: drop-shadow(0 0 10px rgba(255,210,120,0.8)) drop-shadow(0 0 24px rgba(255,180,60,0.7)); }
  25%  { filter: drop-shadow(0 0 15px rgba(255,225,150,0.9)) drop-shadow(0 0 28px rgba(255,190,80,0.85)); }
  50%  { filter: drop-shadow(0 0 9px rgba(255,205,110,0.75)) drop-shadow(0 0 20px rgba(255,165,50,0.7)); }
  75%  { filter: drop-shadow(0 0 14px rgba(255,230,170,0.95)) drop-shadow(0 0 30px rgba(255,190,90,0.9)); }
  100% { filter: drop-shadow(0 0 10px rgba(255,210,120,0.8)) drop-shadow(0 0 24px rgba(255,180,60,0.7)); }
}

@keyframes flame-core-pulse {
  0%   { transform: translateX(-50%) scale(0.92); opacity: 0.92; }
  30%  { transform: translateX(-50%) scale(1.02); opacity: 1; }
  55%  { transform: translateX(-50%) scale(0.96); opacity: 0.96; }
  80%  { transform: translateX(-50%) scale(1.05); opacity: 1; }
  100% { transform: translateX(-50%) scale(0.92); opacity: 0.92; }
}

@keyframes flame-core-flicker {
  0%   { filter: blur(1.8px); }
  50%  { filter: blur(2.3px); }
  100% { filter: blur(2px); }
}

@keyframes glow-pulse {
  0%   { opacity: 0.7; transform: translateX(-50%) scale(1); }
  25%  { opacity: 0.9; transform: translateX(-50%) scale(1.05); }
  50%  { opacity: 0.75; transform: translateX(-50%) scale(1.02); }
  75%  { opacity: 0.95; transform: translateX(-50%) scale(1.07); }
  100% { opacity: 0.7; transform: translateX(-50%) scale(1); }
}

@keyframes inner-glow-pulse {
  0%   { opacity: 0.8; }
  50%  { opacity: 1; }
  100% { opacity: 0.8; }
}

@keyframes candle-light-flicker {
  0%   { opacity: 0.7; }
  20%  { opacity: 0.92; }
  40%  { opacity: 0.73; }
  60%  { opacity: 0.95; }
  80%  { opacity: 0.78; }
  100% { opacity: 0.7; }
}

@keyframes drip-sway {
  0%   { transform: translateX(0) scaleX(1); }
  25%  { transform: translateX(0.5vw) scaleX(1.02); }
  50%  { transform: translateX(-0.4vw) scaleX(0.98); }
  75%  { transform: translateX(0.3vw) scaleX(1.01); }
  100% { transform: translateX(0) scaleX(1); }
}

@keyframes spark-rise-1 {
  0%   { bottom: 0%; opacity: 0; transform: translateX(0) scale(0.8); }
  10%  { opacity: 0.8; }
  40%  { transform: translateX(-8px) scale(1); }
  80%  { bottom: 95%; opacity: 0.1; transform: translateX(-16px) scale(0.9); }
  100% { bottom: 105%; opacity: 0; }
}

@keyframes spark-rise-2 {
  0%   { bottom: 0%; opacity: 0; transform: translateX(0) scale(0.7); }
  15%  { opacity: 0.9; }
  45%  { transform: translateX(6px) scale(1); }
  85%  { bottom: 100%; opacity: 0.1; transform: translateX(10px) scale(0.85); }
  100% { bottom: 112%; opacity: 0; }
}

@keyframes spark-rise-3 {
  0%   { bottom: 10%; opacity: 0; transform: translateX(0) scale(0.7); }
  10%  { opacity: 0.9; }
  35%  { transform: translateX(4px) scale(1); }
  80%  { bottom: 105%; opacity: 0.1; transform: translateX(-8px) scale(0.85); }
  100% { bottom: 115%; opacity: 0; }
}

@keyframes spark-rise-4 {
  0%   { bottom: 5%; opacity: 0; transform: translateX(0) scale(0.75); }
  12%  { opacity: 0.9; }
  40%  { transform: translateX(-5px) scale(1); }
  78%  { bottom: 110%; opacity: 0.1; transform: translateX(-12px) scale(0.9); }
  100% { bottom: 120%; opacity: 0; }
}

@keyframes spark-rise-5 {
  0%   { bottom: 0%; opacity: 0; transform: translateX(0) scale(0.7); }
  15%  { opacity: 1; }
  50%  { transform: translateX(7px) scale(1); }
  82%  { bottom: 100%; opacity: 0.1; transform: translateX(4px) scale(0.8); }
  100% { bottom: 113%; opacity: 0; }
}

@keyframes spark-rise-6 {
  0%   { bottom: 8%; opacity: 0; transform: translateX(0) scale(0.8); }
  12%  { opacity: 0.9; }
  45%  { transform: translateX(-4px) scale(1); }
  85%  { bottom: 105%; opacity: 0.1; transform: translateX(-10px) scale(0.85); }
  100% { bottom: 118%; opacity: 0; }
}

@keyframes spark-rise-7 {
  0%   { bottom: 5%; opacity: 0; transform: translateX(0) scale(0.65); }
  18%  { opacity: 0.9; }
  48%  { transform: translateX(2px) scale(0.95); }
  85%  { bottom: 105%; opacity: 0.1; transform: translateX(-6px) scale(0.8); }
  100% { bottom: 118%; opacity: 0; }
}

@keyframes spark-rise-8 {
  0%   { bottom: 5%; opacity: 0; transform: translateX(0) scale(0.7); }
  14%  { opacity: 0.95; }
  50%  { transform: translateX(-3px) scale(1); }
  85%  { bottom: 110%; opacity: 0.1; transform: translateX(6px) scale(0.9); }
  100% { bottom: 122%; opacity: 0; }
}

@media (max-width: 700px) {
  .scene {
    width: 70vw;
    height: 80vh;
  }
  .candle-body {
    height: 48vh;
  }
}
</style> </head> <body> <div class="scene"> <div class="candle-wrapper"> <div class="flame-wrapper"> <div class="flame-glow"></div> <div class="flame"></div> <div class="flame-core"></div> <div class="inner-glow"></div> </div>
  <div class="candle-body">
    <div class="light-on-candle"></div>
    <div class="drip d1"></div>
    <div class="drip d2"></div>
    <div class="drip d3"></div>
    <div class="wick"></div>
  </div>

  <div class="sparks">
    <div class="spark s1"></div>
    <div class="spark s2"></div>
    <div class="spark s3"></div>
    <div class="spark s4"></div>
    <div class="spark s5"></div>
    <div class="spark s6"></div>
    <div class="spark s7"></div>
    <div class="spark s8"></div>
  </div>
</div>
</div> </body> </html>*
Updated files
v1