Search code examples
htmlcssflexbox

Apply image overlay when hovering exactly within the image


I have two flexbox columns. The left column contains text; the right column contains a picture. The columns should take up 60% and 40% of the width of the page, respectively. The text is longer than the picture is tall. I'd like a semi-transparent overlay on the picture; when I hover on the overlay, I'd like the overlay to disappear.

However, I can't get the overlay to show up, and I can't seem to restrict the hover area to just the size of the picture -- anywhere in the right column, even below the picture, triggers the hover effect.

Because I want the page to be responsive, I don't want to manually set the picture's size (or aspect-ratio): it should fill the width of the right column, and the right column should fill 40% of the page's width -- no px here, please.

Here's a quick mockup of what I'm trying to do. In this example, the yellow #img-container expands below the bottom of the image, and the green .overlay doesn't show up. Both should be exactly the size of the image.

Fiddle here.

Am I going about this the right way? Is there something obvious I'm missing? I'm pretty new to web design... thanks for the help!


Solution

  • To be able to put an overlay over a specific element:

    • you will need the element you are overlaying (your #container-img) to be position: relative.
    • The overlay itself must be positioned 'relative' to that element with position: absolute.
    • Depending on your requirements the overlay is positioned inside the element by assigning values to top, right, bottom and/or left or, as I used in the snippet, define their shorthand inset property. As you want to overlay the image, inset: 0 will stretch the overlay to all sides of its parent #container-img.
    • All that is left to do is define CSS for when #container-img is hovered.

    I commented my changes and additions in the snippet:

    #container {
      display: flex;
      gap: 50px;
    }
    
    #container-text {
      flex: 3;
    }
    
    #container-img {
      flex: 2;
      background-color: yellow;
      align-self: flex-start;
    }
    
    /*************************/
    /* Changes and additions */
    /*************************/
    /* Changed */
    #container-img img {
      display: block; /* removes small whiete space below image */
      /* disable this property to see the difference! */
    
      width: 100%;
      opacity: 20%;
    }
    
    #container-img .overlay {
        content: "";
        position: absolute;
        inset: 0; /* shorthand for T/R/B/L properties */
        background: rgb(0,255,0,.2); /* a semi transparent color */
    }
    
    /* ADDED */
    #container-img {
      position: relative; /* new stacking context to position overlay */
    }
    #container-img:hover .overlay {
      display: none; /* hide the overlay on hover */
    }
    <div id="container">
    
      <div id="container-text">
        <p>teeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeext</p>
        <p>text</p>
        <p>text</p>
        <p>text</p>
        <p>text</p>
        <p>text</p>
        <p>text</p>
        <p>text</p>
        <p>text</p>
        <p>text</p>
        <p>text</p>
        <p>text</p>
      </div>
    
      <div id="container-img">
        <img src="https://play-lh.googleusercontent.com/IeNJWoKYx1waOhfWF6TiuSiWBLfqLb18lmZYXSgsH1fvb8v1IYiZr5aYWe0Gxu-pVZX3" alt="profile picture">
        <div class="overlay"></div>
      </div>
    
    </div>