skip to Main Content

I am trying to build out a banner element on a website, and am having an issue getting it to fulfil the criteria I am after. Ideally I would like to have a solution that is CSS only.

The layout is pretty simple – a background image, with centered text overlaid. Diagram below:

enter image description here

In order of priority, I need the element to do the following:

  1. The element must always be tall enough to accomodate the text within it. This comes from a CMS so could be of any length.
  2. As long as it does not break the first criteria, the element must not be taller than 80svh
  3. As long as it does not break the first and second criteria, the element must respect the aspect ratio of the background image. Again, this is from a CMS, so I have the image width and height available to me to use in any aspect-ratio CSS.

My first attempt looked like this:

div.wrapper {
  display: grid;
  grid-template-rows: repeat(1, minmax(0, 1fr));
  grid-template-columns: repeat(1, minmax(0, 1fr));
}

div.image-holder {
  width: 100%;
  min-height: 80svh;
  grid-row-start: 1;
  grid-column-start: 1;
  position: relative;
}

div.text-holder {
  padding: 2rem;
  display: flex;
  justify-content: center;
  align-items: center;
  grid-row-start: 1;
  grid-column-start: 1;
  position: relative;
  z-index: 30;
}

p {
  max-width: 760px;
  font-size: 1.8rem;
  line-height: 2.3rem;
  font-weight: 700;
  text-align: center;
  font-family: sans-serif;
}

img {
  object-fit: cover;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  width: 100%;
  height: 100%;
  display: block;
  opacity: 0.5;
}
<div class="wrapper">
  <div class="image-holder">
    <img
  src="https://placebear.com/1200/800" alt="Bears" />
  </div>
  <div class="text-holder">
    <p>Central text element, amount of text unknown. Solution must work for any amount of added text.</p>
  </div>
</div>

This fulfilled criteria 1, but as long as the element was large enough to accomodate the text the overall height was always set to 80svh, and didn’t do anything with the aspect ratio of the image.

Then I tried the following:

div.wrapper {
      display: grid;
      grid-template-rows: repeat(1, minmax(0, 1fr));
      grid-template-columns: repeat(1, minmax(0, 1fr));
    }

    div.image-holder {
      width: 100%;
      grid-row-start: 1;
      grid-column-start: 1;
      position: relative;
    }

    div.text-holder {
      padding: 2rem;
      display: flex;
      justify-content: center;
      align-items: center;
      grid-row-start: 1;
      grid-column-start: 1;
      position: relative;
      z-index: 30;
    }

    p {
      max-width: 760px;
      font-size: 1.8rem;
      line-height: 2.3rem;
      font-weight: 700;
      text-align: center;
      font-family: sans-serif;
    }

    img {
      object-fit: cover;
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      width: 100%;
      height: 100%;
      display: block;
      opacity: 0.5;
    }
<div class="wrapper">
      <div class="image-holder">
        <img
      src="https://placebear.com/1200/800" alt="Bears" />
      </div>
      <div class="text-holder" style="aspect-ratio: 1200 / 800; // This is inlined as it is pulled from the image size from the CMS">
        <p>Central text element, amount of text unknown. Solution must work for any amount of added text.</p>
      </div>
    </div>

This was closer, and fulfilled criteria 1 and 3, but now I didn’t have the max height of the element set to 80svh. So the element would carry on scaling at the aspect ratio to any height.

I am stuck as to what to try next. I am hoping this isn’t an unusual layout aim, and that someone has managed this before. If I need to lean on javascript for this I will, but I am hoping to get it done with CSS if possible.

3

