skip to content

In a React Native poetry app, how do you render one paragraph with inline bold and tappable linked words, and what do nested pieces inherit?

level: middleimportance: must knowfreq 62%

answer

  1. one paragraph, one attributed string
  2. nested Text is a span, not a box
  3. inheritance only inside a Text subtree
  4. View passes no text styles down
  5. onPress on a span taps that range

basics

~20 s

Nest Text inside Text: React Native flattens the tree into one attributed string, so bold or linked words are inline spans that wrap with the line. Nested Text inherits its ancestor Text's text styles and can override them; a View passes none down.

solid answer

~40 s

Write the stanza as one outer `Text` and nest a `Text` for each bold phrase or linked word. React Native flattens the whole subtree into a single `NSAttributedString` on iOS or `SpannableString` on Android, so the nested pieces are **ranges of one paragraph**, not separate boxes: they wrap mid-line with the surrounding words. Each nested `Text` inherits the text attributes of its `Text` ancestors, such as `fontFamily`, `fontSize`, `fontWeight` and `color`, and overrides only what it sets. Box styles like `padding`, `margin` or `width` do nothing on a nested span. A linked word is a nested `Text` with `onPress`; only its range responds. Inheritance stops at the `Text` boundary: a `View` cannot hand `color` or `fontSize` down, so shared defaults go in a small wrapper component around `Text`.

code

tsx · 22 lines
tsx
import {StyleSheet, Text} from 'react-native';

type Props = {onGlossary: (term: string) => void};

export function Stanza({onGlossary}: Props) {
  return (
    <Text style={styles.stanza}>
      Salt wind combs the <Text style={styles.bold}>harbour grass</Text> and
      sings of the{' '}
      <Text style={styles.link} onPress={() => onGlossary('selkie')}>
        selkie
      </Text>{' '}
      asleep beneath the tide.
    </Text>
  );
}

const styles = StyleSheet.create({
  stanza: {fontSize: 18, lineHeight: 28, color: '#222'},
  bold: {fontWeight: 'bold'},
  link: {color: '#1a5fb4', textDecorationLine: 'underline'},
});

go deeper

for a junior

Recall that inline formatting means nesting Text inside Text, and that nested Text inherits its parent Text's text styles while a View passes none.

for a middle

Explain the flattening into one NSAttributedString or SpannableString, why nested spans wrap with the line, and why box styles on a nested Text are ignored.

for a senior

Show how you would structure a shared text component so defaults flow through Text nesting, and how you keep tappable spans small and clearly styled in long paragraphs.

for a principal

Discuss the isolation trade React Native made against CSS inheritance: predictable components in exchange for explicit, team-wide text primitives that must be designed and enforced.

## The problem: mixed formatting inside one paragraph A poetry app is the purest version of this problem. A stanza is one paragraph, yet a few words are **bold** for emphasis and a few are **links** to a glossary entry. The formatting must flow with the text: when the line wraps, the bold phrase and the linked word wrap with it, exactly where the words fall. Both platforms solve this natively with *attributed text*: a single string plus a list of ranges, each carrying attributes such as bold or a colour (`NSAttributedString` on iOS, `SpannableString` on Android). Building those range lists by hand is tedious, so React Native lets you express them by **nesting `Text` inside `Text`**. ## How nesting is flattened 1. The outermost `Text` becomes the native **paragraph** view. It is the only box that takes part in flexbox layout. 2. Every `Text` nested inside it is rendered as a *virtual* text node, not as a native view. 3. React Native walks the subtree and produces one attributed string: the concatenated characters plus one attribute range per nested `Text`. 4. The platform's text engine lays that string out, breaking lines wherever the words fall, regardless of where the spans begin or end. For `<Text style={{fontWeight: 'bold'}}>I am bold <Text style={{color: 'red'}}>and red</Text></Text>` the result is one string, `I am bold and red`, where the first range is bold and the second is bold **and** red. ## What a nested Text inherits Inheritance in React Native is **limited to text subtrees**. A nested `Text` starts from its ancestor `Text`'s text attributes and applies its own style on top. | Style | On the outer Text | On a nested Text | |---|---|---| | `fontFamily`, `fontSize`, `fontWeight`, `fontStyle` | sets the paragraph default | inherited; override per span | | `color`, `backgroundColor`, `textDecorationLine` | sets the paragraph default | inherited; override per span | | `padding`, `margin`, `borderWidth`, `width` | lays out the paragraph box | ignored: a span is not a box | | `onPress`, `onLongPress` | makes the whole paragraph pressable | makes only that span's range pressable | Three consequences follow: - **A `View` passes nothing down.** `View` style has no text attributes, so `color` or `fontSize` on a container never reaches the `Text` inside it; TypeScript rejects them on `ViewStyle`. - **Siblings in a `View` are blocks.** Two `Text` elements side by side in a `View` are two separate paragraphs, each wrapping inside its own box. Only nesting inside one `Text` gives inline flow. - **Spans cannot be spaced like boxes.** To separate a linked word visually, change its text attributes (colour, underline) or add spaces in the string; `margin` on a nested `Text` has no effect. ## Linked words A glossary link is a nested `Text` with an `onPress`. The press handling is attached to that range of the attributed string, so a tap on the linked word fires its handler while a tap on plain words around it does not. What the handler does, such as opening a screen or a URL, is ordinary app code. Since React Native 0.84 a `Text` with `onPress` or `onLongPress` is also announced to screen readers as a link by default. ## Sharing the paragraph style Because there is no inheritance from containers, an app cannot set one font on the root and have every `Text` pick it up. The idiomatic answer is composition: - write a `PoemText` component that renders `Text` with the app's paragraph style and passes children through; - build variations (`PoemTitle`, `Footnote`) by nesting a styled `Text` inside `PoemText`, so they inherit its defaults and override only what differs; - keep per-word styling as nested `Text` inside those components. ## The contrast with CSS On the web, inherited CSS properties such as `font-family` and `color` cascade from any ancestor element, so styling the `body` restyles the whole page. React Native deliberately does not do this. A component renders the same wherever it is dropped, because nothing outside its own `Text` tree can change its text attributes, and the native side only stores text attributes where text actually is. The price is that shared defaults are explicit components rather than one rule at the root.

  • In React Native, why does adding margin to a nested Text around a linked word not move it?
    A nested `Text` is not a native view and not a flexbox item; it is a range inside the parent paragraph's attributed string. Attributed text carries text attributes such as font, colour and decoration, not box geometry, so `margin`, `padding` and `width` have nothing to apply to. Use spacing characters or text attributes, or restructure into separate boxes if the design really needs box spacing.
  • In React Native, why doesn't `color` on a parent View reach the Text inside it, and what do teams use instead?
    Style inheritance only exists inside a `Text` subtree; a `View` has no text attributes to pass down, and `ViewStyle` does not even accept `color` or `fontSize` in TypeScript. Teams create a shared text component that renders `Text` with the default style and nest more specific styled `Text` inside it for variants, so defaults are inherited through the `Text` tree rather than a container.

A nested Text is a highlighter stroke on one printed line, not a sticky note stuck on the page: it colours a run of words that still wraps with the sentence, and it takes up no space of its own.

saying these in an interview costs you the question

  • Setting color or fontSize on a View styles every Text inside it, like a CSS cascade.
  • Each nested Text becomes its own native view laid out by flexbox.
  • Padding or margin on a nested Text adds space around that word.
  • Two sibling Text elements in a View flow inline like one paragraph.
  • A nested Text cannot override a style it inherited from its parent Text.