How to Build a Scrollable Text Highlighter in React Native with Auto-Scroll

7 min read
#React Native#UI#Animation#Auto Scroll#JavaScript

Create a stunning scrollable text highlighter in React Native that reveals 3 words at a time with smooth auto-scrolling and dynamic transparency. Perfect for storytelling, presentations, or educational apps.

How do I highlight words in a long scrollable text and scroll with them automatically?
If you've ever needed this for a storytelling app, programming demo, or interactive UI — you're in the right place.

In this post, I’ll walk you through building a scrollable text component in React Native that:

  • Displays a long block of text
  • Highlights 3 words at a time
  • Automatically scrolls when the current words go out of view
  • Uses fading transitions to focus the user’s attention
  • Is powered by ScrollView, refs, and layout measuring

Why Build This?

Sometimes in apps, we want to focus user attention on parts of a long text — for example, in tutorials, storytelling apps, or educational content. Highlighting a few words at a time with a smooth scroll creates an engaging experience.


🧠 Thought Process

Before diving into code, I mapped the experience I wanted:

  1. Scrollable long text
  2. Overlay the same text on top
  3. Make the top layer semi-transparent, except 3 words
  4. Auto-scroll when words move out of view
  5. Loop the animation every few seconds
  6. Stop scrolling at the end

Each requirement adds a small layer of complexity — so we tackle them one step at a time.


Step 1: Setting Up the Base Component and Text

const programmingFacts = `
The history of programming languages dates back to the 19th century with Ada Lovelace, who is often considered the first computer programmer. She worked on Charles Babbage's Analytical Engine and wrote the first algorithm intended to be processed by a machine. In the 1940s, assembly languages emerged, allowing humans to write instructions in symbolic code instead of binary. FORTRAN, developed in the 1950s, was one of the first high-level programming languages and significantly boosted scientific computing.

The 1970s brought the creation of C by Dennis Ritchie, which became widely popular due to its efficiency and control over system resources. Meanwhile, the object-oriented paradigm took hold with languages like Smalltalk and later C++. Java arrived in the 1990s with its promise of “write once, run anywhere,” revolutionizing cross-platform software development.

The rise of the internet era saw scripting languages like JavaScript, PHP, and Python gain popularity for web development. Python, created by Guido van Rossum in 1991, is renowned for its readability and simplicity, making it a favorite among beginners and professionals alike.

Functional programming concepts, though originating earlier, gained renewed interest with languages like Haskell and Scala. Meanwhile, modern languages like Rust focus on memory safety and concurrency.

Programming continues to evolve with new paradigms and languages emerging to solve complex problems efficiently. The journey from Ada Lovelace’s first algorithm to today’s diverse ecosystem highlights the rich and dynamic history of programming.
`.repeat(10);

Thought process: This text is long and informative, perfect for scrolling, and it’s real content to demonstrate a useful UI pattern.


Step 2: Splitting Text into Words

To highlight 3 words at a time, we need to split the entire text into individual words.

const words = programmingFacts.trim().split(/\s+/);

Why? We want to control opacity per word and update the highlighted words on a timer. Splitting lets us access each word separately.


Step 3: State to Track the Visible Word Index

We’ll keep track of the starting index of the 3 visible words with React state:

const [visibleIndex, setVisibleIndex] = useState(0);

Why? > visibleIndex controls which words are fully visible. Every 3 seconds, we’ll increment this by 3 to shift the spotlight.


Step 4: Cycling Through Words on a Timer

We use a useEffect hook to update the visibleIndex every 3 seconds.

useEffect(() => {
  const interval = setInterval(() => {
    setVisibleIndex((prev) => {
      const maxIndex = words.length - 1;
      const nextIndex = prev + 3;

      if (nextIndex > maxIndex) {
        const lastGroupStart = Math.max(words.length - 3, 0);
        if (prev === lastGroupStart) {
          clearInterval(interval);
          return prev;
        }
        return lastGroupStart;
      }
      return nextIndex;
    });
  }, 3000);

  return () => clearInterval(interval);
}, [words.length]);

