Skip to content
Gradient Text preview
An animated render of the SwiftUI source on this page.

Gradient Text

From syxUI — written for both platforms, not translated between them.

Type filled with a gradient and an optional travelling highlight.

Text Effects · SwiftUI · Flutter · iOS 17 · Flutter 3.27

  • text
  • gradient
  • shine
  • typography
  • headline
  • colour

The actual source

GradientText.swift
// Gradient Text · syxUI · https://syxui.dev/components/gradient-text
// Free in any project. Keep this line and credit syxUI where a person can read it.

import SwiftUI

/// Type filled with a gradient, plus an optional highlight that travels across
/// the letterforms.
///
/// The fill is a gradient `foregroundStyle` and the highlight is the same
/// glyphs used as a mask, so the effect is independent of font and weight.
struct GradientText: View {
    var text: String = "syxUI"
    var font: Font = .system(size: 56, weight: .heavy, design: .rounded)
    var colors: [Color] = [
        Color(red: 0.36, green: 0.30, blue: 0.90),
        Color(red: 0.87, green: 0.30, blue: 0.62),
        Color(red: 0.95, green: 0.55, blue: 0.25),
    ]
    var shine: Bool = true
    var shinePeriod: Double = 2.6
    /// Pin the highlight at a fixed position (-1 leading, 1 trailing) instead
    /// of sweeping it. Useful for scroll-linked effects and for screenshots.
    var shinePhase: CGFloat? = nil

    @Environment(\.accessibilityReduceMotion) private var reduceMotion
    @State private var animatedPhase: CGFloat = -1

    private var phase: CGFloat { shinePhase ?? animatedPhase }

    var body: some View {
        Text(text)
            .font(font)
            .foregroundStyle(
                LinearGradient(colors: colors, startPoint: .leading, endPoint: .trailing)
            )
            .overlay {
                if shine && !reduceMotion {
                    shineLayer.mask(Text(text).font(font))
                }
            }
            .onAppear(perform: startShine)
            .accessibilityLabel(text)
    }

    /// A narrow bright band swept across the glyphs.
    private var shineLayer: some View {
        GeometryReader { geo in
            LinearGradient(
                colors: [.clear, .white.opacity(0.8), .clear],
                startPoint: .leading,
                endPoint: .trailing
            )
            .frame(width: geo.size.width * 0.45)
            .offset(x: phase * geo.size.width * 1.6)
        }
    }

    private func startShine() {
        guard shine, !reduceMotion, shinePhase == nil else { return }
        withAnimation(.linear(duration: shinePeriod).repeatForever(autoreverses: false)) {
            animatedPhase = 1
        }
    }
}

#Preview {
    GradientText()
        .padding(30)
}
iOS 17 · No dependencies

SwiftUI note. Masking a gradient with the text keeps the effect independent of the font. Set shine: false for a static fill.

Dependencies

SwiftUI
No external dependencies

Requires iOS 17

Flutter
No external dependencies

Requires Flutter 3.27