377

Among the many properties of the Text view, I couldn't find any related to text alignment. I've seen in a demo that it automatically handles RTL, and when placing stuff using View's body, it always centers it automatically.

Is there some concept that I'm missing about layout system in SwiftUI and if not, how can I set the text alignment properties to the Text?

15 Answers 15

587

You can do this via the modifier .multilineTextAlignment(.center).

Text("CENTER")
    .multilineTextAlignment(.center)

Apple Documentation

6
  • 20
    Is something exists to justify text ?
    – theMouk
    Commented Nov 28, 2019 at 10:20
  • 11
    These seems to only work if the text is long enough to wrap. So this example does not work? Commented Nov 9, 2022 at 11:57
  • @Christopher: if the text is not long enough to wrap and you did not fill the parent view, it will take the space it needs to display the text, and thus center in a space exactly the same size, which does nothing. Try adding a border to your Text to see what I mean.
    – vrwim
    Commented Nov 10, 2022 at 10:08
  • See StaticVoidMans answer below.
    – stromyc
    Commented Mar 9, 2023 at 21:49
  • When the content takes only 1 line, it is not aligned as centrally.
    – wzso
    Commented Apr 19, 2024 at 15:33
397

From SwiftUI beta 3 forward, you can center a text view with the frame modifier:

Text("Centered")
    .frame(maxWidth: .infinity, alignment: .center)
3
  • 19
    For some reason, ".multilineTextAlignment()" wasn't giving me the results I wanted, but this did.
    – Chad Mx
    Commented Nov 3, 2021 at 5:47
  • 3
    This doesn't work for the majority of case
    – Arturo
    Commented Dec 17, 2021 at 4:49
  • The reason this one works is because if it's a tight square, having it aligned to its leading, center or trailing is the same since it's just squished in there, but the frame expands that square, so then the alignment makes more sense Commented Jul 25, 2023 at 16:25
265

Was trying to understand this myself as other answers here mention Text.multilineTextAlignment(_:) / VStack(alignment:) / frame(width:alignment:) but each solution solves a specific problem. Eventually it depends on the UI requirement and a combination of these.


VStack(alignment:)

The alignment here is for the inner views in respective to one another.
So specifying .leading would associate all inner views to have their leading aligned with one another.

VStack(alignment: .leading, spacing: 6) {
  Text("Lorem ipsum dolor")
        .background(Color.gray.opacity(0.2))
  Text("sit amet")
        .background(Color.gray.opacity(0.2))
}
.background(Color.gray.opacity(0.1))

image


.frame

In frame(width:alignment:) or frame(maxWidth:alignment:), the alignment is for the contents within the given width.

VStack(alignment: .leading, spacing: 6) {
  Text("Lorem ipsum dolor")
      .background(Color.gray.opacity(0.2))
  Text("sit amet")
      .background(Color.gray.opacity(0.2))
}
.frame(width: 380, alignment: .trailing)
.background(Color.gray.opacity(0.1))

The inners views are leading aligned respective to one another but the views themselves are trailing aligned respective to the VStack.

image


.multilineTextAlignment

This specifies the alignment of the text inside and can be seen best when there are multiple lines otherwise without a defined frame(width:alignment), the width is automatically adjusted and gets affected by the default alignments.

VStack(alignment: .trailing, spacing: 6) {
  Text("0. automatic frame\n+ view at parent's specified alignment\n+ multilineTA not set by default at leading")
    .background(Color.gray.opacity(0.2))
  Text("1. automatic frame\n+ view at parent's specified alignment\n+ multilineTA set to center")
  .multilineTextAlignment(.center)
  .background(Color.gray.opacity(0.2))
  Text("2. automatic frame\n+ view at parent's specified alignment\n+ multilineTA set to trailing")
  .multilineTextAlignment(.trailing)
  .background(Color.gray.opacity(0.2))
}
.frame(width: 380, alignment: .trailing)
.background(Color.gray.opacity(0.1))

image


Tests with combinations:

VStack(alignment: .trailing, spacing: 6) {
  Text("1. automatic frame, at parent's alignment")
  .background(Color.gray.opacity(0.2))
  Text("2. given full width & leading alignment\n+ multilineTA at default leading")
  .frame(maxWidth: .infinity, alignment: .leading)
  .background(Color.gray.opacity(0.2))
  Text("3. given full width & center alignment\n+ multilineTA at default leading")
  .frame(maxWidth: .infinity, alignment: .center)
  .background(Color.gray.opacity(0.2))
  Text("4. given full width & center alignment\n+ multilineTA set to center")
  .multilineTextAlignment(.center)
  .frame(maxWidth: .infinity, alignment: .center)
  .background(Color.gray.opacity(0.2))
  Text("5. given full width & center alignment\n+ multilineTA set to trailing")
  .multilineTextAlignment(.trailing)
  .frame(maxWidth: .infinity, alignment: .center)
  .background(Color.gray.opacity(0.2))
  Text("6. given full width but no alignment\n+ multilineTA at default leading\n+ leading is based on content, looks odd sometimes as seen here")
  .frame(maxWidth: .infinity)
  .background(Color.gray.opacity(0.2))
}
.frame(width: 380)
.background(Color.gray.opacity(0.1))

image

5
  • 8
    That's a very compelling answer. Thank you. I will consider making this an accepted answer as well.
    – inokey
    Commented May 16, 2020 at 7:09
  • 3
    @inokey glad to share my observations :) I later found an interesting article going more in depth with view alignments in general: Alignment Guides in SwiftUI Commented May 16, 2020 at 7:19
  • awesome stuff man. SwiftUI really evolved since I originally posted that question.
    – inokey
    Commented May 16, 2020 at 7:36
  • Do you know why multi line tex becomes one line if I put ex. Spacer().frame(height: 50) If I remove the height from the spacer, the multi line text shows all lines. How do I force showing all lines? Commented Dec 5, 2021 at 15:16
  • 1
    I hate it that this is not the accepted answer. Thank you. Commented Apr 19, 2022 at 4:21
35

I've actually run into the problem where I had to align text on a single line. What I've found to work is this:

Text("some text")
    .frame(alignment: .leading)

If you combine this with the frame width parameter you can get some nice text block formatting for labels and such.

30

I guess SwiftUI wants us to use wrappers like stacks for such things.

So instead of writing something like Text("Hello World").aligned(.leading), the following is encouraged:

VStack(alignment: .leading) {
    Text("Hello World")
}
5
  • 1
    So I can't just drop a label that is independent of stack?
    – inokey
    Commented Jun 4, 2019 at 12:40
  • @inokey I didn't find a modifier for this at least.
    – fredpi
    Commented Jun 4, 2019 at 13:13
  • I didn't either. It seems to me like I miss some sort of a base concept from SUI. I can't even drop like just the "view" in between two things, and give it a color, like they don't have plain a-la-uiview object in there.
    – inokey
    Commented Jun 4, 2019 at 13:16
  • 1
    The frame modifier has an alignment parameter Commented Jun 12, 2019 at 5:40
  • 1
    Seems silly to have to do (although it does work). Where did you hear that this was encouraged?
    – MobileMon
    Commented Jul 31, 2019 at 19:26
23

We need to align the Text and not the Stack it's in. So calling multilineTextAlignment(.center) and setting the line limits I can be able to see the texts aligned to center. I don't know why I have to set the line limits, I thought it would expand if you have a large text.

Text("blahblah")
        .font(.headline)
        .multilineTextAlignment(.center)
        .lineLimit(50)
22

I had the same problem. i used this for fixing that.

Text("Test")
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading)
2
  • 1
    This produces very strange results, I wouldn't recommend Commented Dec 14, 2021 at 8:38
  • 1
    This resolved my problem. I tried to implement GridItem(s) and inside it Circle() and Text() is there. But Alignment of text makes my UI messy. After trying 2 hours this answer saved my! JazakAllah Khair Kaseera.
    – Mubin Mall
    Commented Oct 17, 2022 at 9:59
22

There are multiple ways for the alignment of text in SwiftUI-

1st-

VStack(alignment: .leading){    
   Text("Leading alignment")    
}

2nd -

VStack{    
   Text("Leading alignment")
     .multilineTextAlignment(.leading)    
}

3rd -

VStack{    
   Text("Leading alignment")    
}.frame(maxWidth: .infinity, alignment: .leading)

And to shift the whole block of text use Spacer() under the HStack -

 HStack {  
    Text("Leading alignment")   
    Spacer()  
 }
2
  • Thanks for this answer, particularly the 3rd option; it's very simple. For anyone looking to centre-align: wrap the Text() blocks with a Spacer() on top and below, inside of the HStack{}. For right-alignment, simply put a Spacer() on top of the Text().
    – Daggerpov
    Commented Mar 26, 2024 at 1:49
  • You don't even need VStack in the second case, a simple Group works too. Commented Apr 18, 2024 at 7:13
18

If you would like to keep constant width for the Text, the ".multilineTextAlignment(.leading)" won't take any effect until there is only one line of text.

This is the solution that worked for me:

struct LeftAligned: ViewModifier {
    func body(content: Content) -> some View {
        HStack {
            content
            Spacer()
        }
    }
}


extension View {
    func leftAligned() -> some View {
        return self.modifier(LeftAligned())
    }
}

Usage:

Text("Hello").leftAligned().frame(width: 300)
14

You can set alignment for Vertical stackView as leading. Like below

 VStack(alignment: .leading) {
            Text("Turtle Rock")
                .font(.title)
            Text("Joshua Tree National Park")
                .font(.subheadline)
        }

enter image description here

14

I'd like to use Spacer() view to aligning text block. This example show text at the trailing side:

HStack{
    Spacer()
    Text("Wishlist")
}
10

You can always add a frame to the Text field and can modify it's alignment.

Text("Hello World!")
   .frame(alignment : .topLeading)

Since, this is just for a couple of lines - this is better than using alignment on either of the Stacks

5

Default .center value

You can redefine multilineTextAlignment() method using a modified content:

import SwiftUI

extension View {
    func multilineTextAlignment() -> some View {
        ModifiedContent(content: self, modifier: AlignedText())
    }
}

struct AlignedText : ViewModifier {
    func body(content: Content) -> some View {
        content
            .foregroundColor(.white)
            .background(.black)
            .multilineTextAlignment(.center)
    }
}

...and then use multilineTextAlignment() with no explicit parameter's value.

struct ContentView : View {
    var body: some View {
        Text("SwiftUI SwiftUI SwiftUI SwiftUI SwiftUI")
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .font(.largeTitle)
            .multilineTextAlignment()    // Center alignment is a new DEFAULT
    }
}

enter image description here

1

You can use this property of SwiftUI

multilineTextAlignment

for TextAlignment.

VStack { 
    Text("Your Text")
      .multilineTextAlignment(.center)
}
0

Not sure if this is the answer you are looking for but I have experienced that SwiftUI automatically switches to RTL for languages like Arabic, you don't need to explicitly specify that like in UIKit.

Not the answer you're looking for? Browse other questions tagged or ask your own question.