
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
- Flutter
- No external dependencies
Requires iOS 17
Requires Flutter 3.27


