How to apply description over image using CSS Grid?

I am trying to create a grid of images that display descriptions over a faded version of an image when the user hovers over a specified image. My current progress can be seen below and on this JSFiddle .

div#grid-container {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-gap: 25px;
  width: 95%;
  margin: 15px auto;
  
  div {
    margin: auto;
    overflow: hidden;
    // cursor: pointer;
    background-color: black;
    color: white;
    
    img {
      height: auto;
      max-width: 100%;
    }
    
    p {
      display: none;
      position: relative;
      padding: 0;
      top: -40px;
      left: 10px;
      margin: 0;
    }
    
    &:hover {
      
      img {
        opacity: 0.35;
      }
      
      p {
        display: block;
      }
    }
  }
}
      

<h2>Grid Test</h2>
<div id="grid-container">
  <div class="">
    <img src="http://i.imgur.com/kEmy7gp.jpg" alt="A Rock" />
    <p>A beautiful rock structure.</p>
  </div>
  <div class="">
    <img src="http://i.imgur.com/kEmy7gp.jpg" alt="A Rock" />
    <p>A beautiful rock structure.</p>
  </div>
  <div class="">
    <img src="http://i.imgur.com/kEmy7gp.jpg" alt="A Rock" />
    <p>A beautiful rock structure.</p>
  </div>
  <div class="">
    <img src="http://i.imgur.com/kEmy7gp.jpg" alt="A Rock" />
    <p>A beautiful rock structure.</p>
  </div>
  <div class="">
    <img src="http://i.imgur.com/kEmy7gp.jpg" alt="A Rock" />
    <p>A beautiful rock structure.</p>
  </div>
  <div class="">
    <img src="http://i.imgur.com/kEmy7gp.jpg" alt="A Rock" />
    <p>A beautiful rock structure.</p>
  </div>
  <div class="">
    <img src="http://i.imgur.com/kEmy7gp.jpg" alt="A Rock" />
    <p>A beautiful rock structure.</p>
  </div>
  <div class="">
    <img src="http://i.imgur.com/kEmy7gp.jpg" alt="A Rock" />
    <p>A beautiful rock structure.</p>
  </div>
</div>
      

Run codeHide result


As you can see in my JSFiddle example, what I am currently doing has these nasty black bars as well as a resizing issue due to relative placement. I can get rid of the relative black bar with margin-bottom

, but it still doesn't fix my unnecessary resizing problem.

Ideally, I would like to have a kiss div

over the image so that I can position things inside that div, but I have no idea how I can get around this without a complete mess. I would like some help on how I can logically do this with the following constraints:

  • I would rather not use JavaScript, but I am not 100% against it. But of course there is no framework.
  • I don't want to make pictures of background-image

    my div

    s.
  • Images must be changed. (although it might be worth noting that the initial size of the images is known)
+3


source to share


3 answers


There are two reasons for the problem.

Problem # 1: position: relative

The paragraph element is relatively positioned above the image.

div#grid-container div p {
    display: none;
    position: relative;
    padding: 0;
    top: -40px;
    left: 10px;
    margin: 0;
}

      

The problem is that relative positioning does not remove the element from the normal flow. So even if you use top

and left

to place the text, the original space for the element remains in place ( full explanation ).

You need to remove the item from the normal flow so that it doesn't take up space in the container. Use position: absolute

and create a parent bounding rectangle with position: relative

.

div {
    margin: auto;
    overflow: hidden;
    background-color: black;
    color: white;
    position: relative;  /* new */

p {
    display: none;
    position: absolute; /* adjusted */
    padding: 0;
    bottom: 40px;       /* adjusted */
    left: 10px;
    margin: 0;
}

      

modified demo 1




Problem # 2: vertical-align: baseline

Image elements are elements of grid elements. This means that they do not participate in the layout of the grid. They exist in a block layout where line-level elements are automatically assigned a baseline alignment with the vertical-align

( source ) property .

This is why there is a small gap under the images ( full explanation ).

To fix the problem, override the default with vertical-align: top

.

img {
  height: auto;
  max-width: 100%;
  vertical-align: top;  /* new */
}

      

revised demo 2

+2


source


What you can do is use the :after

on property div

to place a semi-transparent dark background over the image and take advantage of the use position: absolute;

of the paragraph element. See below and this updated demo on the JSFiddle. Read more :after

on MDN .



div {
    margin: auto;
    overflow: hidden;
    // cursor: pointer;
    color: white;
    position: relative;

    img {
      display: block;
      height: auto;
      max-width: 100%;
    }

    &:hover:after {
      position: absolute;
      display: block;
      content: '';
      top: 0;
      left: 0;
      bottom: 0;
      right: 0;
      background-color: rgba(0,0,0,.25);
    }

    p {
      display: none;
      position: absolute;
      padding: 0;
      bottom: 10px;
      left: 10px;
      margin: 0;
      z-index: 1;
    }

      

+1


source


You have to remove the background color in the div and place it at p, and set the display to a block at p with opacity 0, hover over the opacity to 0.65 and add padding to the left p and reduce the top border of the box:

    div#grid-container {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-gap: 25px;
  width: 95%;
  margin: 15px auto;

  div {
    margin: auto;
    overflow: hidden;
    // cursor: pointer;

    color: white;

    img {
      height: auto;
      max-width: 100%;
    }

    p {
      opacity: 0;
      position: relative;
      padding: 0;
      top: -20px;
      left: 0px;
      margin: 0;
      padding-left: 10px;
      background-color: black;
    }

    &:hover {

      img {
        opacity: 0.35;
      }

      p {
        opacity: 0.65;
      }
    }
  }
}

      

You can even play with the opacity of the image, I would put at least 0.75

0


source







All Articles