Answers


  1. In your case, you need to add some tricks. For example, another image that will have position: absolute; relative to .wrapper in case the height of .image-holder is too small.
    For example, something like this:

    body{
      min-width: 320px;
      margin: 0;
    }
    
    .wrapper {
      display: grid;
      grid-template-areas: 'a';
      position: relative;
      --max-img-height: 80svh;
    }
    
    .image-holder {
      grid-area: a;
      height: fit-content(var(--max-img-height));
      display: grid;
      opacity: 0.5;
    }
    
    .image-holder img {
      width: 100%;
    }
    
    .image-holder img:first-child {
      max-height: var(--max-img-height);
    }
    
    .image-holder img:last-child {
      position: absolute;
      height: 100%;
      object-fit: cover;
    }
    
    .text-holder {
      padding: 2rem;
      position: relative;
      z-index: 1;
      grid-area: a;
      display: grid;
      place-items: center;
    }
    
    .text-holder p {
      max-width: 760px;
      font-size: 1.8rem;
      line-height: 2.3rem;
      font-weight: 700;
      text-align: center;
      font-family: sans-serif;
      margin: 0;
    }
    <div class="wrapper">
      <div class="image-holder">
        <img src="https://placebear.com/1200/800" alt="Bears">
        <img src="https://placebear.com/1200/800" alt="Bears">
      </div>
      <div class="text-holder">
        <p>Central text element, amount of text unknown. Solution must work for any amount of added text. Central text element, amount of text unknown.</p>
      </div>
    </div>
    Login or Signup to reply.
  2. Assuming we’re allowed to change the HTML structure, we can add max-height: 100% to the container of both text and image holder (in this example I used both-holder), then also add max-height: 80svh to the main wrapper:

    div.wrapper {
      display: grid;
      grid-template-rows: repeat(1, minmax(0, 1fr));
      grid-template-columns: repeat(1, minmax(0, 1fr));
      max-height: 80svh;
    }
    
    div.image-holder {
      z-index: 5;
    }
    
    div.both-holder {
      display: flex;
      justify-content: center;
      align-items: center;
      grid-row-start: 1;
      grid-column-start: 1;
      position: relative;
      max-height: 100%;
    }
    
    .text-holder {
      z-index: 30;
      padding: 2rem;
    }
    
    p {
      max-width: 760px;
      font-size: 1.8rem;
      line-height: 2.3rem;
      font-weight: 700;
      text-align: center;
      font-family: sans-serif;
    }
    
    img {
      object-fit: cover;
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      width: 100%;
      height: 100%;
      display: block;
      opacity: 0.5;
    }
    <div class="wrapper">
      <div class="both-holder" style="aspect-ratio: 1200 / 800; // This is inlined as it is pulled from the image size from the CMS">
        <div class="image-holder">
          <img src="https://placebear.com/1200/800" alt="Bears" />
        </div>
        <div class="text-holder">
          <p>Central text element, amount of text unknown. Solution must work for any amount of added text.</p>
        </div>
      </div>
    </div>
    Login or Signup to reply.
  3. body {
      min-width: 320px;
      margin: 0;
    }
    
    .wrapper {
      display: grid;
      grid-template-areas: 'a';
      position: relative;
      --max-img-height: 80vh;
    }
    
    .image-holder {
      grid-area: a;
      min-height: 100%; /* Ensure it's tall enough to accommodate the text */
      max-height: var(--max-img-height); /* Not taller than 80vh */
      display: grid;
      opacity: 0.5;
    }
    
    .image-holder img {
      width: 100%;
      height: 100%;
      object-fit: cover; /* Maintain aspect ratio and cover the container */
    }
    
    .text-holder {
      padding: 2rem;
      position: relative;
      z-index: 1;
      grid-area: a;
      display: grid;
      place-items: center;
    }
    
    .text-holder p {
      max-width: 760px;
      font-size: 1.8rem;
      line-height: 2.3rem;
      font-weight: 700;
      text-align: center;
      font-family: sans-serif;
      margin: 0;
    }
    <div class="wrapper">
      <div class="image-holder">
        <img src="https://placebear.com/1200/800" alt="Bears">
        <img src="https://placebear.com/1200/800" alt="Bears">
      </div>
      <div class="text-holder">
        <p>Central text element, amount of text unknown. Solution must work for any amount of added text. Central text element, amount of text unknown.</p>
      </div>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search