003-home page-background image with text

I am working on the following layout for a home page

  • gray box represents a full bleed background image

  • h1, following text and get a quote button would probably be constrained with max-width, not sure yet

  • the whole block of h1, text and the button would be white text on gray backgound with opacity (so image is slightly visible) stretching full width of the image and placed on top of the image

  • I also plan to add 3 flexbox cards below an image representing main services that the company offers

please see the following link for current home page (current image is just for testing purposes and would probably replaced for a different image)


Question: Is CSS grid technique described here https://css-tricks.com/positioning-overlay-content-with-css-grid/ a good choice to achieve “text on top of image” effect?

1 Like

Yes that’s fine but its using a foreground image rather than a background image but that’s more of a semantic issue than a coding issue. There’s no real difference in most of these methods except grid avoids absolute positioning.

There are caveats with most of these methods and in that grid demo if I increase the amount of text or increase text size in the browser then it no longer fits on the image. What do you do then?

You have to plan ahead and if you only have the odd line of text then that’s fine but if you have multiple lines of text what do you do to make the image stretch over it? If you use object-fit: cover then you crop the image and if the image is an important part of the section you may just cut out the most important bit.

If the image is just decoration then the odd cropping won’t matter.


The amount of text (h1 and p) most likely wouldn’t change. I have to switch an image to a different one. Let me also try add those 3 flexbox cards below an image and see how everything fits together.

1 Like

I added a backgorund color and opacity to a wrapper div and it affected h2 and p that sit inside. I need to keep the text white and keep the opacity. Do I need z-index on h2 and p to fix it?

