Code Talk: How the Flash Effect Was Created on My Website

Cover Image for Code Talk: How the Flash Effect Was Created on My Website
Mal Nushi
Mal Nushi

On the 'Photography' page on my personal website, I wanted to add a little bit of flair to match the page. I came up with the idea of making a single word in a sentence flash like a camera.

In this post, I want to go over how I made the component.

The Purpose

For every page on the 'sidequest' subpage on my website, I want to add something that is thematically relevant of the activity on the page. In this case, I needed to create a component that is in a way reminisicent of a camera flash.

Code

Here is the source code for the component:

/**
 * What is this component you say??? It is a FlashingText component.
 *
 * It is a client component that displays text with a camera flash effect on a given word.
 * Check the photography page to see it in action, baby!
 */

"use client";

import React from "react";

/**
 * Props for the FlashingText component.
 * @property {string} text - The complete text content to display
 * @property {string} flashWord - The specific word that should have the flash effect
 * @property {string} [className] - Optional CSS class name for styling the container paragraph
 */
interface FlashingTextProps {
  text: string;
  flashWord: string;
  className?: string;
}

/**
 * This renders the text with a camera flash effect applied to a chosen word.
 *
 * @param {Object} props - Component props
 * @param {string} props.text - The full text to display
 * @param {string} props.flashWord - The word within the text that should flash
 * @param {string} [props.className] - Optional CSS class for styling
 * @returns - The rendered text with flash effect
 */
export default function FlashingText({
  text,
  flashWord,
  className,
}: FlashingTextProps): React.JSX.Element {
  // If flashWord is not in text, just return the text
  if (!text.includes(flashWord)) {
    return <p className={className}>{text}</p>;
  }

  // Split the text by the flashWord to create parts
  const parts = text.split(flashWord);

  return (
    <p className={className}>
      {parts.map((part, index) => (
        <React.Fragment key={index}>
          {part}
          {index < parts.length - 1 && (
            <span className="camera-flash">{flashWord}</span>
          )}
        </React.Fragment>
      ))}
      <style jsx>{`
        .camera-flash {
          position: relative;
          animation: cameraFlash 3s infinite;
        }
        @keyframes cameraFlash {
          0%,
          100% {
            color: inherit;
          }
          5% {
            color: white;
            text-shadow: 0 0 8px white, 0 0 15px white;
          }
          10% {
            color: inherit;
            text-shadow: none;
          }
        }
      `}</style>
    </p>
  );
}

How It Works

  1. • It takes in the full sentence (text) and the word that should flash (flashWord).
  2. • If the flashWord exists in the text, the component splits the string around that word.
  3. • It reassembles the sentence, replacing every instance of flashWord with a <span> that has the camera flash animation.
  4. • The flash effect is achieved with a quick white text-shadow burst using keyframes.

Component Design

I choose to use <style jsx> instead of an external CSS file to keep the animation self-contained. I want the styling to travel with the component and prevent any future issues like className clashing and not having to worry about global stylesheets or tailwind overrides.

I could have chose to regex for this component to filter out the specific word I wanted to add the effect to, but I felt like the approach I went with, which is replacing every instance of the flashWord without altering the original string. Using text.split(flashWord) and rebuilding the string using React.Fragments, I think I was able to achieve that.

The API

The component accepts four props:

  1. text: The complete text content to display.
  2. flashWord: The specific word that should have the flash effect.
  3. className: Optional CSS class name for styling the container paragraph.
/**
 * Props for the FlashingText component.
 * @property {string} text - The complete text content to display
 * @property {string} flashWord - The specific word that should have the flash effect
 * @property {string} [className] - Optional CSS class name for styling the container paragraph
 */
interface FlashingTextProps {
  text: string;
  flashWord: string;
  className?: string;
}

Usage

This component is used on the Photography page like this:

<FlashingText
  text="I like taking pictures of things. Specifically, I like taking pictures of urban environments and architecture."
  flashWord="things"
  className="mb-8 text-neutral-600 dark:text-neutral-400"
/>

In this example, the word "flash" flashes periodically.