Clipped Text
Static text must not clip its visible content at its current state or when it is resized.
What We Look For
Visible content of static-text elements should not be clipped, whether it be at the default text size or at larger Dynamic Type sizes.
Failing Example ❌
A fixed height constraint prevents text containers from growing to fit their content
When the user increases their Dynamic Type size, resized text is clipped at the container boundary
Text is cut off without any ellipsis, scroll bars, or indication that this content can be accessed
Passing Example ✅
Flexible height allows the container to grow vertically as text wraps across multiple lines
No content is clipped at any Dynamic Type size
Users who rely on larger text sizes can access all of the information on screen
At a Glance
- This rule has a serious impact for users
- This rule requires iOS 17.0 or later and runs on static text elements that are visible and developer-adjustable
- Static text must not clip its visible content at its current state or when it is resized
- Fix by allowing text to wrap or grow:
- Set
numberOfLines = 0(UIKit), or - Remove
.clipped()/.lineLimit()(SwiftUI)
- Set
Impact to Users
Users with low vision, cognitive disabilities, or who rely on larger text sizes via Dynamic Type may be unable to access information that is clipped. WCAG 1.4.4 (Resize Text) requires that text content remain visible and usable when the user enlarges text. This rule helps catch content that has already been clipped, as well as content that would be clipped if the user increases their text-size setting.
Confirm Clipped Text Issue
- Find Accessibility in iOS Settings
- Select Display & Text Size
- Toggle to select the highest accessibility text size in the Larger Text panel
- Observe the on-screen change:
- Inaccessible: Content is clipped by this view
- Accessible: Content wraps, grows vertically, or can be accessed by scrolling
Fix Issues
- Ensure developer adjustable text containers have sufficient width and height to display the full content, including at the largest Dynamic Type size you intend to support
- Use Auto Layout constraints that allow text to wrap or grow vertically
- Set the
numberOfLinesproperty on text tonumberOfLines = 0 - For scrollable content, verify the scroll view itself is correctly sized so longer text can scroll into view rather than truncate
UIKit
To resolve this issue in UIKit, you typically need both a text fix and a layout fix together. Setting numberOfLines to 0 lets the label wrap, but a fixed height constraint on the label or its container will still cut off the wrapped text. Use greaterThanOrEqualToConstant height constraints as well, so the container can actually grow.
-
Set
numberOfLines = 0onUILabelto allow multi-line wrapping (text fix)label.numberOfLines = 0 -
Replace fixed height Auto Layout constraints with >= so the container can grow to fit the wrapped text
label.heightAnchor.constraint(greaterThanOrEqualToConstant: minHeight).isActive = true
SwiftUI
SwiftUI's layout system automatically sizes elements to fit their content. Avoid using a fixed frame or the clipped() property. The .fixedSize and minHeight properties are only needed in edge cases where a parent element is still imposing its own size constraints on the text.
-
Using the
.clipped()property and/or fixed-size frames are the primary causes of clipped text violations - removing these constraints is usually all that's needed// before Text("Long content that needs to wrap") .truncationMode(.tail) .clipped() .frame(width: 50, height: 20) // after Text("Long content that needs to wrap") -
Remove
.lineLimit(1)or set to nil, as a supporting fix to allow text to wrapText("Your text here") .lineLimit(nil) -
If a parent view is constraining the text size, use
.fixedSize(horizontal: false, vertical: true)to let it expand verticallyText("Long content that needs to wrap") .fixedSize(horizontal: false, vertical: true) -
Optionally, set
minHeighton the frame so it can grow with the contentText("Content").frame(minHeight: minHeight) -
Use
ViewThatFits(iOS 16+) for adaptive layouts that switch arrangement at larger sizes, to prevent clipping before it occursViewThatFits { HStack { Text("Label"); Text("Value") } // compact — fits on one row VStack { Text("Label"); Text("Value") } // falls back to stacked if needed }
React Native
To prevent this issue in React Native, ensure that views have flexible heights. You can use any of the following approaches.
-
Don't set a height at all - the container will size itself to fit its content.
<View style={{ padding: 8 }}> <Text>{text}</Text> </View> -
Use the
minHeightproperty instead ofheight- this sets a floor for short content, but the container is free to grow taller when the text needs more room.<View style={{ minHeight: 30, padding: 8 }}> <Text>{text}</Text> </View> -
Use a flex layout, so the container grows with its content and is never squashed below its natural size.
<View style={{ flexGrow: 1, flexShrink: 0, padding: 8 }}> <Text>{text}</Text> </View> -
Use padding instead of a fixed height - the text's intrinsic size and the amount of padding will determine the container's height.
<View style={{ padding: 16 }}> <Text>{text}</Text> </View> -
Set
numberOfLines={0}so the text can wrap to any number of lines, and pair it with an explicitlineHeightto control vertical spacing.<View style={{ padding: 8 }}> <Text numberOfLines={0} style={{ lineHeight: 30 }}>{text}</Text> </View>
Flutter
Resolving this issue in Flutter typically requires both a text fix and a layout fix together. Text widgets wrap by default, but a fixed-height parent or a non-flexible Row child may still clip the wrapped text. Allow containers to size with their content, and respect the system text scaler so Dynamic Type can scale the font.
-
Allow
Textto wrap across multiple lines by leavingmaxLinesunset and keepingsoftWrap: true, which is the defaultText( longString, softWrap: true, ) -
Use padding on containers wrapping text so the box grows with its content
Container( padding: const EdgeInsets.all(8), child: Text(longString), ) -
Wrap
TextinExpandedorFlexiblewhen it lives inside aRow, so it can wrap to multiple lines as the font scalesRow( children: [ const Icon(Icons.info), Expanded(child: Text(longString)), ], ) -
Make the screen scrollable so scaled text remains reachable when it grows past the viewport
SingleChildScrollView( child: Padding( padding: const EdgeInsets.all(16), child: Text(longString), ), )
Can I Ignore This Rule?
Clipped Text has a Serious impact for users, and we recommend remediating this issue in almost all cases. Text that is clipped is simply unreadable, and there is no equivalent workaround for a user who relies on large Dynamic Type sizes.
In rare cases, you may consider ignoring the result if the clipped element is decorative or redundant - for example, a short label that is fully conveyed by another nearby element or by an image's accessibility label. Learn more about ignoring rules.
Resources
Deque University Course Pages
- 1.4.4a Resize (200%) (See Native Mobile iOS)
Note: Full access to Deque University resources requires a subscription.
Other Resources
- WCAG 2.1 Understanding Docs
- Relates to Understanding SC 1.4.4 - Resize Text