Thought process:

  • We move the spotlight forward by 3 words.
  • If the next group overshoots the total words, we jump to the last possible group (which might have fewer than 3 words).
  • Then, we stop updating further to avoid looping.

Step 5: Creating Refs to Each Word

To auto-scroll to the currently highlighted words, we must measure their position on the screen. React Native’s measurement APIs require each item to have its own native view ref.

const wordRefs = useRef([]);

Inside rendering:

{words.map((word, index) => (
  <View key={index} ref={(el) => (wordRefs.current[index] = el)}>
    <Text style={{ /* style with opacity controlled */ }}>
      {word}
    </Text>
  </View>
))}

Why a <View>? Because measuring inline nested <Text> is unreliable. Wrapping words in <View> gives measurable layout nodes.


Step 6: Auto-Scrolling on Highlight Change

Whenever visibleIndex changes, we measure the position of the first visible word and scroll the ScrollView to bring it into view:

  const scrollToWord = () => {
    const ref = wordRefs.current[visibleIndex];
    if (!ref || !scrollViewRef.current) return;

    UIManager.measureLayout(
      findNodeHandle(ref),
      findNodeHandle(scrollViewRef.current),
      () => {},
      (x, y) => {
        scrollViewRef.current.scrollTo({ y: y - 50, animated: true });
      }
    );
  };

  setTimeout(scrollToWord, 100);
}, [visibleIndex]);

Thought process:

  • UIManager.measureLayout finds the relative position of the word inside the scroll view.
  • We offset by 50 pixels to avoid scrolling the word too close to the top edge.
  • A small delay (setTimeout) lets React Native complete layout before measuring.

Step 7: Styling the Text and Overlay

We use two layers:

  • Background full text (fully visible, blurred by a BlurView to soften).
  • Overlay text where we highlight only 3 words by setting their opacity to 1 and others to 0.
const styles = StyleSheet.create({
  container: { flex: 1, paddingTop: 50 },
  scrollContainer: { paddingVertical: 20 },
  text: {
    fontSize: 26,
    lineHeight: 24,
    color: 'black',
    marginHorizontal: 16,
    letterSpacing: 1.2,
  },
  overlayText: {
    position: 'absolute',
    top: 0,
    left: 0,
  },
});

Inside render:

<Text style={styles.text}>{words.join(' ')}</Text>

<BlurView style={StyleSheet.absoluteFill} blurType="light" blurAmount={10} pointerEvents="none" />

<View style={[styles.text, styles.overlayText, { flexDirection: 'row', flexWrap: 'wrap' }]}>
  {words.map((word, index) => (
    <View key={index} ref={(el) => (wordRefs.current[index] = el)}>
      <Text
        style={{
          opacity: index >= visibleIndex && index < visibleIndex + 3 ? 1 : 0,
          fontSize: styles.text.fontSize,
          lineHeight: styles.text.lineHeight,
          letterSpacing: styles.text.letterSpacing,
          color: styles.text.color,
          marginRight: 4,
        }}
      >
        {word}
      </Text>
    </View>
  ))}
</View>

Why two layers? The blur softens the entire text behind, making the highlighted words on top visually pop out.


🔗 Get the Full Source Code

👉 Access the complete source code for this component directly on GitHub Gist:

View the full code on Gist


🎥 Watch the Demo Video

See this scrollable spotlight effect in action on YouTube:


Conclusion

This tutorial demonstrated how to combine timed state updates, refs, layout measurement, and React Native styling to build a dynamic, scrollable text highlighter. You can customize the number of visible words, timing, and styling as needed.

Feel free to extend this for different kinds of storytelling, educational apps, or presentations!

Let's bring your app idea to life

I specialize in mobile and backend development.

Share this article

Related Articles