Search code examples
htmlcsssassz-indexoverlap

Overlapping/overlaying multiple inline images


I have a list of images I'm trying to overlap so that they look similar to this:

overlapped people

My code:

.avatar img {
    border-radius: 50%;
    position: relative;
    left: -5px;
    z-index: 1;
}
<div class="avatars">
    <span class="avatar">
        <img src="https://picsum.photos/70" width="25" height="25"/>
    </span>
    <span class="avatar">
        <img src="https://picsum.photos/50" width="25" height="25"/>
    </span>
    <span class="avatar">
        <img src="https://picsum.photos/20" width="25" height="25"/>
    </span>
    <span class="avatar">
        <img src="https://picsum.photos/100" width="25" height="25"/>
    </span>
    <!-- Variable amount more avatars -->
</div>
<p>4 People</p>

But obviously, I need an incrementing left value, and a decrementing z-index for the number of avatar imgs. Sure, I could do this with the @for directive, but the thing is, there's a variable amount of avatar imgs. I was looking at the length() function, but it doesn't work the way I was going to use it.

Another idea, is to have a set width div, and fit the images inside that, but that comes with its own issues (what if there are 5 images, or 20, how do control the width). I could also combine the images how I want them, elsewhere and not use any CSS.


Solution

  • You can use flex and reverse order then no need z-index:

    .avatars {
      display: inline-flex;
      flex-direction: row-reverse;
    }
    
    .avatar {
      position: relative;
      border: 4px solid #fff;
      border-radius: 50%;
      overflow: hidden;
      width: 100px;
    }
    
    .avatar:not(:last-child) {
      margin-left: -60px;
    }
    
    .avatar img {
      width: 100%;
      display: block;
    }
    <div class="avatars">
      <span class="avatar">
            <img  src="https://picsum.photos/70">
        </span>
      <span class="avatar">
            <img src="https://picsum.photos/80">
        </span>
      <span class="avatar">
            <img src="https://picsum.photos/90">
        </span>
      <span class="avatar">
           <img src="https://picsum.photos/100">
        </span>
    </div>

    Here is another idea with scale:

    .avatars {
      display: inline-block;
      transform: scale(-1, 1);
    }
    
    .avatar {
      position: relative;
      display: inline-block;
      border: 4px solid #fff;
      border-radius: 50%;
      overflow: hidden;
      width: 100px;
    }
    
    .avatar:not(:first-child) {
      margin-left: -60px;
    }
    
    .avatar img {
      width: 100%;
      display: block;
      transform: scale(-1, 1);
    }
    <div class="avatars">
      <span class="avatar">
            <img  src="https://picsum.photos/70">
        </span>
      <span class="avatar">
            <img src="https://picsum.photos/80">
        </span>
      <span class="avatar">
            <img src="https://picsum.photos/90">
        </span>
      <span class="avatar">
           <img src="https://picsum.photos/100">
        </span>
    </div>

    Another idea using mask in case you want to keep the order of your images. This will also give you transparency between the images:

    .avatar {
      display: inline-block;
      border-radius: 50%;
      overflow: hidden;
      width: 100px;
    }
    
    .avatar:not(:first-child) {
      margin-left: -60px;
      -webkit-mask:radial-gradient(circle 55px at 5px 50%,transparent 99%,#fff 100%);
              mask:radial-gradient(circle 55px at 5px 50%,transparent 99%,#fff 100%);
    }
    
    .avatar img {
      width: 100%;
      display: block;
    }
    
    body {
      background:pink
    }
    <div class="avatars">
      <span class="avatar">
            <img  src="https://picsum.photos/70">
        </span>
      <span class="avatar">
            <img src="https://picsum.photos/80">
        </span>
      <span class="avatar">
            <img src="https://picsum.photos/90">
        </span>
      <span class="avatar">
           <img src="https://picsum.photos/100">
        </span>
    </div>

    Another idea using a 3D tranformation trick (without transparency)

    .avatars {
      transform-style:preserve-3d; /* here */
    }
    
    .avatar {
      display: inline-block;
      border-radius: 50%;
      overflow: hidden;
      width: 100px;
    }
    
    .avatar:not(:first-child) {
      margin-left: -60px;
      transform:rotateY(-1deg); /* and here */
    }
    
    .avatar img {
      width: 100%;
      display: block;
    }
    <div class="avatars">
      <span class="avatar">
            <img  src="https://picsum.photos/70">
        </span>
      <span class="avatar">
            <img src="https://picsum.photos/80">
        </span>
      <span class="avatar">
            <img src="https://picsum.photos/90">
        </span>
      <span class="avatar">
           <img src="https://picsum.photos/100">
        </span>
    </div>