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



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
- • It takes in the full sentence
(text)
and the word that should flash(flashWord)
. - • If the
flashWord
exists in the text, the component splits the string around that word. - • It reassembles the sentence, replacing every instance of
flashWord
with a<span>
that has the camera flash animation. - • 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:
- •
text
: The complete text content to display. - •
flashWord
: The specific word that should have the flash effect. - •
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.