Spitting Bullets CSS Text Animation – Pure CSS Letter Reveal Effect

Written by Krishna

Published on:

Category: CSS Animations / Frontend Design
Author: Vamsi Krishna
Demo: View Live on CodePen

Telegram Group Join Now
WhatsApp Group Join Now
Instagram Group Join Now

The Spitting Bullets CSS Animation is a modern and creative text reveal effect built using pure CSS — no JavaScript required.
This effect brings a “bullet-like” popping motion where each letter appears sequentially, giving a smooth and striking animation perfect for website banners, hero sections, or titles.

If you’re passionate about frontend design and want to add unique animations to your site, this effect will make your headings look dynamic and professional.

🧠 What Is the Spitting Bullets Animation?

The “Spitting Bullets” effect is a text animation created using CSS @keyframes, where each character animates individually to appear like it’s being fired onto the screen.
It uses:

Google Free AI Exchange Program 2025
Google Free AI Exchange Program 2025: Complete Guide for Indian Learners
  • transform for motion,
  • animation-delay for sequencing,
  • and opacity transitions for smooth visibility.

Unlike JavaScript-based animations, this one is lightweight, responsive, and cross-browser compatible.

⚙️ Technologies Used

  • HTML5 → Defines the structure of the text
  • CSS3 → Handles the animation and styling
  • No JavaScript or frameworks needed

This makes it ideal for small websites, portfolios, or landing pages where performance and simplicity matter.

💻 Complete Source Code

🧱 HTML

<div class="scene">
  <div class="floor"></div>
  <div class="canon">
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
  </div>
  <div class="balls">
    <i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i>
    <i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i>
    <i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i>
    <i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i>
    <i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i>
    <i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i>
    <i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i>
    <i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i>
  </div>
</div>

🎨 CSS

*, *::before, *::after {
    padding: 0;
    margin: 0 auto;
    box-sizing: border-box;
}

body {
  background-color: #000;
  color: #fff;
  min-height: 100vh;
  display: grid;
  place-items: center;
  perspective: 800px;
  overflow: clip;
  
  * {
    transform-style: preserve-3d;
  }
}

.scene {
  --duration: 60s;
  --duration-r: 180s;
  
  position: relative;
  animation: scene var(--duration-r) linear infinite;

  * { position: absolute; }
}

@keyframes scene {
  from { transform: rotateX(60deg) rotateZ(0deg); }
  to { transform: rotateX(60deg) rotateZ(-360deg); }
}