.headline {
    background-color: grey;
    opacity: 0.5;
<div class="entry-content">
<figure ><img /></figure>
<div class="headline">
<h2 ></h2>
<div class="btn-home">
<button type="button"></button>
</div><!-- .entry-content -->

The opacity property is what’s known as ‘atomic’ in that affects the element and all its children. It can’t be undone on child elements.

If all you wanted was the background color affected then use rgba.


background:rgba(204, 204, 204, 0.5)

The last value is the opacity.

1 Like

Works for me. Thanks Paul.

The following rule centers everything that sits within .entry-content. It also placed the button between h2 and p. How do I place the button after p (see screenshot in post #1) ? The whole block of h2 , p` and button just needs to be stacked. Is it a job for a flexbox ?

.home .entry-content {
    display: grid;
    grid-template: "container";
    place-items: center;
    place-content: center;
    max-height: clamp(1500px, 50vh, 2000px);

If this is the page that you linked to at the start then the problem is that you have placed everything in the grid area called ‘container’. That effectively stacks everything on top of itself just like absolute positioning in some ways.

What you really want is the figure in the grid container and the rest of the content in a single div which is placed in the container area and not all the individual items.

If you add a wrapper like this:

<div class="entry-content">

  <figure class="wp-block-image size-full"><img fetchpriority="high" decoding="async" width="2048" height="1152" src="http://test.prygara.com/wp-content/uploads/2024/05/home-page-landscaping-driveway-interlock-edited-2048x1152-1.jpg" alt="" class="wp-image-2045" srcset="https://test.prygara.com/wp-content/uploads/2024/05/home-page-landscaping-driveway-interlock-edited-2048x1152-1.jpg 2048w, https://test.prygara.com/wp-content/uploads/2024/05/home-page-landscaping-driveway-interlock-edited-2048x1152-1-300x169.jpg 300w, https://test.prygara.com/wp-content/uploads/2024/05/home-page-landscaping-driveway-interlock-edited-2048x1152-1-1024x576.jpg 1024w, https://test.prygara.com/wp-content/uploads/2024/05/home-page-landscaping-driveway-interlock-edited-2048x1152-1-768x432.jpg 768w, https://test.prygara.com/wp-content/uploads/2024/05/home-page-landscaping-driveway-interlock-edited-2048x1152-1-1536x864.jpg 1536w" sizes="(max-width: 2048px) 100vw, 2048px"></figure>

  <div class="figure-text">
    <div class="headline">

      <h2 class="wp-block-heading">R&amp;W Stone has over 20 years of experience.</h2>

      <p>Through landscaping and interlocking we will help you create a design that will enhance your home’s appeal, increase its value and offer a unique look.</p>

    <div class="btn-home">
      <button type="button">Get a Free Quote</button>

I added this wrapper <div class="figure-text"> in the above and that should fix the problem without changing the css. You will then need to add text-align: center to .btn-home to centre the button,

When you create template areas for a grid and place items using that area name the effectively the content is all placed on top of each other.


:fire: Magic number alert.

You would virtually never use a max-height in that way. Fixed heights are a no no for elements that hold fluid content. You never know the height and can’t control it either as the user may have zoomed the text. Use a min-height if you need an initial height but let the element grow as required.

Why did you think you needed that rule?


I came across this declaration in the original CCS Tricks article here so tried to use it in my layout.

Use min-height with a clamp function or set min-height on a parent and height: 100% on the image (child)? The way this is set up with WordPress is that it takes the original big image and then serves it in different sizes depending on screen size.

I used big image 2560 x 1441 pixels. If I go with min-height, what min-height would you recommend? Can you give an example?

Actually let me add those flexbox cards below the button and see what happens…

Ok ok. Its probably ok for images with only a small amount of text but I wouldn’t do it that way.

For a big here image like that I would let it fill the viewport height from the header downwards. You can do that very easily in grid or flex. In that way the image is always the viewport height and you don’t need any magic numbers.

Here’s the basic example.

If you wanted the footer at the bottom initially you can just move the footer inside the wrapper and it will all work.

No magic numbers required once again :slight_smile:

1 Like

I changed the layout as you suggested. I think because its a big image the top of a house is hidden under the header (please see screenshot below - area circled in red).

.home .entry-content {
	background: url(....) no-repeat 30%;
	background-size: cover; 
	display: flex;

when I change background-size: cover; to background-size: contain; top of a house is visible however image now gets narrower…

Question: how to properly scale down the image so top of a house fully visible but the image occupies whole viewport? Please see updated link post # 1 in this thread.

You can only do that if you don’t crop the height of the image. The image height has to be auto and would either need to be an image in the html or you would have to give the main element the same aspect ratio as the image.

What you are asking is physically impossible in the real world as you can’t have an image that is variable in width but its height is fixed. If the width changes then so must the height if you want to see all the image as nature intended. :slight_smile:

This is not a limitation of web design but the laws of the universe.:slight_smile: Imagine a picture of a person now you can’t just stretch the person wide without increasing their height or they would end up as a very fat short person.

The only options are to let the image scale its width but let the height auto adjust to maintain aspect ratio. Of course that would end up with a very large image going way below the fold of the document and not a great idea.

When you use background-size :cover it will ensure that the image covers the designated height and width but in order to do this it must enlarge both dimensions until the area is filled and then it crops that area to fit. hence why you get the top or bottom of the house cropped out.

If you use background-size: contain then the whole image will be viewable in the area designated but will not fill the area unless it just happens to have the same aspect ratio. there will will be gaps either at the side or the top and bottom.

When you choose hero images you should choose your images carefully so that the important bits like your house are more in the centre of the image and away from the edges, e.g. More sky and more ground in front of the house.

I suggest that you change the background-position to top anyway rather than centred and that will show more of the top of the house.

.home .entry-content {
    background: url(https://test.prygara.com/wp-content/uploads/2024/05/home-page-landscaping-driveway-interlock-edited-scaled.jpg) no-repeat 50% 0;
    background-size: cover;
    display: flex;

There are no other solutions apart from those mentioned or swapping for different images at different widths but then you’d still need to do what I suggested anyway in creating the image.


Thanks for your detailed explanation. As you mentioned it is impossible to have an image with fixed height but variable in width. The problem with this image is that my client initially wanted it on a front page because it shows stone interlock driveway in front of a garage. The interlock driveway area becomes visible though on narrower (mobile) screens which is expected I guess because we use background-size :cover and a browser redraws an image to fill out the available space.

Let me add a mobile menu and 3 flexbox cards representing main client services below the image and see how it all sticks together. Can you recommend a good resource (tutorial) on the web for mobile menus?

1 Like

It only becomes visible when the screen happens to be the same aspect ratio as the image which will be on smaller than larger screens because the height would need to be much greater on wider screens.

The only option is to display all the image is to do this:

.home .entry-content{
    aspect-ratio: 2560 / 1441   

That means on large wide screens the image will go below the fold because that’s the only way it can work.

I don’t look at many tutorials these days but here are a couple I plucked out.:slight_smile:

1 Like

I added 3 flexcards below the hero image

<div class="cards">
  <div class="card"><!--card 1 -->
     <div class="content">
       <a href="..."><img class="..." src="..." alt="" /></a>
      <div class="btn-home">
       <a href="..."><button type="button">Read more</button></a>
   </div><!--card 1 -->
  <div class="card"><!--card 2 -->
  <div class="card"><!--card 3 -->
<div><!--.cards -->

There’s a little bit of white space between an image and read more button (please see red arrow on the following image). Also see updated test link in post #1. Is it because space distribution is not calculated properly within class=“card” flex container or is it related to CSS properties applied to indivildual flex-items?

You will have been told this before as its one of those things that we have to say almost weekly on the forums but images are treated like text elements and by default are aligned to the baseline. There will be a gap underneath just as there needs to be for descenders when you use text. That’s so that inline images (which they are by default) will align on the baseline with the text content to which they refer.

The easiest solution is to turn the image into a block element and the gap will disappear.


html :where(img[class*=wp-image-]) {
    height: auto;
    max-width: 100%;
    display: block;

I generally set all images to block in my reset stylesheet as 99% of the time that’s what you want.

I notice that you have this structure which is invalid html.

<a href="https://test.prygara.com/services/" target="_blank" rel="noopener"><button type="button">Read more</button></a>

Either its a link or its a button? It can’t be both and anchors cannot have interactive content like buttons or indeed nested links (or vice versa).

You can style a button to look like a a link or style a link to look like a button so there is never any need to have both at the same time anyway. Use one or the other?

If its a link to another page then it should just be an anchor. On the other hand if clicking the text produces a dynamic effect using js (or form submit) then it should be a button. There is no need to confuse the two.:slight_smile: