Skip to main content

Reusable ImageOnClick Component

· 4 min read
Docux
Curious explorer, a bit of a mad experimenter, and a bit of a contributor.
📚This article is part of the series:Design your site

Developer Developer License: MIT

An amazing component to display your images on click! Lighten up your documentation presentations or blog articles - it's easy to implement and creates a clean, professional look.

Publication

This article was originally published by DocuxLab on the Docusaurus Community and is republished here but here is an improved version.

The code for the component used for this functionality should be placed in \src\components\ImageOnClick\index.js.

src\components\ImageOnClick\index.js
import React, { useState } from 'react'; // Import React and useState hook
import clsx from 'clsx'; // Import clsx library for conditional classes
import useBaseUrl from '@docusaurus/useBaseUrl'; // Import the useBaseUrl function from Docusaurus
import styles from './styles.module.css'; // Import styles from CSS module

// Define the ImageOnClick component as a functional component
const ImageOnClick = ({ imageUrl, altText, buttonName }) => {
const [showImg, setShowImg] = useState(false); // State to track whether image should be shown or hidden

const generatedImageUrl = useBaseUrl(imageUrl); // Use the useBaseUrl function to generate the image URL

return (
<span>
{/* Button to toggle visibility of the image */}
<a onClick={() => setShowImg(!showImg)} className={styles.cursor}>
{buttonName}
</a>
{/* Conditionally render the image if showImg is true */}
{showImg && (
<div className={styles.imageonclick} onClick={() => setShowImg(false)}>
{/* Close button */}
<button
className={styles.closeButton}
onClick={(e) => {
e.stopPropagation();
setShowImg(false);
}}
aria-label="Close image"
>

</button>
{/* Image element */}
<img
src={generatedImageUrl}
alt={altText}
onClick={(e) => e.stopPropagation()}
/>
</div>
)}
</span>
);
}

export default ImageOnClick; // Export the ImageOnClick component

CSS

To center the image and apply modern lightbox effects, we'll add some CSS:

src\components\ImageOnClick\styles.module.css
/* Modern lightbox overlay */
.imageonclick {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background: radial-gradient(circle, rgba(0, 0, 0, 0.4) 0%, rgba(0, 0, 0, 0.9) 100%);
display: flex;
justify-content: center;
align-items: center;
z-index: 9999;
backdrop-filter: blur(8px);
animation: lightboxFadeIn 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94);
cursor: pointer;
}

/* Image with elegant zoom effect */
.imageonclick img {
max-width: 90%;
max-height: 90%;
width: auto;
height: auto;
object-fit: contain;
border-radius: 16px;
box-shadow:
0 25px 80px rgba(0, 0, 0, 0.8),
0 0 0 1px rgba(255, 255, 255, 0.1);
animation: imageZoomIn 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
cursor: default;
transition: transform 0.3s ease;
}

.imageonclick img:hover {
transform: scale(1.02);
}

/* Modern close button */
.closeButton {
position: absolute;
top: 20px;
right: 20px;
color: white;
font-size: 24px;
font-weight: 400;
cursor: pointer;
z-index: 10001;
width: 48px;
height: 48px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 24px;
background: linear-gradient(135deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.05));
border: 1px solid rgba(255, 255, 255, 0.2);
backdrop-filter: blur(10px);
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
animation: buttonSlideIn 0.6s cubic-bezier(0.34, 1.56, 0.64, 1) 0.2s both;
}

.closeButton:hover {
background: linear-gradient(135deg, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0.1));
transform: scale(1.1) rotate(90deg);
border-color: rgba(255, 255, 255, 0.4);
}

.closeButton:active {
transform: scale(0.95) rotate(90deg);
}

/* Enhanced animations */
@keyframes lightboxFadeIn {
from {
opacity: 0;
backdrop-filter: blur(0px);
background: radial-gradient(circle, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0) 100%);
}
to {
opacity: 1;
backdrop-filter: blur(8px);
background: radial-gradient(circle, rgba(0, 0, 0, 0.4) 0%, rgba(0, 0, 0, 0.9) 100%);
}
}

@keyframes imageZoomIn {
from {
transform: scale(0.5) translateY(60px);
opacity: 0;
filter: blur(4px);
}
50% {
opacity: 0.8;
filter: blur(2px);
}
to {
transform: scale(1) translateY(0);
opacity: 1;
filter: blur(0px);
}
}

@keyframes buttonSlideIn {
from {
transform: translateY(-20px) scale(0.8);
opacity: 0;
}
to {
transform: translateY(0) scale(1);
opacity: 1;
}
}

/* Enhanced responsive design */
@media (max-width: 768px) {
.closeButton {
top: 15px;
right: 15px;
width: 44px;
height: 44px;
font-size: 20px;
}

.imageonclick img {
max-width: 95%;
max-height: 85%;
border-radius: 12px;
}
}

@media (max-width: 480px) {
.closeButton {
top: 10px;
right: 10px;
width: 40px;
height: 40px;
font-size: 18px;
}

.imageonclick img {
max-width: 98%;
max-height: 80%;
border-radius: 8px;
}
}

/* Exit animation (optional) */
.imageonclick.closing {
animation: lightboxFadeOut 0.3s ease-out forwards;
}

.imageonclick.closing img {
animation: imageZoomOut 0.3s ease-out forwards;
}

@keyframes lightboxFadeOut {
to {
opacity: 0;
backdrop-filter: blur(0px);
}
}

@keyframes imageZoomOut {
to {
transform: scale(0.8) translateY(20px);
opacity: 0;
}
}

Using the Component in an MDX File

Basic

<ImageOnClick imageUrl="/img/friends.jpg" altText="Dinosaur" buttonName="Click me" />
Click me

Emoji Button

<ImageOnClick imageUrl="/img/friends.jpg" altText="Dinosaur" buttonName="🔎" />

Using markdown emoji: 🔎