SwiftUI Gradient Text

How to have text with a gradient fill in SwiftUI

When searching how to implement gradient text with SwiftUI the solution I found was to use a LinearGradient and use the Text element as the mask for that View. However, LinearGradient wants to expand to fill all the available space, and all the examples I found used fixed size Views.

The implementation I came up with to implement this for arbitrary fonts and text was to:

  • Create a transparent text, to set the needed size.
  • Put the LinearGradient into the text's background property.
  • Place a second, duplicate, Text element as the mask for the gradient.

// Custom View
struct GradientText: View {
   
   @State var text: String
   @State var gradient:LinearGradient = LinearGradient(
      gradient: Gradient(colors: [.white, .gray]),
      startPoint: .top,
      endPoint: .bottom
   )
   
   var body: some View {
      Text(text)
      .foregroundColor(Color.clear)
      .background(gradient.mask(Text(self.text)))
   }
   
}

// Example Usage
struct Gradient_Previews: PreviewProvider {
    static var previews: some View {
      GradientText(text: "Hello World Gradient Text!")
         .font(.system(size: 50, weight: .bold))
         .padding()
         .background(Color.black)
         .previewLayout(PreviewLayout.sizeThatFits)
         .padding()
         .previewDisplayName("Example Gradient Text")
    }
}

If anyone knows a better solution without the duplicate Text element please let me know on Twitter or Mastodon.