Search code examples
cssstyled-components

Put a pseudo element over other pseudo element (css best practices)


I downloaded this design from frontend mentor to practice my css skills

enter image description here

this is the hover state of the design

enter image description here

this is my design

enter image description here

I got this result with the next css rules:

const CardImage = styled.div`
  background-image: url(${(props) => props.cardImage || DefaultImage});
  background-repeat: no-repeat;
  background-size: cover;
  border-radius: 15px;
  height: 270px;
  margin-bottom: 25px;
  width: 270px;
  &:hover:after {
    content: url(${ViewIcon});
    position: absolute;
    left: calc(50% - 24px);
    top: calc(50% - 135px);
  }
  &:hover:before {
    position: relative;
    content:'';
    display: block;
    height: 100%;
    width: 100%;
    background-color: rgba(1,153,174,0.5);
  }
`;

I'm new in css and I'm not sure if this is the best way to do this is there other best way to do this?

the only way to do this is using pseudo elements?


Solution

  • Unless you need more than 2 elements or need to move them around using JS, there's nothing wrong with using ::before and ::after for that effect.
    You can always create an empty div, make it absolute and create a similar effect. (In this case, the results would be the same)

    Unrelated to the question, but here are a few changes to make it more readable (personal preference) and to have a smoother animation.

    const CardImage = styled.div`
      background-image: url(${(props) => props.cardImage || DefaultImage});
      background-repeat: no-repeat;
      background-size: cover;
      border-radius: 15px;
      height: 270px;
      margin-bottom: 25px;
      width: 270px;
    
      &::before {
        position: relative;
        content:'';
        display: block;
        height: 100%;
        width: 100%;
        background-color: rgba(1,153,174,0.5);
        opacity: 0;
        transition: opacity .3s;
        will-change: opacity;
      }
    
      &::after {
        content: url(${ViewIcon});
        position: absolute;
        left: calc(50% - 24px);
        top: calc(50% - 135px);
        opacity: 0;
        transition: opacity .3s;
        will-change: opacity;
      }
    
      &:hover {
       &::before,
       &::after {
         opacity: 1;
       }
      }
    `;