Skip to content

Shimmer Text

Text with a band of light that sweeps across its letters through a mask.

Shimmer Text, playing
  • Text
  • iOS 18.0+
  • beginner
Download .swift
Origin
Original work
Found by
shimmer · shine · highlight · loading · mask · text animation · slide to unlock · brillo · destello · reflejo · cargando · máscara · animación de texto

A band of light that sweeps across the letters, masked by the text itself.

With Reduce Motion on, the text is drawn plainly in the highlight color.

struct ShimmerTextDemo: View {
private let dimmed = Color.white.opacity(0.35)
var body: some View {
ZStack {
LinearGradient(colors: [Color(white: 0.16), .black], startPoint: .top, endPoint: .bottom)
.ignoresSafeArea()
VStack(spacing: 28) {
ShimmerText(text: "Shimmer", baseColor: dimmed, highlightColor: .white)
.font(.system(.largeTitle, design: .rounded, weight: .black))
.scaleEffect(1.5)
ShimmerText(text: "slide to unlock", baseColor: dimmed, highlightColor: .white, duration: 1.8)
.font(.title3.weight(.medium))
Label {
ShimmerText(text: "Writing your summary...", baseColor: .purple.opacity(0.5), highlightColor: .white)
} icon: {
Image(systemName: "sparkles")
.foregroundStyle(.purple)
.accessibilityHidden(true)
}
.font(.headline)
.padding(.horizontal, 20)
.padding(.vertical, 14)
.background(.white.opacity(0.08), in: .capsule)
}
.padding(24)
}
}
}
ParameterTypeDefaultDescription
textStringRequired
baseColorColor.secondary
highlightColorColor.primary
durationDouble2.2Seconds for one sweep.

Copy this code into your project, or download the file.

ShimmerText.swift
// SPDX-License-Identifier: MIT
// Copyright (c) 2026 Oscar Canton and SwiftUI Blocks contributors
import SwiftUI
/// A band of light that sweeps across the letters, masked by the text itself.
///
/// With Reduce Motion on, the text is drawn plainly in the highlight color.
struct ShimmerText: View {
let text: String
var baseColor: Color = .secondary
var highlightColor: Color = .primary
/// Seconds for one sweep.
var duration: Double = 2.2
/// Half the width of the band of light, as a fraction of the text's width.
private let bandWidth = 0.3
@Environment(\.accessibilityReduceMotion) private var reduceMotion
var body: some View {
Text(text)
.foregroundStyle(reduceMotion ? highlightColor : baseColor)
.overlay {
if !reduceMotion {
TimelineView(.animation(minimumInterval: 1.0 / 60.0)) { context in
band(at: context.date)
}
.mask { Text(text).foregroundStyle(.black) }
.accessibilityHidden(true)
}
}
}
/// Start and end points beyond 0...1 place the band off to the side, between sweeps.
private func band(at date: Date) -> LinearGradient {
let cycle = date.timeIntervalSinceReferenceDate.truncatingRemainder(dividingBy: duration) / duration
let center = -bandWidth + (1 + 2 * bandWidth) * cycle
return LinearGradient(
colors: [.clear, highlightColor, .clear],
startPoint: UnitPoint(x: center - bandWidth, y: 0.5),
endPoint: UnitPoint(x: center + bandWidth, y: 0.5)
)
}
}
// MARK: - Demo
struct ShimmerTextDemo: View {
private let dimmed = Color.white.opacity(0.35)
var body: some View {
ZStack {
LinearGradient(colors: [Color(white: 0.16), .black], startPoint: .top, endPoint: .bottom)
.ignoresSafeArea()
VStack(spacing: 28) {
ShimmerText(text: "Shimmer", baseColor: dimmed, highlightColor: .white)
.font(.system(.largeTitle, design: .rounded, weight: .black))
.scaleEffect(1.5)
ShimmerText(text: "slide to unlock", baseColor: dimmed, highlightColor: .white, duration: 1.8)
.font(.title3.weight(.medium))
Label {
ShimmerText(text: "Writing your summary...", baseColor: .purple.opacity(0.5), highlightColor: .white)
} icon: {
Image(systemName: "sparkles")
.foregroundStyle(.purple)
.accessibilityHidden(true)
}
.font(.headline)
.padding(.horizontal, 20)
.padding(.vertical, 14)
.background(.white.opacity(0.08), in: .capsule)
}
.padding(24)
}
}
}
#Preview {
ShimmerTextDemo()
}