creating overlapping user icons

Viewed 343

I'm trying to create a a component that overlaps over the user icons just as shown in the photo. I've seen this being used on google. If I have a list of user icons, how do I overlap them over each other?

I want something like this enter image description here.

<template>
    <div >
    <ul>
      <li v-for="user in userList" :key="user.key">
        <user-icon-component :name="user.name" :image="user.picture"></user-icon-component>
      </li>
    </ul>
    </div>
</template>


<script>
export default {
  name: "UserList",
  props: {
    userList: {
      type: Object,
      default: null,
    },
  },
};
</script>

<style>

</style>
2 Answers

I liked the idea in your question and took it as a challenge for myself and here is the result:

vue overlapping avatars component

basically the approach I took was to use the component's props as style in style binding. there are some scoped style as well but I think they can be set in the style binding as well if needs be (probably the code could be cleaner).

user prop is an array of objects that contains this property: img: 'imageURL' and using a v-for on a div element with:

:style="{ backgroundImage: `url(${user.img})`}"

we can set the images.

as for the overlapping part, divs have position: relative and using the index of v-for, the style binding becomes like this:

:style="{backgroundImage: `url(${user.img})`, left: `-${i*15}px`}"

which shifts every element to the left by 15px except for the first one.

here is the image of the final result:

enter image description here

Thanks for your question, it was fun :)

The icon component is just an <img> tag with a user prop:

Vue.component('user-icon-component', {
  props: ['user'],
  template: `
  <img :src="user.picture" width="32" height="32" />
  `
})

Give the <li>s position: absolute and the <ul> position: relative to pull them out of the normal document flow. Set the left position on each <li> as a calculation from the index of the loop:

<ul class="icon-container">
  <li v-for="(user, key, i) in userList" :key="user.key"
      class="icon" :style="{ left: `${i * 20}px` }">
    <user-icon-component :user="user"></user-icon-component>
  </li>
</ul>

Here's a demo:

Vue.component('user-icon-component', {
    props: ['user'],
  template: `
  <img :src="user.picture" width="32" height="32" />
  `
})

/***** APP *****/
new Vue({
  el: "#app",
  data() {
    return {
        userList: {
        'Bob': { name: 'Bob', key: 1, picture: 'https://www.flaticon.com/svg/static/icons/svg/3084/3084430.svg' },
        'Mary': { name: 'Mary', key: 2, picture: 'https://www.flaticon.com/svg/static/icons/svg/3084/3084431.svg' },
        'Paul': { name: 'Paul', key: 3, picture: 'https://www.flaticon.com/svg/static/icons/svg/3084/3084452.svg' },
      }
    }
  },
});
.icon-container {
  position: relative;
}
.icon {
  position: absolute;
}
ul {
  list-style-type: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <ul class="icon-container">
    <li v-for="(user, key, i) in userList" :key="user.key"
        class="icon" :style="{ left: `${i * 20}px` }">
      <user-icon-component :user="user"></user-icon-component>
    </li>
  </ul>
</div>

Related