UI Components Easy
Line Shadow Text
Large heading with an animated shadow made of repeated lines offset below. Multiple text-shadows create a striking striped shadow effect with a smooth animated offset.
Open in Lab
MCP
css javascript svelte vue
Targets: TS JS HTML React Svelte Vue
Code
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: system-ui, -apple-system, sans-serif;
background: #0a0a0a;
color: #f1f5f9;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
}
.line-shadow-text {
--shadow-color: 167, 139, 250;
font-size: clamp(3rem, 10vw, 8rem);
font-weight: 900;
letter-spacing: -0.03em;
color: #f1f5f9;
position: relative;
cursor: default;
animation: line-shadow-drift 4s ease-in-out infinite alternate;
}
/*
Build a striped shadow by stacking many text-shadow layers.
Every other line uses lower opacity to create the "lined" look.
*/
@keyframes line-shadow-drift {
0% {
text-shadow:
1px 1px 0 rgba(var(--shadow-color), 0.25),
2px 2px 0 rgba(var(--shadow-color), 0.0),
3px 3px 0 rgba(var(--shadow-color), 0.22),
4px 4px 0 rgba(var(--shadow-color), 0.0),
5px 5px 0 rgba(var(--shadow-color), 0.19),
6px 6px 0 rgba(var(--shadow-color), 0.0),
7px 7px 0 rgba(var(--shadow-color), 0.16),
8px 8px 0 rgba(var(--shadow-color), 0.0),
9px 9px 0 rgba(var(--shadow-color), 0.13),
10px 10px 0 rgba(var(--shadow-color), 0.0),
11px 11px 0 rgba(var(--shadow-color), 0.1),
12px 12px 0 rgba(var(--shadow-color), 0.0),
13px 13px 0 rgba(var(--shadow-color), 0.07),
14px 14px 0 rgba(var(--shadow-color), 0.0),
15px 15px 0 rgba(var(--shadow-color), 0.04);
}
100% {
text-shadow:
2px 4px 0 rgba(var(--shadow-color), 0.25),
4px 6px 0 rgba(var(--shadow-color), 0.0),
6px 8px 0 rgba(var(--shadow-color), 0.22),
8px 10px 0 rgba(var(--shadow-color), 0.0),
10px 12px 0 rgba(var(--shadow-color), 0.19),
12px 14px 0 rgba(var(--shadow-color), 0.0),
14px 16px 0 rgba(var(--shadow-color), 0.16),
16px 18px 0 rgba(var(--shadow-color), 0.0),
18px 20px 0 rgba(var(--shadow-color), 0.13),
20px 22px 0 rgba(var(--shadow-color), 0.0),
22px 24px 0 rgba(var(--shadow-color), 0.1),
24px 26px 0 rgba(var(--shadow-color), 0.0),
26px 28px 0 rgba(var(--shadow-color), 0.07),
28px 30px 0 rgba(var(--shadow-color), 0.0),
30px 32px 0 rgba(var(--shadow-color), 0.04);
}
}
@media (prefers-reduced-motion: reduce) {
.line-shadow-text {
animation: none;
}
}
/* Subtle label underneath */
.line-shadow-label {
text-align: center;
margin-top: 2rem;
font-size: 0.8rem;
color: #444;
letter-spacing: 0.15em;
text-transform: uppercase;
}/**
* Line Shadow Text
* Minimal JS -- the effect is CSS-driven.
* This script lets you dynamically set the shadow color via data attributes.
*/
(function () {
const el = document.querySelector(".line-shadow-text");
if (!el) return;
// Allow data-shadow-color override (R, G, B)
const color = el.dataset.shadowColor;
if (color) {
el.style.setProperty("--shadow-color", color);
}
})();<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Line Shadow Text</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div style="text-align: center;">
<h1 class="line-shadow-text">Shadow</h1>
<p class="line-shadow-label">Striped shadow effect</p>
</div>
<script src="script.js"></script>
</body>
</html>import { type ReactNode } from "react";
interface LineShadowTextProps {
children: ReactNode;
shadowColor?: string;
}
export default function LineShadowText({
children = "Shadow",
shadowColor = "167, 139, 250",
}: LineShadowTextProps) {
return (
<div
style={{
minHeight: "100vh",
background: "#0a0a0a",
display: "flex",
alignItems: "center",
justifyContent: "center",
flexDirection: "column",
}}
>
<h1
className="line-shadow-text"
style={
{
"--shadow-color": shadowColor,
fontSize: "clamp(3rem, 10vw, 8rem)",
fontWeight: 900,
letterSpacing: "-0.03em",
color: "#f1f5f9",
cursor: "default",
animation: "lineShadowDrift 4s ease-in-out infinite alternate",
} as React.CSSProperties
}
>
{children}
</h1>
<p
style={{
marginTop: "2rem",
fontSize: "0.8rem",
color: "#444",
letterSpacing: "0.15em",
textTransform: "uppercase",
}}
>
Striped shadow effect
</p>
<style>{`
@keyframes lineShadowDrift {
0% {
text-shadow:
1px 1px 0 rgba(var(--shadow-color), 0.25),
2px 2px 0 rgba(var(--shadow-color), 0.00),
3px 3px 0 rgba(var(--shadow-color), 0.22),
4px 4px 0 rgba(var(--shadow-color), 0.00),
5px 5px 0 rgba(var(--shadow-color), 0.19),
6px 6px 0 rgba(var(--shadow-color), 0.00),
7px 7px 0 rgba(var(--shadow-color), 0.16),
8px 8px 0 rgba(var(--shadow-color), 0.00),
9px 9px 0 rgba(var(--shadow-color), 0.13),
10px 10px 0 rgba(var(--shadow-color), 0.00),
11px 11px 0 rgba(var(--shadow-color), 0.10),
12px 12px 0 rgba(var(--shadow-color), 0.00),
13px 13px 0 rgba(var(--shadow-color), 0.07),
14px 14px 0 rgba(var(--shadow-color), 0.00),
15px 15px 0 rgba(var(--shadow-color), 0.04);
}
100% {
text-shadow:
2px 4px 0 rgba(var(--shadow-color), 0.25),
4px 6px 0 rgba(var(--shadow-color), 0.00),
6px 8px 0 rgba(var(--shadow-color), 0.22),
8px 10px 0 rgba(var(--shadow-color), 0.00),
10px 12px 0 rgba(var(--shadow-color), 0.19),
12px 14px 0 rgba(var(--shadow-color), 0.00),
14px 16px 0 rgba(var(--shadow-color), 0.16),
16px 18px 0 rgba(var(--shadow-color), 0.00),
18px 20px 0 rgba(var(--shadow-color), 0.13),
20px 22px 0 rgba(var(--shadow-color), 0.00),
22px 24px 0 rgba(var(--shadow-color), 0.10),
24px 26px 0 rgba(var(--shadow-color), 0.00),
26px 28px 0 rgba(var(--shadow-color), 0.07),
28px 30px 0 rgba(var(--shadow-color), 0.00),
30px 32px 0 rgba(var(--shadow-color), 0.04);
}
}
`}</style>
</div>
);
}<script>
export let shadowColor = "167, 139, 250";
export let text = "Stealthis";
</script>
<div class="wrapper">
<h1
class="line-shadow-text"
style="--shadow-color: {shadowColor};"
>
<slot>{text}</slot>
</h1>
<p class="line-shadow-label">Striped shadow effect</p>
</div>
<style>
.wrapper {
min-height: 100vh;
background: #0a0a0a;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
font-family: system-ui, -apple-system, sans-serif;
overflow: hidden;
}
.line-shadow-text {
--shadow-color: 167, 139, 250;
font-size: clamp(3rem, 10vw, 8rem);
font-weight: 900;
letter-spacing: -0.03em;
color: #f1f5f9;
position: relative;
cursor: default;
animation: lineShadowDrift 4s ease-in-out infinite alternate;
}
@keyframes lineShadowDrift {
0% {
text-shadow:
1px 1px 0 rgba(var(--shadow-color), 0.25),
2px 2px 0 rgba(var(--shadow-color), 0.00),
3px 3px 0 rgba(var(--shadow-color), 0.22),
4px 4px 0 rgba(var(--shadow-color), 0.00),
5px 5px 0 rgba(var(--shadow-color), 0.19),
6px 6px 0 rgba(var(--shadow-color), 0.00),
7px 7px 0 rgba(var(--shadow-color), 0.16),
8px 8px 0 rgba(var(--shadow-color), 0.00),
9px 9px 0 rgba(var(--shadow-color), 0.13),
10px 10px 0 rgba(var(--shadow-color), 0.00),
11px 11px 0 rgba(var(--shadow-color), 0.10),
12px 12px 0 rgba(var(--shadow-color), 0.00),
13px 13px 0 rgba(var(--shadow-color), 0.07),
14px 14px 0 rgba(var(--shadow-color), 0.00),
15px 15px 0 rgba(var(--shadow-color), 0.04);
}
100% {
text-shadow:
2px 4px 0 rgba(var(--shadow-color), 0.25),
4px 6px 0 rgba(var(--shadow-color), 0.00),
6px 8px 0 rgba(var(--shadow-color), 0.22),
8px 10px 0 rgba(var(--shadow-color), 0.00),
10px 12px 0 rgba(var(--shadow-color), 0.19),
12px 14px 0 rgba(var(--shadow-color), 0.00),
14px 16px 0 rgba(var(--shadow-color), 0.16),
16px 18px 0 rgba(var(--shadow-color), 0.00),
18px 20px 0 rgba(var(--shadow-color), 0.13),
20px 22px 0 rgba(var(--shadow-color), 0.00),
22px 24px 0 rgba(var(--shadow-color), 0.10),
24px 26px 0 rgba(var(--shadow-color), 0.00),
26px 28px 0 rgba(var(--shadow-color), 0.07),
28px 30px 0 rgba(var(--shadow-color), 0.00),
30px 32px 0 rgba(var(--shadow-color), 0.04);
}
}
@media (prefers-reduced-motion: reduce) {
.line-shadow-text {
animation: none;
}
}
.line-shadow-label {
margin-top: 2rem;
font-size: 0.8rem;
color: #444;
letter-spacing: 0.15em;
text-transform: uppercase;
}
</style><script setup>
const props = defineProps({
shadowColor: { type: String, default: "167, 139, 250" },
});
</script>
<template>
<div class="wrapper">
<h1
class="line-shadow-text"
:style="{ '--shadow-color': props.shadowColor }"
>
<slot>Stealthis</slot>
</h1>
<p class="subtitle">Striped shadow effect</p>
</div>
</template>
<style>
.wrapper {
min-height: 100vh;
background: #0a0a0a;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
font-family: system-ui, -apple-system, sans-serif;
overflow: hidden;
}
.line-shadow-text {
--shadow-color: 167, 139, 250;
font-size: clamp(3rem, 10vw, 8rem);
font-weight: 900;
letter-spacing: -0.03em;
color: #f1f5f9;
cursor: default;
animation: lineShadowDrift 4s ease-in-out infinite alternate;
}
.subtitle {
margin-top: 2rem;
font-size: 0.8rem;
color: #444;
letter-spacing: 0.15em;
text-transform: uppercase;
}
@keyframes lineShadowDrift {
0% {
text-shadow:
1px 1px 0 rgba(var(--shadow-color), 0.25),
2px 2px 0 rgba(var(--shadow-color), 0.00),
3px 3px 0 rgba(var(--shadow-color), 0.22),
4px 4px 0 rgba(var(--shadow-color), 0.00),
5px 5px 0 rgba(var(--shadow-color), 0.19),
6px 6px 0 rgba(var(--shadow-color), 0.00),
7px 7px 0 rgba(var(--shadow-color), 0.16),
8px 8px 0 rgba(var(--shadow-color), 0.00),
9px 9px 0 rgba(var(--shadow-color), 0.13),
10px 10px 0 rgba(var(--shadow-color), 0.00),
11px 11px 0 rgba(var(--shadow-color), 0.10),
12px 12px 0 rgba(var(--shadow-color), 0.00),
13px 13px 0 rgba(var(--shadow-color), 0.07),
14px 14px 0 rgba(var(--shadow-color), 0.00),
15px 15px 0 rgba(var(--shadow-color), 0.04);
}
100% {
text-shadow:
2px 4px 0 rgba(var(--shadow-color), 0.25),
4px 6px 0 rgba(var(--shadow-color), 0.00),
6px 8px 0 rgba(var(--shadow-color), 0.22),
8px 10px 0 rgba(var(--shadow-color), 0.00),
10px 12px 0 rgba(var(--shadow-color), 0.19),
12px 14px 0 rgba(var(--shadow-color), 0.00),
14px 16px 0 rgba(var(--shadow-color), 0.16),
16px 18px 0 rgba(var(--shadow-color), 0.00),
18px 20px 0 rgba(var(--shadow-color), 0.13),
20px 22px 0 rgba(var(--shadow-color), 0.00),
22px 24px 0 rgba(var(--shadow-color), 0.10),
24px 26px 0 rgba(var(--shadow-color), 0.00),
26px 28px 0 rgba(var(--shadow-color), 0.07),
28px 30px 0 rgba(var(--shadow-color), 0.00),
30px 32px 0 rgba(var(--shadow-color), 0.04);
}
}
@media (prefers-reduced-motion: reduce) {
.line-shadow-text {
animation: none;
}
}
</style>Line Shadow Text
A bold heading with an eye-catching shadow made of repeated, evenly-spaced line shadows that animate their offset to create a dynamic depth effect.
How it works
Multiple text-shadow layers are stacked, each offset slightly further than the last, with alternating opacity to create a lined/striped look. A CSS animation shifts the shadow offset over time.
Features
- Striped shadow effect — multiple layered text-shadows
- Animated offset — shadow drifts smoothly via keyframes
- Customizable — shadow color, line count, and animation speed
- Lightweight — pure CSS effect with minimal JS