DEV Community

qian
qian

Posted on

Beautifying the HTMLImageElement not-loaded/errored status display, react component

background

  • Browser's native image not loaded status doesn't look good, I'd like not to use it.
  • I am using react.

ideas

  • Determine if the image is loaded successfully by onLoaded event.
  • If loaded successfully show the HTMLImageElement, if not show the custom error component while HTMLImageElement is hidden (visibility: hidden).

how it looks like

fail

Image description

fail with alt on it

Image description

success

Image description

tips

  • When load failed, the HTMLImageElement can't be set to display: none, the HTMLImageElement needs to be in the document tree. Also the HTMLImageElement should to be invisible and looks like not placed in the web page, so use the grid display to implement this.

  • every time the image is changed, will reload again, so need to set loaded status to false first.

reference



import { cn } from "@/lib/utils";
import { Image } from "lucide-react";
import { useEffect, useState } from "react";
interface ImageProps {
  src: string;
  iconSize?: number;
  className?: string;
  alt?: string;
  showAlt?: boolean;
}

const BeautyImage = ({
  src,
  iconSize = 16,
  className = "",
  alt = "",
  showAlt = false,
}: ImageProps) => {
  // load successfully or not
  const [imageLoaded, setImageLoaded] = useState(false);

  /**
   * onLoad event
   */
  const onImageLoad = () => {
    setImageLoaded(true);
  };

  /**
   * everytime the src changes, set load status to fail
   */
  useEffect(() => {
    setImageLoaded(false);
  }, [src]);

  return (
    <div
      className={cn(
        "flex flex-col justify-center items-center text-xs text-ttertiary",
        className
      )}
    >
      <div
        className={cn(
          "grid",
          imageLoaded
            ? "grid-rows-[1fr] opacity-100"
            : "grid-rows-[0fr] opacity-0"
        )}
      >
        <div className="overflow-hidden">
          <img className="rounded-full" src={src} onLoad={onImageLoad} />
        </div>
      </div>
      {/* custom error component */}
      {!imageLoaded && (
        <div className="flex flex-col items-center justify-center">
          <Image size={iconSize} />
          {showAlt && alt && <p>{alt}</p>}
        </div>
      )}
    </div>
  );
};
Enter fullscreen mode Exit fullscreen mode

Heroku

Simplify your DevOps and maximize your time.

Since 2007, Heroku has been the go-to platform for developers as it monitors uptime, performance, and infrastructure concerns, allowing you to focus on writing code.

Learn More

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay