Search code examples
javascriptcssreactjssass

How to position badge icon independent the size of the avatar?


I need to build an avatar component which will have badgets. The problem is that the positioning is not correct according to the Avatar's size.

In the image below it is easier to understand what the problem is. Can you tell me how to adjust the positioning so that it is correct regardless of the size of the Avatar?

Here's my code I put into codesandbox

Thank you in advance.

enter image description here

import React from "react";
import BadgeSvg from "./BadgeSvg";
import "./avatar.scss";

const Avatar = ({ size }) => {
  const image = "https://i.imgur.com/pKHO357.png";

  return (
    <div>
      <div className={`content-icon ${size}`}>
        <img
          src={image}
          alt="Avatar Image"
          className={`content-icon ${size}`}
        />
      </div>
      <div className="badge">
        <BadgeSvg size={size} />
      </div>
    </div>
  );
};

export default Avatar;
.content-icon {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
  border-radius: 50%;
  background-color: #f2f2f2;
  object-fit: cover;
  color: #999999;

  &.xsmall {
    width: 16px;
    height: 16px;
  }

  &.small {
    width: 32px;
    height: 32px;
  }

  &.medium {
    width: 40px;
    height: 40px;
  }

  &.large {
    width: 72px;
    height: 72px;
  }

  &.xlarge {
    width: 96px;
    height: 96px;
  }
}

.badge {
  position: relative;
  top: -18px;
  right: -52px;
  display: flex;
  width: min-content;
}


Solution

  • Re-structuring jsx will solve your problem with css absolute and relative position. But for perfect positioning you need to calculate some css manually like bellow.

    Here is your Avatar component

    import React from "react";
    import BadgeSvg from "./BadgeSvg";
    import "./avatar.scss";
    
    const Avatar = ({ size }) => {
      const image = "https://i.imgur.com/pKHO357.png";
    
      const getRightValue = (aSize) => {
        if (aSize === "medium") {
          return { right: "-3px" };
        }
    
        if (aSize === "xlarge") {
          return { right: "5px" };
        }
    
        if (aSize === "large") {
          return { right: 0 };
        }
      };
    
      return (
        <div>
          <div className={`content-icon ${size}`}>
            <img
              src={image}
              alt="Avatar Image"
              className={`content-icon ${size}`}
            />
            <div className="badge" style={getRightValue(size)}>
              <BadgeSvg size={size} />
            </div>
          </div>
        </div>
      );
    };
    
    export default Avatar;
    

    And this is the final css

    .content-icon {
      position: relative;
      /* rest of css */
    }
    
    .badge {
      position: absolute;
      bottom: 0;
    }
    

    And this this is the final output, hope this will help.

    output of code