How to Add a Looping Typewriter Subtitle to Your Astro Banner

This guide walks through implementing a typewriter effect for a banner subtitle in an Astro + Yukina setup. The effect progressively reveals the subtitle, holds the fully typed text for three seconds, then restarts in a smooth loop. The subtitle remains horizontally centered beneath the main title.

Prerequisites

  • Astro project using the shared banner component pattern (src/components/Banner.astro)
  • Tailwind utilities available (the snippets rely on Tailwind classes)
  • Access to your layout that renders the banner (src/layouts/MainLayout.astro) and the routed page that should enable the effect (e.g., src/pages/[...page].astro)

Step 1: Add a toggle prop to the Banner component

Introduce a typewriterSubtitle?: boolean prop so the effect can be switched on where needed.

// src/components/Banner.astro
export interface Props {
  title?: string;
  subTitle?: string;
  bannerImage?: string;
  slug?: string;
  typewriterSubtitle?: boolean;
}

const { title, subTitle, bannerImage, slug, typewriterSubtitle } = Astro.props;
const subtitleText = subTitle ?? YukinaConfig.subTitle;

Use the prop to conditionally apply a typewriter class and set CSS variables for the character count:

<h2
  class:list={["subtitle", typewriterSubtitle && "subtitle-typewriter"]}
  style={
    typewriterSubtitle
      ? `--typewriter-steps: ${subtitleText.length}; --typewriter-width: ${subtitleText.length}ch;`
      : undefined
  }
>
  {subtitleText}
</h2>

Step 2: Add the typewriter styles and timing

Append the animation styles to the banner stylesheet. The 7-second loop types for roughly 4 seconds and holds the completed text for about 3 seconds before restarting. The subtitle is centered with a slight margin from the title.

/* src/components/Banner.astro */
.subtitle {
  @apply mt-3 text-center text-xl text-[var(--subtitle-color)] drop-shadow-md lg:mt-4 lg:text-3xl;
  font-family: var(--subtitle-font);
}

.subtitle-typewriter {
  @apply mx-auto inline-block overflow-hidden whitespace-nowrap;
  border-right: 2px solid var(--subtitle-color);
  width: 0;
  animation:
    typing 7s steps(var(--typewriter-steps), end) infinite,
    blink-caret 0.75s step-end infinite;
}

@keyframes typing {
  0% {
    width: 0;
  }
  58% {
    width: var(--typewriter-width, 100%);
  }
  100% {
    width: var(--typewriter-width, 100%);
  }
}

@keyframes blink-caret {
  from,
  to {
    border-color: transparent;
  }
  50% {
    border-color: var(--subtitle-color);
  }
}

Step 3: Plumb the prop through the main layout

Expose the toggle on your layout so any page can enable the effect when rendering the banner.

// src/layouts/MainLayout.astro
export interface Props {
  title?: string;
  subTitle?: string;
  bannerImage?: string;
  slug?: string;
  typewriterSubtitle?: boolean;
}

<Banner
  title={props.title}
  subTitle={props.subTitle}
  bannerImage={props.bannerImage}
  slug={props.slug}
  typewriterSubtitle={props.typewriterSubtitle}
/>;

Step 4: Turn it on for the desired route (example: homepage)

If your homepage is the first page of a paginated list, you can enable the typewriter only there by passing the prop when currentPage === 1.

// src/pages/[...page].astro
<Main typewriterSubtitle={page.currentPage === 1}>
  <!-- page content -->
</Main>

You can also hardcode typewriterSubtitle={true} on any specific page or layout slot where the effect is desired.

Step 5: Verify the behavior

  1. Run pnpm dev and open the homepage.
  2. Confirm the subtitle types from left to right, pauses for roughly three seconds after completion, then restarts.
  3. Check that the subtitle is horizontally centered and sits slightly below the main title.

Optional adjustments

  • Typing pace and pause: Change typing 7s ... to alter the full cycle duration; adjust the 58% keyframe to control how quickly the text finishes before the pause.
  • Caret styling: Modify border-right or the blink-caret keyframe for color and blink speed.
  • Scope: Pass typewriterSubtitle only on routes where the effect fits the page tone.

Add a Typewriter Subtitle

Author

Shayne Wong

Publish Date

11 - 26 - 2025

License

Shayne Wong

Avatar
Shayne Wong

All time is no time when it is past.