Props
Usage guidelines
- Any time that text is needed in the UI as a label, paragraph or number display
- When you need to use a semantic H1–H6 heading to create a clear typographic hierarchy and page structure. Use Heading instead.
Best practices
Emphasize text inside of paragraphs by using a bold weight.
Emphasize text inside of paragraphs by underlining it; this can be confused with Link.
Use size to emphasize things like numbers that don’t define a page structure.
Use as section, page or surface titles to create a logical hierarchy. Use Heading instead.
Use a minimal amount of sizes and styles to keep the UI clean and readable.
Mix styles and alignment, as this can be hard to read and follow.
Start-align paragraph text.
Center-align paragraph text. This is hard to read, especially for users with dyslexia.
Accessibility
Accessible sizing
A minimum text size of 16 px (12pt) is recommended for readability. Some short text labels, or secondary text can go lower than that, but smaller sizes should be kept to a minimum. Making text brief will also help with readability.
Accessible color
For low-vision users, text color contrast is very important. To insure accessible contrast, stick to our standard text colors. See our accessibility page for design considerations and handy accessibility tools for checking color contrast.
Localization
Keep text simple and short to avoid truncation or line wrapping in UI controls like buttons when translating languages that require more characters. Avoid overriding our line-height settings, as this can result in text clipping for scripts, like Hindi, that have taller ascenders and descenders.
Text-wrapping and hyphenation
Hyphenation on iOS is turned off by default to avoid incorrect word breaks when strings of text wrap to the next line. This is especially helpful for international languages where an incorrect word break can greatly change the meaning of a word or sentence.
Variants
Alignment
Use align
to adjust the positioning of text within wrapper elements.
import { Divider, Flex, Text } from 'gestalt'; export default function Example() { return ( <Flex alignItems="center" height="100%" justifyContent="center" width="100%" > <Flex direction="column" gap={{ column: 4, row: 0 }} width={200}> <Text align="start">Start (default)</Text> <Divider /> <Text align="end">End</Text> <Divider /> <Text align="center">Center</Text> <Divider /> <Text align="forceLeft">Force left</Text> <Divider /> <Text align="forceRight">Force right</Text> </Flex> </Flex> ); }
Block vs. inline
The Text component allows you to specify whether you want block
or inline
text.
import { Box, Flex, Text } from 'gestalt'; export default function Example() { return ( <Flex alignItems="center" height="100%" justifyContent="center" width="100%" > <Flex alignItems="start" direction="column" gap={{ column: 4, row: 0 }}> <Text>Some content in a default block element. (default)</Text> <Box> <Text inline>Inline text with the inline prop.</Text>{' '} <Text inline>More inline text.</Text> </Box> </Flex> </Flex> ); }
Colors
You can specify which color you want for your text. Most colors change in dark mode, but light
and dark
are available when no switch is desired.
import { Box, Flex, Text } from 'gestalt'; export default function Example() { return ( <Flex alignItems="center" height="100%" justifyContent="center" width="100%" > <Flex alignItems="start" direction="column" gap={{ column: 3, row: 0 }}> <Box color="inverse" padding={1}> <Text color="inverse" size="400"> Inverse </Text> </Box> <Text color="subtle" size="400"> Subtle </Text> <Text color="default" size="400"> Default </Text> <Text color="success" size="400"> Success </Text> <Text color="warning" size="400"> Warning </Text> <Text color="error" size="400"> Error </Text> <Text color="shopping" size="400"> Shopping </Text> <Box color="primary" padding={1}> <Text color="light" size="400"> Light </Text> </Box> <Box color="infoWeak" padding={1}> <Text color="dark" size="400"> Dark </Text> </Box> </Flex> </Flex> ); }
Overflow & truncation
Gestalt provides utility options to deal with text overflow.
import { Box, Flex, Text } from 'gestalt'; export default function Example() { return ( <Flex alignItems="center" justifyContent="center" width="100%" height="100%" > <Flex direction="column" gap={{ column: 2, row: 0 }} width={200}> <Text>breakWord (default):</Text> <Box color="secondary" padding={2} rounding={2}> <Text> This is a long and Supercalifragilisticexpialidocious sentence. 次の単語グレートブリテンおよび北アイルランド連合王国で本当に大きな言葉 </Text> </Box> <Text>normal:</Text> <Box color="secondary" padding={2} rounding={2}> <Text overflow="normal"> This is a long and Supercalifragilisticexpialidocious sentence. 次の単語グレートブリテンおよび北アイルランド連合王国で本当に大きな言葉 </Text> </Box> <Text>lineClamp:</Text> <Box color="secondary" padding={2} rounding={2}> <Text lineClamp={2}> This is a long and Supercalifragilisticexpialidocious sentence. 次の単語グレートブリテンおよび北アイルランド連合王国で本当に大きな言葉 </Text> </Box> </Flex> </Flex> ); }
Sizes
You can apply size
options to define the size of the text. These font sizes follow those available through our Design Tokens. If your text needs to be a semantic heading (H1-H6), use Heading instead.
import { Flex, Text } from 'gestalt'; export default function Example() { return ( <Flex alignItems="center" height="100%" justifyContent="center" width="100%" > <Flex direction="column" alignItems="start" gap={{ row: 2, column: 0 }}> <Flex alignItems="center" gap={{ row: 2, column: 0 }}> <Text inline size="100"> Size 100 </Text> <span lang="ja"> <Text inline size="100"> こんにちは </Text> </span> </Flex> <Flex alignItems="center" gap={{ row: 2, column: 0 }}> <Text inline size="200"> Size 200 </Text> <span lang="ja"> <Text inline size="200"> こんにちは </Text> </span> </Flex> <Flex alignItems="center" gap={{ row: 2, column: 0 }}> <Text inline size="300"> Size 300 (default size) </Text> <span lang="ja"> <Text inline size="300"> こんにちは </Text> </span> </Flex> <Flex alignItems="center" gap={{ row: 2, column: 0 }}> <Text inline size="400"> Size 400 </Text> <span lang="ja"> <Text inline size="400"> こんにちは </Text> </span> </Flex> <Flex alignItems="center" gap={{ row: 2, column: 0 }}> <Text inline size="500"> Size 500 </Text> <span lang="ja"> <Text inline size="500"> こんにちは </Text> </span> </Flex> <Flex alignItems="center" gap={{ row: 2, column: 0 }}> <Text inline size="600"> Size 600 </Text> <span lang="ja"> <Text inline size="600"> こんにちは </Text> </span> </Flex> </Flex> </Flex> ); }
Styles
There are multiple styles, such as bold and italic, that we can attach to the Text component.
import { Flex, Text } from 'gestalt'; export default function Example() { return ( <Flex alignItems="center" height="100%" justifyContent="center" width="100%" > <Flex direction="column" alignItems="start" gap={2}> <Text weight="bold">Bold</Text> <Text italic>Italic</Text> <Text underline>Underline</Text> </Flex> </Flex> ); }
Title
The title
attribute on a <div>
can be used to show the full text of a truncated string on hover. That attribute is populated automatically when the text is truncated using lineClamp
, as long as children
is a string.
If children
is a React.Node
(e.g. when using Link), use the title
prop to manually set the title
attribute.
import { Flex, Text, Box, Link } from 'gestalt'; export default function Example() { return ( <Flex alignItems="center" height="100%" justifyContent="center" width="100%" > <Flex direction="column" alignItems="start" gap={2}> <Flex alignItems="center" direction="column" gap={{ column: 2, row: 0 }} > <Text size="200" weight="bold"> Hover over the examples below for a few seconds to see the title text: </Text> <Box borderStyle="sm" maxWidth={400} padding={1}> <Flex direction="column" gap={{ column: 3, row: 0 }}> <Flex direction="column" gap={{ column: 1, row: 0 }}> <Text italic size="100"> This title attribute is automatically added because lineClamp is used and children is a string. </Text> <Text lineClamp={1}> This is a long and Supercalifragilisticexpialidocious sentence. 次の単語グレートブリテンおよび北アイルランド連合王国で本当に大きな言葉 </Text> </Flex> <Flex direction="column" gap={{ column: 1, row: 0 }}> <Text italic size="100"> This example uses lineClamp but has no title attribute, because children is a React.Node. </Text> <Text lineClamp={1}> <Link href="#"> This is a long and Supercalifragilisticexpialidocious sentence. 次の単語グレートブリテンおよび北アイルランド連合王国で本当に大きな言葉 </Link> </Text> </Flex> <Flex direction="column" gap={{ column: 1, row: 0 }}> <Text italic size="100"> This example uses lineClamp and children is a React.Node, but uses the title prop. </Text> <Text lineClamp={1} title="This is a long and Supercalifragilisticexpialidocious sentence. 次の単語グレートブリテンおよび北アイルランド連合王国で本当に大きな言葉" > <Link href="#"> This is a long and Supercalifragilisticexpialidocious sentence. 次の単語グレートブリテンおよび北アイルランド連合王国で本当に大きな言葉 </Link> </Text> </Flex> </Flex> </Box> </Flex> </Flex> </Flex> ); }
Refs
Don't use ref
to manipulate the underlaying HTML div or span elements. Use ref
to only read HTML attributes. For example, a valid use case can be detecting truncation. The example below illustrates a case where detecting truncation allows rendering links contained within Text.
import { useEffect, useRef, useState } from 'react'; import { Label, Switch, Flex, Text, Box, Link } from 'gestalt'; export default function Example() { const [showLongText, setShowLongText] = useState(false); const [applyTruncationDetection, setApplyTruncationDetection] = useState(false); const text = 'Tag brand partners in your Idea Pins with the paid partnership tool.'; const veryLongText = 'Tag brand partners in your Idea Pins with the paid partnership tool. Just make an Idea Pin in the app, add the paid partnership label and tag your partner brand. Once they approve the request, their brand name will show up on your Idea Pin. Brands can also choose to promote your Idea Pins as ads, boosting your reach to even more people. When you use the paid partnership tool, you work directly with brands to define the payment terms and process. Pinterest will not be directly involved in payment.'; const textRef = useRef(null); const [ellipsisActive, setEllipsisActive] = useState(false); const isEllipsisActive = (element) => element.offsetHeight < element.scrollHeight || element.offsetWidth < element.scrollWidth; useEffect(() => { const checkEllipsisActive = () => { if (textRef.current) { if (!ellipsisActive && isEllipsisActive(textRef.current)) { setEllipsisActive(true); } else if (ellipsisActive && !isEllipsisActive(textRef.current)) { setEllipsisActive(false); } } }; checkEllipsisActive(); window.addEventListener('resize', checkEllipsisActive); return () => { window.removeEventListener('resize', checkEllipsisActive); }; }); return ( <Flex alignItems="center" height="100%" justifyContent="center" width="100%" > <Flex gap={8} direction="column" width="90%"> <Flex gap={2} direction="column"> <Box display="flex" alignItems="center"> <Box paddingX={2} WIDTH> <Label htmlFor="longText"> <Text>Show long text</Text> </Label> </Box> <Switch onChange={() => setShowLongText(!showLongText)} id="longText" switched={showLongText} /> </Box> <Box display="flex" alignItems="center"> <Box paddingX={2}> <Label htmlFor="truncation"> <Text>Apply truncation detection</Text> </Label> </Box> <Switch onChange={() => setApplyTruncationDetection(!applyTruncationDetection) } id="truncation" switched={applyTruncationDetection} /> </Box> </Flex> <Flex direction="column"> <Text inline align="start" lineClamp={2} ref={textRef} title={ ellipsisActive && typeof veryLongText === 'string' ? veryLongText : undefined } > {showLongText ? veryLongText : text}{' '} <Text inline> <Link accessibilityLabel="Visit our Help Site" href="#" display="inline" > Visit our Help Site </Link> </Text> </Text> {ellipsisActive && applyTruncationDetection ? ( <Text> <Link accessibilityLabel="Visit our Help Site" href="#" display="inline" > Visit our Help Site </Link> </Text> ) : null} </Flex> </Flex> </Flex> ); }
Writing
- Keep text in UI components short and clear
- Use Sentence case for UI labels
- Use long text labels that could end up truncating or causing space issues when translating to other languages
- Use Title Case or ALL CAPS in UI labels
- Use ALL CAPS for paragaph text unless referring to a product or other entity that uses that style
Related
Heading
Heading allows you to add H1–H6 level text on a page. They are generally placed underneath a PageHeader, and provide you with a way to create a logical text hierarchy.
Typography guidelines
A run-down on our typographic foundations, with some guidelines for using Heading and Text components together in products.
Design tokens
Values for text sizes, weights, families and colors.
Link
Used as a text-only navigational element. Links usually appear within or directly following a paragraph or sentence.
Component quality checklist
Quality item | Status | Status description |
---|---|---|
Figma Library | Ready | Component is available in Figma across all platforms. |
Responsive Web | Ready | Component is available in code for web and mobile web. |
iOS | Ready | Component is available in code for iOS. |
Android | Ready | Component is available in code for Android. |