fervor [>]CODING & CURIOSITY
FERVOR LEARNING SYSTEMTUTORIALS
← React

React / 10 MIN READ

Background Image Component

Reusable component for background images

From the original Fervor library. Examples may use older package versions.

Create a Background Image Component in React

Introduction

In modern web design, background images play a pivotal role in enhancing user experience. They add depth, character, and visual interest to web pages. When working with React, it’s common to find scenarios where you’d want to change a background image dynamically or keep the logic modular. In this tutorial, we’ll delve into creating a reusable BackgroundImage component in React that can be easily integrated into any project.

Overview

A BackgroundImage component provides a dedicated and isolated module where you can define the logic, styling, and behavior of a background image. By doing this, you achieve clean code, enhance maintainability, and pave the way for potential enhancements like transitions or animations.

Code Explanation

BackgroundImage Component

We initiate by setting up the BackgroundImage component:

function BackgroundImage({ imageUrl }) {
    return (
        <div className="background-image" style={{ backgroundImage: `url(${imageUrl})` }}></div>
    );
}

Here, the component accepts an imageUrl prop and sets it as the background for the div.

Integrating the Component

You can then include the BackgroundImage in any parent component, such as:

function ParentComponent() {
    const imagePath = "/path/to/image.jpg";
    return(
        <div className='parent-container'>
            <BackgroundImage imageUrl={imagePath} />
            {/* Other content */}
        </div>
    );
}

Syntax Breakdown

  1. imageUrl Prop: This prop passed to the BackgroundImage component is simply a string pointing to the image path or URL.

  2. Inline Styling: Using React’s inline styling, we set the backgroundImage CSS property to the provided imageUrl. It’s rendered as style={{ backgroundImage: url(${imageUrl}) }}.

  3. CSS for Positioning: For the background to cover the entire container without affecting the rest of the content, we use:

.parent-container {
    position: relative;
}

.background-image {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    background-size: cover;
    background-repeat: no-repeat;
    background-position: center;
    z-index: -1;
}

Examples

Using Local Images

If you have an image stored locally in your project:

const localImagePath = "/assets/images/background.jpg";
<BackgroundImage imageUrl={localImagePath} />

Using External Images

For images hosted externally:

const externalImagePath = "https://example.com/background.jpg";
<BackgroundImage imageUrl={externalImagePath} />

Best Practices

  1. Optimize Images: Ensure that the images used are optimized for the web to reduce loading times.
  2. Alternative Backgrounds: For crucial UI sections, consider providing a fallback background color in case the image doesn’t load.
  3. Modularity: If planning to add transitions or dynamic behavior, it’s advantageous to keep all associated logic within the BackgroundImage component.

Additional Resources

Conclusion

A dedicated BackgroundImage component in React provides a modular and clean approach to manage background images. By isolating background image logic, you simplify integration into various parts of your application and ensure maintainability. Happy coding!

Bonus Cool ideas

Once you have a dedicated BackgroundImage component, the possibilities are vast. Here are some cool things you can do with it:

  1. Dynamic Image Selection: Based on user actions or other events, dynamically change the background image. For example, you could change the background based on the time of day or user preferences.

  2. Interactive Transitions: Add CSS transitions or animations when the background changes. Fade-ins, fade-outs, or even more complex animations like a slide can be visually appealing.

  3. Randomized Backgrounds: Store an array of image URLs and select a random one each time the component mounts. This way, users get a fresh look every time they visit or refresh the page.

  4. Parallax Scrolling Effect: Create a parallax effect where the background moves at a slower rate than the foreground when users scroll. This can create a sense of depth and dynamism.

  5. Image Blur on Action: When users open a modal, menu, or any overlay on the page, you can apply a blur effect to the background, focusing attention on the active element.

  6. Responsive Backgrounds: Use different images or styles based on screen size to ensure that the background looks great on all devices.

  7. Interactive Background Effects: Integrate JavaScript libraries like particles.js or three.js to create interactive or 3D animated backgrounds.

  8. Gradient Overlays: Add a gradient overlay over the image to ensure that text or other elements remain visible and legible. This can be a static gradient or even a dynamic one based on user interaction.

  9. Background Slideshow: Cycle through multiple background images, creating a slideshow effect. This can be automatic, based on a timer, or user-controlled.

  10. User-customizable Backgrounds: Allow users to upload or select their preferred background from a gallery.

  11. Temperature-based Backgrounds: Integrate with a weather API and change the background based on the current weather or temperature of a user’s location.

  12. Dark Mode Switch: Toggle between a light and dark background based on user preference for dark mode or light mode.

