Close Menu
    DevStackTipsDevStackTips
    • Home
    • News & Updates
      1. Tech & Work
      2. View All

      The Double-Edged Sustainability Sword Of AI In Web Design

      August 20, 2025

      Top 12 Reasons Enterprises Choose Node.js Development Services for Scalable Growth

      August 20, 2025

      GitHub’s coding agent can now be launched from anywhere on platform using new Agents panel

      August 20, 2025

      Stop writing tests: Automate fully with Generative AI

      August 19, 2025

      I’m a diehard Pixel fan, but I’m not upgrading to the Pixel 10. Here’s why

      August 21, 2025

      Google Pixel Watch 4 vs. Samsung Galaxy Watch 8: I compared the two best Androids, and here’s the winner

      August 21, 2025

      Get a free Amazon gift card up to $300 when you preorder a new Google Pixel 10 phone – here’s how

      August 21, 2025

      Everything announced at Made by Google 2025: Pixel 10 Pro, Fold, Watch 4, and more

      August 21, 2025
    • Development
      1. Algorithms & Data Structures
      2. Artificial Intelligence
      3. Back-End Development
      4. Databases
      5. Front-End Development
      6. Libraries & Frameworks
      7. Machine Learning
      8. Security
      9. Software Engineering
      10. Tools & IDEs
      11. Web Design
      12. Web Development
      13. Web Security
      14. Programming Languages
        • PHP
        • JavaScript
      Featured

      Copy Errors as Markdown to Share With AI in Laravel 12.25

      August 21, 2025
      Recent

      Copy Errors as Markdown to Share With AI in Laravel 12.25

      August 21, 2025

      Deconstructing the Request Lifecycle in Sitecore Headless – Part 2: SSG and ISR Modes in Next.js

      August 20, 2025

      Susan Etlinger, AI Analyst and Industry Watcher on Building Trust

      August 20, 2025
    • Operating Systems
      1. Windows
      2. Linux
      3. macOS
      Featured

      TerraMaster D1 SSD Plus Review: Experience a Faster External SSD

      August 20, 2025
      Recent

      TerraMaster D1 SSD Plus Review: Experience a Faster External SSD

      August 20, 2025

      Microsoft is investigating Windows 11 KB5063878 SSD data corruption/failure issue

      August 20, 2025

      Microsoft Surface Won’t Turn On: 6 Tested Solutions to Fix

      August 20, 2025
    • Learning Resources
      • Books
      • Cheatsheets
      • Tutorials & Guides
    Home»News & Updates»3D Layered Text: Motion and Variations

    3D Layered Text: Motion and Variations

    August 20, 2025

    In the previous chapter, we built a basic 3D layered text effect using nothing but HTML and CSS. It looks great and has a solid visual presence, but it’s completely static. That is about to change.

    In this chapter, we will explore ways to animate the effect, add transitions, and play with different variations. We will look at how motion can enhance depth, and how subtle tweaks can create a whole new vibe.

    3D Layered Text Article Series

    1. The Basics
    2. Motion and Variations (you are here!)
    3. Interactivity and Dynamism (coming August 22)

    ⚠️ Motion Warning: This article contains multiple animated examples that may include flashing or fast moving visuals. If you are sensitive to motion, please proceed with caution.

    ‘Counter’ Animation

    Let’s start things off with a quick animation tip that pairs perfectly with layered 3D text. Sometimes, we want to rotate the element without actually changing the orientation of the text so it stays readable. The trick here is to combine multiple rotations across two axes. First, rotate the text on the z-axis. Then, add a tilt on the x-axis. Finally, rotate the text back on the z-axis.

    @keyframes wobble {
      from { transform: rotate(0deg) rotateX(20deg) rotate(360deg); }
      to { transform: rotate(360deg) rotateX(20deg) rotate(0deg); }
    }

    Since we rotate on the z-axis and then reverse that rotation, the text keeps its original orientation. But because we add a tilt on the x-axis in the middle, and the x-axis itself keeps rotating, the angle of the tilt changes as well. This creates a kind of wobble effect that shows off the text from every angle and emphasizes the sense of depth.

    CodePen Embed Fallback

    If we want to take this a few steps further, we can combine the wobble with a floating effect. We will animate the .layers slightly along the z-axis:

    .layers {
      animation: hover 2s infinite ease-in-out alternate;
    }
    
    @keyframes hover {
      from { transform: translateZ(0.3em); }
      to { transform: translateZ(0.6em); }
    }

    To really sell the effect, we will leave the original span in place — like a shadowed anchor — change its color to transparent, and animate the blur factor of its text-shadow:

    span {
      color: transparent;
      animation: shadow 2s infinite ease-in-out alternate;
    }
    
    @keyframes shadow {
      from { text-shadow: 0 0 0.1em #000; }
      to { text-shadow: 0 0 0.2em #000; }
    }

    Syncing those two animations together gives the whole thing a more realistic feel:

    CodePen Embed Fallback

    Splitting Letters

    OK, this is starting to look a lot better now that things are moving. But the whole word is still moving as one. Can we make each letter move independently? The answer, as usual, is “yes, but…”

    It is absolutely possible to split each word into a separate letters and animate them individually. But it also means a lot more elements moving on the screen, and that can lead to performance issues. If you go this route, try not to animate too many letters at once, and consider reducing the number of layers.

    In the next example, for instance, I reduced the layer count to sixteen. There are five letters, and to place them side by side, I gave the .scene a display: flex, then added a small delay to each letter using :nth-child:

    CodePen Embed Fallback

    New Angles

    Until now, we have only been moving the text along the z-axis, but we can definitely take it further. Each layer can be moved or rotated in any direction you like, and if we base those transformations on the --n variable, we can create all sorts of interesting effects. Here are a few I played with, just to give you some ideas.

    In the first one, I am animating the translateX to create a shifting effect:

    CodePen Embed Fallback

    In the others, I am adding a bit of rotation. The first one is applied to the y-axis for the sloping effect:

    CodePen Embed Fallback

    This next example applies rotation on the x-axis for the tilting:

    CodePen Embed Fallback

    And, finally, we can apply it on the z-axis for a rotating example:

    CodePen Embed Fallback

    Layer Delay

    Working with separate layers does not just let us tweak the animation for each one; it also lets us adjust the animation-delay for every layer individually, which can lead to some really interesting effects. Let us take this pulsing example:

    CodePen Embed Fallback

    Right now, the animation is applied to the .layeredText element itself, and I am simply changing its scale:

    .layeredText {
      animation: pulsing 2s infinite ease-out;
    }
    
    @keyframes pulsing {
      0%, 100% { scale: 1; }
      20% { scale: 1.2; }
    }

    But we can apply the animation to each layer separately and give each one a slight delay. Note that the span is part of the stack. It is a layer, too, and sometimes you will want to include it in the animation:

    .layer {
      --delay: calc(var(--n) * 0.3s);
    }
    
    :is(span, .layer) {
      animation: pulsing 2s var(--delay, 0s) infinite ease-out;
    }

    Here I am using the :is selector to target both the individual layers and the span itself with the same animation. The result is a much more lively and engaging effect:

    CodePen Embed Fallback

    Pseudo Decorations

    In the previous chapter, I mentioned that I usually prefer to save pseudo elements for decorative purposes. This is definitely a technique worth using. We can give each layer one or two pseudo elements, add some content, position them however we like, and the 3D effect will already be there.

    It can be anything from simple outlines to more playful shapes. Like arrows, for example:

    CodePen Embed Fallback

    Notice that I am using the :is selector to include the span here, too, but sometimes we will not want to target all the layers — only a specific portion of them. In that case, we can use :nth-child to select just part of the stack. For example, if I want to target only the bottom twelve layers (out of twenty four total), the decoration only covers half the height of the text. I can do something like :nth-child(-n + 12) , and the full selector would be:

    :is(span, .layer:nth-child(-n + 12))::before {
      /* pseudo style */
    }

    This is especially useful when the decoration overlaps with the text, and you do not want to cover it or make it hard to read.

    CodePen Embed Fallback

    Of course, you can animate these pseudo elements too. So how about a 3D “Loading” text with a built-in spinner?

    CodePen Embed Fallback

    I made a few changes to pull this off. First, I selected twelve layers from the middle of the stack using a slightly more advanced selector: .layer:nth-child(n + 6):nth-child(-n + 18). This targets the layers from number six to eighteen.

    Second, to fake the shadow, I added a blur filter to the span‘s pseudo element. This creates a nice soft effect, but it can cause performance issues in some cases, so use it with care.

    :is(span, .layer:nth-child(n + 6):nth-child(-n + 18))::before {
      /* spinner style */
    }
    
    span {
      /* span style */
    
      &::before {
        filter: blur(0.1em);
      }
    }

    Face Painting

    But you don’t have to use pseudo elements to add some visual interest. You can also style any text with a custom pattern using background-image. Just select the top layer with the :last-child selector, set its text color to transparent so the background shows through, and use background-clip: text.

    .layer {
      /* layer style */
        
      &:last-child {
        color: transparent;
        background-clip: text;
        background-image: ... /* use your imagination */
      }
    }

    Here is a small demo using striped lines with repeating-linear-gradient, and rings made with repeating-radial-gradient:

    CodePen Embed Fallback

    And, yes, you can absolutely use an image too:

    CodePen Embed Fallback

    Animating Patterns

    Let us take the previous idea a couple of steps further. Instead of applying a pattern just to the top layer, we will apply it to all the layers, creating a full 3D pattern effect. Then we will animate it.

    We’ll start with the colors. First, we give all the layers a transparent text color. The color we used before will now be stored in a custom property called --color, which we will use in just a moment.

    .layer {
      --n: calc(var(--i) / var(--layers-count));
      --color: hsl(200 30% calc(var(--n) * 100%));
    
      color: transparent;
    }

    Now let’s define the background, and we’ll say we want a moving checkerboard pattern. We can create it using repeating-conic-gradient with two colors. The first will be our --color variable, and the second could be transparent. But in this case, I think black with very low opacity works better.

    We just need to set the background-size to control the pattern scale, and of course, make sure to apply background-clip: text here too:

    .layer {
      --n: calc(var(--i) / var(--layers-count));
      --color: hsl(200 30% calc(var(--n) * 100%));
    
      color: transparent;
      background-image:
        repeating-conic-gradient(var(--color) 0 90deg, hsl(0 0% 0% / 5%) 0 180deg);
      background-size: 0.2em 0.2em;
      background-clip: text;
      transform: translateZ(calc(var(--i) * var(--layer-offset)));
      animation: checkers 24s infinite linear;
    }
    
    @keyframes checkers {
      to { background-position: 1em 0.4em; }
    }

    As you can see, I have already added the animation property. In this case, it is very simple to animate the pattern. Just slowly move the background-position, and that is it. Now we have text with a moving 3D pattern:

    CodePen Embed Fallback

    Variable Fonts

    So far, we have been using a single font, and as I mentioned earlier, font choice is mostly a matter of taste or brand guidelines. But since we are already working with layered text, we absolutely have to try it with variable fonts. The idea behind variable fonts is that each one includes axes you can manipulate to change its appearance. These can include width, weight, slant, or just about anything else.

    Here are a few examples I really like. The first one uses the Climate Crisis font, which has a YEAR axis that ranges from 1979 to 2025. With each year, the letters melt slightly and shrink a bit. It is a powerful ecological statement, and when you stack the text in layers, you can actually see the changes and get a pretty striking 3D effect:

    CodePen Embed Fallback

    Another great option is Bitcount, a variable font with a classic weight axis ranging from 100 to 900. By changing the weight based on the layer index, you get a layered effect that looks like peaks rising across the text:

    CodePen Embed Fallback

    And here is an example that might give your browser a bit of a workout. The font Kablammo includes a MORF axis, and adjusting it completely changes the shape of each letter. So, I figured it would be fun to animate that axis (yes, font-variation-settings is animatable), and add a short delay between the layers, like we saw earlier, to give the animation a more dynamic and lively feel.

    CodePen Embed Fallback

    Delayed Position

    Before we wrap up this second chapter, I want to show you one more animation. By now you have probably noticed that there is always more than one way to do things, and sometimes it is just a matter of finding the right approach. Even the positioning of the layers, which we have been handling statically with translateZ, can be done a little differently.

    If we animate the layers to move along the z-axis, from zero to the full height of the text, and add an equal delay between each one, we end up with the same visual 3D effect, only in motion.

    .layer {
      --n: calc(var(--i) / var(--layers-count));
      --delay: calc(var(--n) * -3s);
    
      animation: layer 3s var(--delay) infinite ease-in-out;
    }
    
    @keyframes layer {
      from { transform: translateZ(0); }
      to { transform: translateZ(calc(var(--layers-count) * var(--layer-offset))); }
    }

    This is a more advanced technique, suited for more complex animations. It is not something you need for every use case, but for certain effects, it can look very cool.

    CodePen Embed Fallback

    Wrapping Up

    So far, we have brought the layered text effect to life with movement, variation, and creative styling. We also saw how even small changes can have a huge visual impact when applied across layers.

    But everything we have done so far has been pre defined and self contained. In the next chapter, we are going to add a layer of interactivity. Literally. From simple :hover transitions to using JavaScript to track the mouse position, we will apply real-time transformations and build a fully responsive bulging effect.

    3D Layered Text Article Series

    1. The Basics
    2. Motion and Variations (you are here!)
    3. Interactivity and Dynamism (coming August 22)

    3D Layered Text: Motion and Variations originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

    Source: Read More 

    Facebook Twitter Reddit Email Copy Link
    Previous ArticleAiffro K100 All-SSD NAS running Linux: Introduction to the Series
    Next Article rescrobbled – music scrobbler daemon

    Related Posts

    News & Updates

    I’m a diehard Pixel fan, but I’m not upgrading to the Pixel 10. Here’s why

    August 21, 2025
    News & Updates

    Google Pixel Watch 4 vs. Samsung Galaxy Watch 8: I compared the two best Androids, and here’s the winner

    August 21, 2025
    Leave A Reply Cancel Reply

    For security, use of Google's reCAPTCHA service is required which is subject to the Google Privacy Policy and Terms of Use.

    Continue Reading

    Photobooth is photobooth software for the Raspberry Pi and PC

    Linux

    Signal-kloon TeleMessage SGNL gebruikte kwetsbare Spring Boot Actuator

    Security

    Tutorial on Seamlessly Accessing Any LinkedIn Profile with exa-mcp-server and Claude Desktop Using the Model Context Protocol MCP

    Machine Learning

    Windows 11’s Settings app is getting an AI agent that can configure options on your PC for you

    News & Updates

    Highlights

    Franse overheid beschrijft aanvallen op organisaties via Ivanti-lekken

    July 2, 2025

    Franse overheid beschrijft aanvallen op organisaties via Ivanti-lekken

    Franse organisaties, waaronder overheidsinstanties, defensiebedrijven en telecombedrijven, zijn eind vorig jaar aangevallen via kwetsbaarheden in Ivanti Cloud Service Appliance (CSA). Op het moment va …
    Read more

    Published Date:
    Jul 02, 2025 (1 hour, 30 minutes ago)

    Vulnerabilities has been mentioned in this article.

    CVE-2024-9380

    CVE-2024-8963

    CVE-2024-8190

    CVE-2025-2764 – CarlinKit CPC200-CCPA Update.cgi Cryptographic Signature Verification Bypass Code Execution Vulnerability

    April 23, 2025

    CVE-2025-50060 – Oracle BI Publisher Unauthenticated HTTP Web Server Remote Code Execution and Data Access Vulnerability

    July 16, 2025

    CVE-2024-58100 – Linux Kernel bpf Changes_pkt_data Property Vulnerability

    May 5, 2025
    © DevStackTips 2025. All rights reserved.
    • Contact
    • Privacy Policy

    Type above and press Enter to search. Press Esc to cancel.