Typography typographycurvedpathsvgheading

Curved Path Heading

SVG textOnPath arc headline for playful badges, stamp seals, and creative hero section headers.

Preview

ASTRO COMPONENTS KIT • ZERO RUNTIME • PURE CSS •
✦

Usage

Copy the full block below to use this component with its imports.

astro
---
import { CurvedPathHeading } from 'astro-component-kit';
---

<CurvedPathHeading text="PREMIUM ASTRO UI LIBRARY • " radius={120} />
--- import { CurvedPathHeading } from 'astro-component-kit'; --- <CurvedPathHeading text="PREMIUM ASTRO UI LIBRARY • " radius={120} />

Manual Installation

If you are not using the npm package, create a new file src/components/lib/CurvedPathHeading.astro and paste the following code:

astro
---
/**
 * CurvedPathHeading — Typographic heading flowing along an SVG circular or arched trajectory.
 * 
 * @param {string} text - Headline text content. Default is 'ASTRO COMPONENTS KIT • ZERO RUNTIME DEPENDENCIES •'.
 * @param {number} size - Pixel container diameter. Default is 260.
 * @param {boolean} animate - Whether the badge rotates continuously. Default is true.
 */
interface Props {
  text?: string;
  size?: number;
  animate?: boolean;
}

const {
  text = 'ASTRO COMPONENTS KIT • ZERO RUNTIME • PURE CSS •',
  size = 260,
  animate = true,
} = Astro.props;

const pathId = `curve-path-${Math.random().toString(36).substring(2, 8)}`;
---

<div class:list={['curved-heading', { 'is-animated': animate }]} style={`--curved-size: ${size}px;`}>
  <svg viewBox="0 0 300 300" width={size} height={size}>
    <defs>
      <path
        id={pathId}
        d="M 150, 150 m -110, 0 a 110,110 0 1,1 220,0 a 110,110 0 1,1 -220,0"
      />
    </defs>
    <text class="curved-heading__text">
      <textPath href={`#${pathId}`} startOffset="0%">
        {text}
      </textPath>
    </text>
  </svg>
  <div class="curved-heading__core">✦</div>
</div>

<style>
  .curved-heading {
    position: relative;
    width: var(--curved-size);
    height: var(--curved-size);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-family: var(--font-sans, system-ui, sans-serif);
    user-select: none;
  }

  .curved-heading.is-animated svg {
    animation: curved-spin 20s linear infinite;
  }

  .curved-heading__text {
    font-size: 13.5px;
    font-weight: 800;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    fill: var(--c-primary-light, #d4a017);
  }

  .curved-heading__core {
    position: absolute;
    width: 48px;
    height: 48px;
    border-radius: 50%;
    background: rgba(184, 134, 11, 0.12);
    border: 1px solid rgba(184, 134, 11, 0.3);
    color: var(--c-accent, #fef3c7);
    display: grid;
    place-items: center;
    font-size: 1.2rem;
  }

  @keyframes curved-spin {
    from { transform: rotate(0deg); }
    to { transform: rotate(360deg); }
  }

  @media (prefers-reduced-motion: reduce) {
    .curved-heading.is-animated svg { animation: none; }
  }
</style>
--- /** * CurvedPathHeading — Typographic heading flowing along an SVG circular or arched trajectory. * * @param {string} text - Headline text content. Default is 'ASTRO COMPONENTS KIT • ZERO RUNTIME DEPENDENCIES •'. * @param {number} size - Pixel container diameter. Default is 260. * @param {boolean} animate - Whether the badge rotates continuously. Default is true. */ interface Props { text?: string; size?: number; animate?: boolean; } const { text = 'ASTRO COMPONENTS KIT • ZERO RUNTIME • PURE CSS •', size = 260, animate = true, } = Astro.props; const pathId = `curve-path-${Math.random().toString(36).substring(2, 8)}`; --- <div class:list={['curved-heading', { 'is-animated': animate }]} style={`--curved-size: ${size}px;`}> <svg viewBox="0 0 300 300" width={size} height={size}> <defs> <path id={pathId} d="M 150, 150 m -110, 0 a 110,110 0 1,1 220,0 a 110,110 0 1,1 -220,0" /> </defs> <text class="curved-heading__text"> <textPath href={`#${pathId}`} startOffset="0%"> {text} </textPath> </text> </svg> <div class="curved-heading__core">✦</div> </div> <style> .curved-heading { position: relative; width: var(--curved-size); height: var(--curved-size); display: inline-flex; align-items: center; justify-content: center; font-family: var(--font-sans, system-ui, sans-serif); user-select: none; } .curved-heading.is-animated svg { animation: curved-spin 20s linear infinite; } .curved-heading__text { font-size: 13.5px; font-weight: 800; letter-spacing: 0.18em; text-transform: uppercase; fill: var(--c-primary-light, #d4a017); } .curved-heading__core { position: absolute; width: 48px; height: 48px; border-radius: 50%; background: rgba(184, 134, 11, 0.12); border: 1px solid rgba(184, 134, 11, 0.3); color: var(--c-accent, #fef3c7); display: grid; place-items: center; font-size: 1.2rem; } @keyframes curved-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } @media (prefers-reduced-motion: reduce) { .curved-heading.is-animated svg { animation: none; } } </style>

Quick Info

Category
Typography
Filename
CurvedPathHeading.astro
Dependencies
None — pure Astro + CSS
Tags
typographycurvedpathsvgheading