Remember, while these enhancements can provide a unique and engaging experience, it’s essential to ensure that they don’t detract from the overall user experience or make the website less accessible. Always prioritize usability and clarity, and consider running user tests when introducing significant UI changes.

Examples

Let’s delve into code examples for three of the cool features mentioned:

1. Dynamic Image Selection

Let’s change the background based on the time of day:

function BackgroundImage() {
    const [imageUrl, setImageUrl] = useState('');

    useEffect(() => {
        const hour = new Date().getHours();
        
        if (hour >= 6 && hour < 12) {
            setImageUrl("/path/to/morning.jpg");
        } else if (hour >= 12 && hour < 18) {
            setImageUrl("/path/to/afternoon.jpg");
        } else {
            setImageUrl("/path/to/evening.jpg");
        }
    }, []);

    return <div className="background-image" style={{ backgroundImage: `url(${imageUrl})` }}></div>;
}

2. Parallax Scrolling Effect

We can achieve a basic parallax effect using CSS and a bit of JavaScript:

JSX:

function BackgroundImage({ imageUrl }) {
    const [offsetY, setOffsetY] = useState(0);
    const handleScroll = () => setOffsetY(window.pageYOffset);

    useEffect(() => {
        window.addEventListener('scroll', handleScroll);

        return () => window.removeEventListener('scroll', handleScroll);
    }, []);

    return <div className="background-image" style={{ backgroundImage: `url(${imageUrl})`, transform: `translateY(${offsetY * 0.5}px)` }}></div>;
}

CSS:

.background-image {
    /* ...other styles... */
    will-change: transform;
}

3. Gradient Overlays

Provide an overlay to ensure text remains legible:

JSX:

function BackgroundImage({ imageUrl }) {
    return (
        <div className="background-image" style={{ backgroundImage: `linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)), url(${imageUrl})` }}></div>
    );
}

For the gradient overlay, the linear-gradient is used with two color stops, both black (rgba(0, 0, 0, 0.5)), giving a semi-transparent black overlay on top of the image. Adjust the alpha channel (the last value in the rgba function) to make the overlay more or less transparent.

Remember, these are just basic examples, and you might need to adjust or extend the code based on the exact requirements and the overall setup of your project.

Interactive

Here are three interactive background effects using different libraries and technologies:

1. Particles.js Background

particles.js allows for a dynamic particle system that can be interactive.

Installation:

npm install particles.js

JSX:

import React, { useEffect } from 'react';
import particlesJS from 'particles.js';

function ParticlesBackground() {
    useEffect(() => {
        particlesJS.load('particles-js', '/path/to/particles-config.json', function() {
            console.log('callback - particles.js config loaded');
        });
    }, []);

    return <div id="particles-js"></div>;
}

CSS:

#particles-js {
    position: absolute;
    width: 100%;
    height: 100%;
    z-index: -1;
}

You’ll also need a particles-config.json file to configure the particle system. You can generate one using the Particles.js Config Generator.

2. Mouse Move Ripple Effect

A ripple effect that responds to mouse movements can be achieved using vanilla JS:

JSX:

import React, { useRef } from 'react';

function RippleBackground() {
    const bgRef = useRef(null);

    const handleMouseMove = (event) => {
        const { clientX: x, clientY: y } = event;
        bgRef.current.style.setProperty('--x', `${x}px`);
        bgRef.current.style.setProperty('--y', `${y}px`);
    };

    return (
        <div ref={bgRef} className="ripple-background" onMouseMove={handleMouseMove}></div>
    );
}

CSS:

