Skip to content

Avatar Directive

The v-avatar directive is used to display an avatar image, It will use the alt attribute as the fallback text if the image fails to load. You can pass custom classes to apply styles of your choice.

Usage

ADFMJLGM
View Code
vue
<script setup>
const images = [
  {
    src: "https://images.pexels.com/photos/1123757/pexels-photo-1123757.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
    alt: "AD",
  },
  {
    src: "failed",
    alt: "FM",
    className: "bg-zinc-100 dark:bg-zinc-800 text-zinc-800 dark:text-zinc-100 font-medium text-2xl rounded-full",
  },
  {
    src: "https://images.pexels.com/photos/1081685/pexels-photo-1081685.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
    alt: "JL",
  },
  {
    src: "Failed",
    alt: "GM",
    className: "bg-green-100 dark:bg-green-800 text-green-800 dark:text-green-100 font-medium text-2xl",
  },
];
</script>
<template>
  <div class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-4">
    <img
      v-for="(image, index) in images"
      :key="index"
      v-avatar:[image.className]
      :src="image.src"
      :alt="image.alt"
      :class="image.className"
      class="w-32 h-32 rounded-2xl"
    />
  </div>
</template>
<style scoped></style>

Arguments

The v-avatar does not take any arguments.

Modifiers

The v-avatar does not take any modifiers.

Source Code

js
export const VAvatar = {
  mounted(el, binding) {
    el.addEventListener("error", () => {
      const img = el;

      // Get width and height from inline styles
      let width = img.style.width;
      let height = img.style.height;
      let borderRadius = img.style.borderRadius; 

      // If not set via inline styles, try to get from computed styles
      if (!width || !height || !borderRadius || !backgroundColor) {
        const computedStyle = window.getComputedStyle(img);
        width = computedStyle.getPropertyValue("width");
        height = computedStyle.getPropertyValue("height");
        borderRadius = computedStyle.getPropertyValue("border-radius"); 
      }

      // If still not available, use naturalWidth and naturalHeight properties
      if (!width || !height) {
        const naturalWidth = img.naturalWidth;
        const naturalHeight = img.naturalHeight;
        width = naturalWidth ? `${naturalWidth}px` : null;
        height = naturalHeight ? `${naturalHeight}px` : null;
      }

      // Convert width and height to numbers
      const parsedWidth = parseFloat(width);
      const parsedHeight = parseFloat(height);

      // Convert border-radius to a number or percentage to pixels
      let parsedRadius;
      if (borderRadius.includes("%")) {
        console.log("borderRadius:", borderRadius);
        parsedRadius =
          (parseFloat(borderRadius) / 100) *
          Math.min(parsedWidth, parsedHeight);
      } else {
        parsedRadius = parseFloat(borderRadius);
      }

      // Check if parsing was successful and the values are valid
      if (
        !isNaN(parsedWidth) &&
        !isNaN(parsedHeight) &&
        parsedWidth > 0 &&
        parsedHeight > 0 &&
        !isNaN(parsedRadius)
      ) {
        // Create a div element to replace the img element
        const div = document.createElement("div");
        div.style.width = width;
        div.style.height = height;
        div.style.borderRadius = borderRadius; 
        div.style.display = "flex";
        div.style.justifyContent = "center";
        div.style.alignItems = "center";
        if (binding.arg) {
          let classes = binding.arg.split(" ");
          for (let i = 0; i < classes.length; i++) {
            div.classList.add(classes[i]);
          }
        }

        // Create text element
        const text = document.createElement("span");
        text.textContent = img.alt || "Avatar";
        text.style.width = "100%";
        text.style.height = "100%";
        text.style.display = "flex";
        text.style.justifyContent = "center";
        text.style.alignItems = "center";
        text.style.overflow = "hidden";
        text.style.userSelect = "none";

        // Append text to div
        div.appendChild(text);

        // Replace img with div
        img.parentNode.replaceChild(div, img);

        // Remove event listener
        el.removeEventListener("error", () => {});
      } else {
        console.log("Invalid width, height, or radius");
      }
    });
  },
  updated(el, binding) {
    //    watch for color changes
    console.log("updated", binding.value);
  },
};