Search code examples
htmlcssflexboxcss-positioncss-grid

Put text over image without 'position: absolute;' and wrap it to fit compartment in CSS grid


.grid-container {
  display: grid;
  grid-template-columns: repeat( auto-fit, minmax(18vw, 1fr) );
  grid-auto-rows: minmax(35vh, 1fr);
  gap: 20px 20px;
}

.box {
  display: flex;
  justify-content: center;
  align-items: center;
  opacity:0.85;
  background: green;
  color: #efefef;
  font-size:2em;
  border-radius:10px;
  transition: all 0.3s linear;
}

.box img {
  display: block;
  margin-left: auto;
  margin-right: auto;
  width: 50%;
  opacity: 0.6;
  filter: brightness(0) invert(1);
}

.box p  {
  position: absolute;
  font-size: calc(0.9em + 0.9vw);
  font-weight: bold;
}
<div class="grid-container">
  <a href='link' class="box">
    <img src="src/img.png"/>
    <p>TEXT</p>
  </a>
  <a href='link2' class="box">
    <img src="src/img2.png"/>
    <p>ANOTHER TEXT</p>
  </a>
  ...
</div>

Everything works fine, the image is centered horizontally and vertically in its 'box' and the text is also centered (v&h) and over the image. Everything is responsive to window size so the wider the more boxes per column and the text gets bigger.

The only problem is that the text does not break into lines and overflows its box with some windows sizes. Is there a way of making the text in the <p> element to break in lines according to the size of the box?

I have multiple variations like using word-wrap (overflow-wrap), putting the <img> and the <p> inside another <div> and ... but nothing seems to work.

========================

Edit based on comments.

The position: absolute; of the .box p elements is moving its content out of the flow. Maybe a better option would be to get the effect of text over image by another method. Any idea about how to do it?

Edited title to describe better the question after comments


Solution

  • When working with position: absolute , use position: relative; on the parent container to make the child element use the parent as it's positional reference (position: relative and position: absolute summary here). Also, added .box p { text-align: center }

    .grid-container {
      display: grid;
      grid-template-columns: repeat( auto-fit, minmax(18vw, 1fr) );
      grid-auto-rows: minmax(35vh, 1fr);
      gap: 20px 20px;
    }
    
    .box {
      position: relative;
      display: flex;
      justify-content: center;
      align-items: center;
      opacity:0.85;
      background: green;
      color: #efefef;
      font-size:2em;
      border-radius:10px;
      transition: all 0.3s linear;
    }
    
    .box img {
      display: block;
      margin-left: auto;
      margin-right: auto;
      width: 50%;
      opacity: 0.6;
      filter: brightness(0) invert(1);
    }
    
    .box p  {
      position: absolute;
      font-size: calc(12px);
      font-weight: bold;
      text-align: center;
    }
    <div class="grid-container">
      <a href='link' class="box">
        <img src="src/img.png"/>
        <p>TEXT</p>
      </a>
      <a href='link2' class="box">
        <img src="src/img2.png"/>
        <p>ANOTHER TEXT that is much longer to show that you can center the text.</p>
      </a>
      ...
    </div>