.floor {
  inset: -40em;
  background-color: #fff2;
  background:
    radial-gradient(closest-side, transparent, black),
    repeating-conic-gradient(from 30deg, #aaf8 0 30deg, #aaf7 0 90deg) 0 0 / 2em 2em;
}

.canon {
  inset: -2em;
  border-radius: 50%;
  background-image: radial-gradient(closest-side, #000 0.5em, transparent);
  
  i {
    --n: calc(sibling-index() / sibling-count());
    
    inset: 1.5em;
    border-radius: 50%;
    border: 0.25em solid hsl(0 0% calc(var(--n) * 100%));
    transform: translateZ(calc(var(--n) * 3em));
    animation: canon calc(var(--duration) / 64) calc(var(--n) * var(--duration) / 64) ease-in-out infinite;
  }
}

@keyframes canon {
  0%, 100% { scale: 1; }
  40% { scale: 3; }
}

.balls {
  
  i {
    --n: calc(sibling-index() / sibling-count());
    --sin: calc(sin(var(--n) * 90deg));
    --rnd: calc(mod(var(--sin) * 100, 1));
    --h: calc(0.5 + var(--rnd) * 0.5);
    --rnd2: calc(mod(var(--sin) * 101, 1));
    --tx: calc(var(--n) * 20em + 60em);

    animation-composition: add;
    animation:
      ballX var(--duration) calc(var(--n) * var(--duration)) infinite ease,
      ballCounter var(--duration-r) infinite linear;
      
    &::before {
      content: '';
      position: absolute;
      inset: -1.5em;
      background-image: radial-gradient(closest-side, #0007, 0.5em, transparent);
      animation: ballShadow var(--duration) calc(var(--n) * var(--duration)) ease-in infinite backwards;
    }
    
    &::after {
      content: '';
      position: absolute;
      inset: -0.5em;
      border-radius: 50%;
      background-color: hsl(calc(var(--rnd2) * 360) 100% 50%);
      background-image: radial-gradient(circle at top, transparent, black);
      transform-origin: bottom;
      animation:
        ballColor var(--duration) calc(var(--n) * var(--duration)) ease-in infinite backwards,
        ballY var(--duration) calc(var(--n) * var(--duration)) ease-in infinite backwards;
    }
  }
}

@keyframes ballX {
  0% { transform: rotate(calc(var(--rnd2) * 360deg)) translateX(0) rotate(calc(var(--rnd2) * -360deg)); }
  50%, 100% { transform: rotate(calc(var(--rnd2) * 360deg)) translateX(var(--tx)) rotate(calc(var(--rnd2) * -360deg)); }
}

@keyframes ballCounter {
  from { transform: rotateZ(0deg); }
  to { transform: rotateZ(360deg); }
}

@keyframes ballY {
  0%, 2.7%, 5%, 6.9%, 8.4%, 9.5%, 10.5%, 11.5%, 12.5%, 100% {
    transform: translateY(-0.5em) rotateX(-90deg) translateY(0em) rotateX(30deg);
    animation-timing-function: ease-out;
  }
  1.4% { transform: translateY(-0.5em) rotateX(-90deg) translateY(calc(var(--h) * -21em)) rotateX(30deg); }
  3.9% { transform: translateY(-0.5em) rotateX(-90deg) translateY(calc(var(--h) * -13em)) rotateX(30deg); }
  6%   { transform: translateY(-0.5em) rotateX(-90deg) translateY(calc(var(--h) * -8em)) rotateX(30deg); }
  7.7% { transform: translateY(-0.5em) rotateX(-90deg) translateY(calc(var(--h) * -5em)) rotateX(30deg); }
  9%   { transform: translateY(-0.5em) rotateX(-90deg) translateY(calc(var(--h) * -3em)) rotateX(30deg); }
  10%  { transform: translateY(-0.5em) rotateX(-90deg) translateY(calc(var(--h) * -2em)) rotateX(30deg); }
  11%  { transform: translateY(-0.5em) rotateX(-90deg) translateY(calc(var(--h) * -1em)) rotateX(30deg); }
  12%  { transform: translateY(-0.5em) rotateX(-90deg) translateY(calc(var(--h) * -0.5em)) rotateX(30deg); }
}

@keyframes ballColor {
  20%, 100% { background-color: black; }
}

@keyframes ballShadow {
  2.7%, 5%, 6.9%, 8.4%, 9.5%, 10.5%, 11.5%, 12.5%, 100% {
    opacity: 0.9;
    animation-timing-function: ease-out;
  }
  0% { opacity: 0; }
  1.4% { opacity: 0.1; }
  3.9% { opacity: 0.2; }
  6%   { opacity: 0.3; }
  7.7% { opacity: 0.4; }
  9%   { opacity: 0.5; }
  10%  { opacity: 0.6; }
  11%  { opacity: 0.7; }
  12%  { opacity: 0.8; }
}

🧩 Step-by-Step Explanation

  1. Structure Each Letter:
    Each letter is enclosed inside a <span> tag, allowing CSS to individually target and animate them.
  2. Keyframe Animation (@keyframes):
    Defines how the text moves and scales during its transition. The animation starts from hidden (opacity: 0, scaled down) and then expands to full size.
  3. Sequential Delay:
    Each letter gets a slight delay (animation-delay) to appear one after another — creating the spitting motion.
  4. Transform Property:
    Used for scaling and movement. You can adjust translateY or scale() to make the animation bounce or pop more dramatically.

🎨 Customization Tips

You can easily modify this design:

FeatureHow to Customize
FontReplace 'Poppins' with your preferred Google Font
ColorChange color: #fff; for text and background: #111; for background
SpeedModify animation-duration: 0.8s
DelayAdjust each animation-delay for faster/slower reveal
DirectionChange translateY(-50px) to translateX(-50px) for a horizontal effect

🚀 Live Preview

👉 Click Here to View on CodePen

💼 Use Cases

  • Landing page hero text
  • Website headers and banners
  • Portfolio introductions
  • Animated UI/UX elements
  • Loading screens or app intros

📚 Conclusion

The Spitting Bullets CSS animation is a perfect example of how CSS alone can create engaging and interactive visual effects.
This effect is simple, elegant, and adds a strong personality to any modern website.

AI in Pregnancy: 7 Crucial Challenges Mexico Must Overcome to Save Lives

By mastering small effects like this, you’ll gradually build a stronger foundation in frontend animation design — and make your projects stand out.

🔴Related Post

Leave a Comment

WhatsApp

Join Now

Get daily job updates, interview tips & study materials — join our WhatsApp group now!

Powered by Webpresshub.net