Issue with absolute items being sent to top of page

I am currently working on my portfolio page.

At the top of my page I have some font awesome Icons for links (HTML 28):

The issue is that they are not clickable. This is because on HTML line 208 I have my project cards. These project cards are images with a element overlay. When the user hovers over the image, the overlay appears.

This is done on CSS line 388 by changing the opacity from 0 to 0.8 when hovered:

.project-desc {
  position: absolute;
  top: 0;
  left: 0;
  
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  
  opacity: 0;
  background-color: black;
  font-size: 20px;
  padding: 5%;
  width: 100%;
  height: 100%;
  color: white;
  transition: 0.5s ease-in-out;
}

.project-card:hover .project-desc {
  opacity: 0.8;
  cursor: pointer;
  z-index: 2;
}

If you remove the initial opacity of 0 however, you notice the descriptions are stored at the top of the page due to the position property.

This prevents the user from hovering over the links and clicking them.

To fix this, I modified the CSS to have no display until the user hovers:

.project-desc {
  display: none; 
  background-color: black;
  font-size: 20px;
  padding: 5%;
  width: 100%;
  height: 100%;
  color: white;
  transition: 0.5s ease-in-out;
}

.project-card:hover .project-desc {
  position: absolute;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  top: 0;
  left: 0;
  opacity: 0.8;
  cursor: pointer;
  z-index: 2;
}

If we remove the display the overlay is now stored just beneath the card:

The issue now is that changing the display from none to flex on hover is not a linear transition. It instantly changed from 0 opacity to 0.8, ignoring my hover animation duration.

How can I fix this issue? Can I still keep the desc just below the card before hover and create a smooth transition?

If I understand you correctly it sounds like the overlay should just be positioned relative to their parent container element (i.e. set .project-card to have position: relative ).

Example
.project-card {
  width: 100%;
  max-width: 500px;
  height: auto;
  aspect-ratio: 16/9;
  background-color: white;
  box-shadow: 2px 2px 5px black;
  border: 1px solid black;
  transition: 0.3s ease-in-out;
  position: relative;
}

.project-desc {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  position: absolute;
  top: 0;
  left: 0;
  opacity: 0;
  background-color: black;
  font-size: 20px;
  padding: 5%;
  width: 100%;
  height: 100%;
  color: white;
  transition: 0.5s ease-in-out;
}

.project-card:hover .project-desc {
  opacity: 0.8;
  cursor: pointer;
  z-index: 2;
}
1 Like

As lasjorg said, you need a relative position on the parent. Check this guide from MDN Positioning - Learn web development | MDN
It helped me a lot to understand positioning.

Also I made a similar behaviour recently if you want to check: https://codepen.io/3dm777/full/zYzKQPZ

1 Like

Static positioning is the default that every element gets. It just means “put the element into its normal position in the document flow — nothing special to see here.”

  • Linked MDN article

So defining the project-card as a relative container takes it out of the normal flow but still keeps its position. This turns the project card into the new containing block, instead of the html as the initial containing block. Since is relative, its out of the normal flow but still keeps its same position.

A absolute value on the overlay sends the overlay to the top of the containing block, out of normal document flow. The html was the initial containing block, but this was replaced with the project card container. As a result, the overlay then goes to the top of the project card container. This overlaps it within the normal flow image, creating a image overlay.

Is this correct?