DEV Community

Cover image for How to Implement Name-Based Avatar Component in Vue
Taha Shashtari
Taha Shashtari

Posted on • Originally published at tahazsh.com

3 1

How to Implement Name-Based Avatar Component in Vue

One common way to display avatars for users without an image is showing the first letter on a colored circle.

We need to consider the following when creating such a component:

  • It should display the image if provided.
  • It should show the same background color for the same user name.
  • The font size of the letter should be responsive based on the container size.

The code

I named the component in this example Avatar.vue. So, here's how the usage code would be:

<!-- This will show the image version -->
<Avatar name="Test User" image="/image.png" />

<!-- This will show the first letter version -->
<Avatar name="Test User" />
Enter fullscreen mode Exit fullscreen mode

In the code below, I'm using v-bind() in the css, which is a Vue 3 feature that allows us to bind variables to the css. If you are using Vue 2, make sure to use style binding instead. Like <div :style="{ backgroundColor: bgColor }></div>.

Here's the code for Avatar.vue:

<template>
  <div ref="containerRef" class="avatar">
    <img v-if="image" :src="image" class="image" :alt="name" />
    <span v-else-if="name" class="initials">
      {{ name[0] }}
    </span>
  </div>
</template>

<script setup>
import { ref, computed, onMounted } from 'vue'

const props = defineProps({
  image: {
    type: String,
    default: ''
  },

  name: {
    type: String,
    default: ''
  }
})

const containerRef = ref()
const fontSize = ref('1rem')

onMounted(() => {
  // The font size should be 50% of the container width
  fontSize.value = `${containerRef.value.clientWidth * 0.5}px`
})

const bgColor = computed(() => {
  // Don't show a color if the image is provided
  if (props.image) {
    return 'transparent'
  }
  // Calculate the hue value based on the name
  const hue =
    props.name.split('').reduce((acc, cur) => {
      return acc + cur.charCodeAt(0)
    }, 0) % 360
  return `hsla(${hue}, 60%, 50%, 1)`
})
</script>

<style scoped>
.avatar {
  width: 100%;
  aspect-ratio: 1;
  border-radius: 50%;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  /* bind the background color to bgColor */
  background: v-bind(bgColor);
}

.image {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.initials {
  /* bind the font-size to fontSize */
  font-size: v-bind(fontSize);
  color: white;
  font-family: sans-serif;
  user-select: none;
}
</style>
Enter fullscreen mode Exit fullscreen mode

If you pass a specific name to this component, you will always get the same background color for it. It works like this because, in bgColor computed property, I'm calculating the color based on the sum of the char code of each letter in the name.

I'm using hsla for the color to be able to control the color value apart from the other components, which are saturation and lightness.

For this example, I set the font size to the half of the container's width. So if you want to make it smaller or bigger, just change 0.5 in fontSize.value = ${containerRef.value.clientWidth * 0.5}px.


If you liked this article, check out my blog for more articles like this.
I also share coding tips and my latest work on Twitter. Let's be friends!

Hostinger image

Get n8n VPS hosting 3x cheaper than a cloud solution

Get fast, easy, secure n8n VPS hosting from $4.99/mo at Hostinger. Automate any workflow using a pre-installed n8n application and no-code customization.

Start now

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more