.ripple-background {
    position: relative;
    background: radial-gradient(circle at var(--x, 50%) var(--y, 50%), #ff7, transparent);
    width: 100%;
    height: 100%;
    z-index: -1;
}

3. three.js Animated 3D Background

three.js allows for 3D graphics in the browser using WebGL.

Installation:

npm install three

For a basic rotating cube:

JSX:

import React, { useRef, useEffect } from 'react';
import * as THREE from 'three';

function ThreeDBackground() {
    const ref = useRef();

    useEffect(() => {
        const scene = new THREE.Scene();
        const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
        const renderer = new THREE.WebGLRenderer();
        renderer.setSize(window.innerWidth, window.innerHeight);
        ref.current.appendChild(renderer.domElement);

        const geometry = new THREE.BoxGeometry();
        const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
        const cube = new THREE.Mesh(geometry, material);
        scene.add(cube);

        camera.position.z = 5;

        const animate = function () {
            requestAnimationFrame(animate);
            cube.rotation.x += 0.01;
            cube.rotation.y += 0.01;
            renderer.render(scene, camera);
        };
        
        animate();
    }, []);

    return <div ref={ref}></div>;
}

\

CSS:

/* To ensure that the 3D canvas takes the entire view and doesn't interfere with other UI elements. */
div {
    position: absolute;
    top: 0;
    left: 0;
    z-index: -1;
}

Enhancements and Considerations:

  1. Responsive Adjustments: You might want to add event listeners to handle window resizing to ensure the canvas always fits the viewport:
useEffect(() => {
    const handleResize = () => {
        renderer.setSize(window.innerWidth, window.innerHeight);
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
    };

    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
}, []);
  1. Performance Considerations: Using WebGL and 3D animations can be resource-intensive. You should ensure that such features don’t significantly slow down your website or negatively impact the user experience, especially on low-end devices or browsers that don’t fully support WebGL.

  2. Interaction: The real power of libraries like three.js comes from the interactive capabilities. Consider adding mouse listeners or touch events to allow users to interact with the 3D objects in the background.

  3. Assets and Complex Scenes: The given three.js example is pretty basic. For more complex scenes, you’d likely import 3D models, textures, and possibly use additional libraries to manage things like physics or more advanced animations.

  4. Fallback: Not all browsers or devices support WebGL or can handle intensive graphics operations. It’s a good idea to provide a fallback background or experience for such scenarios.

With any interactive background effect, it’s important to ensure that it enhances rather than detracts from the overall user experience. Background effects should remain in the background and not interfere with a user’s ability to engage with the primary content or functionality of your site. Always consider usability and accessibility when implementing visual and interactive features.

3 More

1. Moving Gradient Background with Mouse Movement

This effect will change the gradient’s direction based on the position of the mouse. It creates a dynamic feel as the user moves their cursor.

JSX:

import React from 'react';

function GradientBackground() {
    const handleMouseMove = (event) => {
        const x = (event.clientX / window.innerWidth) * 100;
        const y = (event.clientY / window.innerHeight) * 100;
        event.currentTarget.style.background = `radial-gradient(at ${x}% ${y}%, #FFB6C1, #FF69B4)`;
    };

    return <div className="gradient-background" onMouseMove={handleMouseMove}></div>;
}

CSS:

.gradient-background {
    position: absolute;
    width: 100%;
    height: 100%;
    z-index: -1;
    transition: background 0.2s;
}

2. Liquid Distortion Effect

This involves a more complex library. Liquid distortion effects create a dynamic, interactive ripple effect on images or backgrounds.

You’ll need three.js and the react-three-fiber for better integration with React.

Installation:

npm install three react-three-fiber

For this example, consider visiting this GitHub repo by Robin Delaporte, which uses Three.js to produce a liquid distortion effect. Integrate it with React for interactive backgrounds.

3. Floating Bubbles with CSS

Floating bubbles move based on the mouse’s position, giving a sense of depth.

JSX:

import React, { useRef } from 'react';

function BubbleBackground() {
    const bgRef = useRef(null);

    const handleMouseMove = (event) => {
        const { clientX: x, clientY: y } = event;
        const bubbles = bgRef.current.querySelectorAll('.bubble');
        
        bubbles.forEach(bubble => {
            const speed = bubble.getAttribute('data-speed');
            const dx = (window.innerWidth / 2 - x) * speed / 100;
            const dy = (window.innerHeight / 2 - y) * speed / 100;
            bubble.style.transform = `translate(${dx}px, ${dy}px)`;
        });
    };

    return (
        <div ref={bgRef} className="bubble-background" onMouseMove={handleMouseMove}>
            <div className="bubble" data-speed="2"></div>
            <div className="bubble" data-speed="4"></div>
            <div className="bubble" data-speed="6"></div>
            {/* Add as many bubbles as you like */}
        </div>
    );
}

CSS:

.bubble-background {
    position: relative;
    width: 100%;
    height: 100%;
}

.bubble {
    position: absolute;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.3);
    pointer-events: none;
}

.bubble:nth-child(1) {
    top: 20%;
    left: 10%;
    width: 100px;
    height: 100px;
}

.bubble:nth-child(2) {
    top: 40%;
    left: 50%;
    width: 150px;
    height: 150px;
}

.bubble:nth-child(3) {
    top: 70%;
    left: 30%;
    width: 200px;
    height: 200px;
}

/* Continue with different sizes and positions for each bubble */

The concept here is that each bubble will move at a different speed, creating a parallax effect. The larger the speed value, the further the bubble will move in response to the mouse.

These effects add interactive elements that can enrich the user experience but should be used judiciously so as not to distract from the primary content.

Keep your curiosity going.Explore more React →
287 TUTORIALS · 22 TOPICSREADY