Overlaying an Image

Hello,
I have a mountain image (https://www.ballymoretales.com/c1s1page/)
that I would like put a duplicate overlay image on top of. The overlay image would be just the mountain without the sky. It would have to lineup exactly on all screens. What would be the best method to use?

Thanks

Hi Engine44,
The first thing I would suggest is reducing the size of that image.
It is 3456 x 5184 pixels and it weighs in at 6.33mb. It is way to big in both aspects for what you are doing with it.

I reduced it to 1000 x 1500 px and then saved for web and got it down to 103kb.
The mountain image’s parent container is set to 45vw width.

The ‘Map Of Ballymore’ image below it is 387 x 500px. It’s .center1 class has the width set to 45vw. On my 20" monitor the native image size is stretching to 720 x 930px.

Likewise the mountain image on my 20" monitor (with browser window at full width) with it’s parent width at 45vw renders the image at 718 x 1077px for me.

I’m just pointing out that the mountain is way to big and scaling down while the map is scaling up.

Now, as for your question about overlaying an image. The mtn image is in the html as an <img> element. That will complicate laying another image on top of it. I do see that the mountain image and the map image both tie in to your storyline so they are part of the pages content and the <img> element is correct. As opposed to being a background image.

However, if it were set as a background image in a div you could use multiple backgrounds and laying another image on top would be easy and it positioning would be easily controlled too, by way of background-position. That’s probably what I would do with it. I think your storyline and image will still stay in tune with each other. Background images are used for decoration and add no semantic value to the page, other than the visual connection they make.

3 Likes

You can use the current parent div and set it as a bg image there.
<div class="mountain-bird-wrapper">

See MDN for using multiple bg images

Edit:
As it is now, the html <img> is setting the height of the parent div according to the images aspect ratio. When it gets moved to the parent as a bg image the height of the parent div will collapse since there will be no content holding it open.

That’s where it will get tricky. Luckily that problem has been solved with the old scaling iframe trick that uses using aspect ratio boxes.

Here is the your image I optimized earlier.

In this test code I used a div called .ratio to hold the bg image. You can copy over the relevant rules to your current parent styles.

The new image is 1000 width x 1500 height, its aspect ratio is 2:3. With this aspect ratio , the height is 1.5 times longer than the width.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Test Page</title>
<style>

.ratio {
   width:100%;
   max-width: 45vw;
   margin: auto;
   padding-top: 68%; /*img height / img width  = 2:3 aspect ratio*/
   background: url(mountainNight.jpg) no-repeat;
   background-size: 100%;
   border-radius: 10px;
   border: 1px solid red; /* test aspect ratio accuracy*/
}
</style>

</head>
<body>

<div class="mountain-bird-wrapper ratio">
  <div class="bird-container bird-container--one">
  	<div class="bird bird--one"></div>
  </div>

  <div class="bird-container bird-container--two">
  	<div class="bird bird--two"></div>
  </div>

  <div class="bird-container bird-container--three">
  	<div class="bird bird--three"></div>
  </div>

  <div class="bird-container bird-container--four">
  	<div class="bird bird--four"></div>
  </div>

  <div class="bird-container bird-container--five">
  	<div class="bird bird--five"></div>
  </div>
  <!--<img> moved to background-->
</div>


</body>
</html>
4 Likes

Thanks. Here is the edited code:

<div class="mountain-bird-wrapper">

	<div class="bird-container bird-container--one">
		<div class="bird bird--one"></div>
	</div>
	
	<div class="bird-container bird-container--two">
		<div class="bird bird--two"></div>
	</div>
	
	<div class="bird-container bird-container--three">
		<div class="bird bird--three"></div>
	</div>
	
	<div class="bird-container bird-container--four">
		<div class="bird bird--four"></div>
  </div>

.mountain-bird-wrapper {
      position: relative;
      margin: auto;
      display: block;
      overflow: hidden;
      border: 1px solid #333;
      border-radius: 15px;
      box-shadow: 5px 5px 20px 5px #333;
      width: 45vw;
      max-width: 45vw;
      padding-top: 66.6%;
      background-image: url(/imgMaster/mountainNight.jpg);
      background-repeat: no-repeat;
      background-size: 100%;
}

If everything is ok now,  I will add a second background image.
1 Like

It depends on the specific use case.
Do you actually need another mountain image under your mountain image?
Or do you just want your sky to be a different layer to your mountain?

I need two mountain images so that I can have one new bird fly behind the mountain. Here is the current CSS:


.mountain-bird-wrapper {
      position: relative;
      margin: auto;
      display: block;
      overflow: hidden;
      border: 1px solid #333;
      border-radius: 15px;
      box-shadow: 5px 5px 20px 5px #333;
      width: 45vw;
      max-width: 45vw;
      padding-top: 66.6%;
      background-image: url(/imgMaster/terrainDay.png), url(/imgMaster/mountainNight.jpg);
      background-repeat: no-repeat;
      background-size: 100%;
}

Both images are showing.

How do I adjust the z-index of the images? Thanks.

EDIT: I just read that you can’t adjust the z-index of backgrounds. They are stacked as specified. Is there a workaround to get one bird behind the mountain?

No you can’t get between multiple backgrounds. You’d need to have the second image in another separate layer to do this.

You could use :before or :after to add a new layer over the top of the other background and absolutely place it on top in much the same way that you did with the birds in the other thread.

I’m on a mobile at the moment so can’t offer real code. :slight_smile:

Do you think the before/after approach is better than trying to place one img on top of another?

I took a guess at how to create a second layer with ::before and got lucky. Thanks.

If you make the bird-container z-index:2 and then the new :before element z-index:3 then that will place the birds between the mountain wrapper background and the new overlay. Of course to see the birds under the new overlay there will need to be transparent sections in the image overlay otherwise you can’t see through an image. You could set opacity to less than one on the overlay but that means you will see the birds underneath all parts of the image and I thought you wanted the birds to fly under a mountain section.

Just remember that within the same stacking context the positioned elements z-index will control which is on top with the higher number being nearest to the viewer.

You can’t see through an image unless you either set its opacity to less than one or if the image is made with transparent sections where you want the birds to be shown underneath.

If you want the birds on top of everything then just raise their z-index above the others.

Thanks. I got it working. In the ::before layer, the sky is transparent.

2 Likes

This is why I ask.
In the name of efficiency and reducing page size, Ray has already made a huge saving by optimising your image. But is there any point loading two images of a mountain, when one will never be seen, being obscured by the top layer mountain?
All you really need on the background layer is the sky. This could possibly be created procedurally, with far fewer bites than a second mountain picture. The sky itself could be a simple gradient. For the stars, if as per your other topic, you want them twinkling, I’m sure these could be overlaid by some means.
Then for the mountain image, you need that with an alpha channel on the sky to make that part transparent.

3 Likes

Thank you

I don’t have time to make flying birds or starry skies, so here is a very basic example to illustrate the point about the image overlay.
I made the single image of the mountain, 1000 x 1500, the same as Ray’s, put an alpha channel on the sky, so it’s transparent, then converted a PNG to WebP.
The resulting image is only about 75kb, with alpha.
As PNG it’s about 817kb, which has better browser support, but the lossless compression is inefficient with photos. WebP allows lossy compresion (better for photos) with alpha.
I can’t upload a webp here, so I had to put it in a zip.
mountain.zip (74.0 KB)
The sky is a gradient background. Instead of birds or stars, I put in a simple moon object between the sky and mountain.
The whole thing is about 76kb. The way you were heading, with two oversize images would have been well in excess of 10mb.

4 Likes

Thanks for your time. This is a very dynamic project and now I’m looking at twinkling stars on CodePen. The varying approaches is helping my knowledge quite a bit. Thanks again.

2 Likes

I am having an issue with the height positioning of the birds on different devices. Here is the current code:

<div class="mountain-bird-wrapper">

	<div class="bird-container bird-container--one">
		<div class="bird bird--one"></div>
	</div>
	
	<div class="bird-container bird-container--two">
		<div class="bird bird--two"></div>
	</div>
	
	<div class="bird-container bird-container--three">
		<div class="bird bird--three"></div>
	</div>
	
	<div class="bird-container bird-container--four">
		<div class="bird bird--four"></div>
  </div>

  <div class="bird-container bird-container--five">
		<div class="bird bird--five"></div>
  </div>

</div>



.mountain-bird-wrapper {
  position: relative;
  margin: auto;
  display: block;
  overflow: hidden;
  border: 1px solid #333;
  border-radius: 15px;
  box-shadow: 5px 5px 20px 5px #333;
  width: 45vw;
  max-width: 45vw;
  padding-top: 66.6%;
  background-image: url(/imgMaster/nightSky.jpg);
  background-repeat: no-repeat;
  background-size: 100%;
}
/*----------------------*/

.bird.bird--one {
  background-image: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/174479/bird-cells-new.svg);
  background-size: auto 100%;
  width: 88px;
  height: 125px;
  will-change: background-position;

  animation-name: fly-cycle;
  animation-timing-function: steps(10);
  animation-iteration-count: infinite;
  animation-duration: 1s;
  animation-delay: 0s;
}

.bird.bird--two {
  background-image: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/174479/bird-cells-new.svg);
  background-size: auto 100%;
  width: 88px;
  height: 125px;
  will-change: background-position;

  animation-name: fly-cycle;
  animation-timing-function: steps(10);
  animation-iteration-count: infinite;
  animation-duration: 1.1s;
  animation-delay: -1s;
}

.bird.bird--three {
  background-image: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/174479/bird-cells-new.svg);
  background-size: auto 100%;
  width: 88px;
  height: 125px;
  will-change: background-position;

  animation-name: fly-cycle;
  animation-timing-function: steps(10);
  animation-iteration-count: infinite;
  animation-duration: 1.05s;
  animation-delay: -0.25s;
}

.bird.bird--four {
  background-image: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/174479/bird-cells-new.svg);
  background-size: auto 100%;
  width: 88px;
  height: 125px;
  will-change: background-position;

  animation-name: fly-cycle;
  animation-timing-function: steps(10);
  animation-iteration-count: infinite;
  animation-duration: 1.1s;
  animation-delay: -0.5s;
}

.bird.bird--five {
  background-image: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/174479/bird-cells-new.svg);
  background-size: auto 100%;
  width: 88px;
  height: 125px;
  will-change: background-position;

  animation-name: fly-cycle;
  animation-timing-function: steps(10);
  animation-iteration-count: infinite;
  animation-duration: 1s;
  animation-delay: -0.7s;
}

.bird-container.bird-container--one {
  position: absolute;
  top: 30%;
  left: -25px;
  z-index: 5;
  transform: scale(0) translateX(-10vw);
  will-change: transform;

  animation-name: fly-right-one;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
  animation-duration: 10s;
  animation-delay: 0;
}

.bird-container.bird-container--two {
  position: absolute;
  top: 10%;
  left: -25px;
  z-index: 5;
  transform: scale(0) translateX(-10vw);
  will-change: transform;

  animation-name: fly-right-one;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
  animation-duration: 11s;
  animation-delay: 0s;
}

.bird-container.bird-container--three {
  position: absolute;
  top: 33%;
  left: -25px;
  z-index: 5;
  transform: scale(0) translateX(-10vw);
  will-change: transform;

  animation-name: fly-right-one;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
  animation-duration: 10.6s;
  animation-delay: 9.5s;
}

.bird-container.bird-container--four {
  position: absolute;
  top: 4%;
  left: -25px;
  z-index: 5;
  transform: scale(0) translateX(-10vw);
  will-change: transform;

  animation-name: fly-right-one;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
  animation-duration: 13s;
  animation-delay: 10.25s;
}

.bird-container.bird-container--five {
  position: absolute;
  top: 19%;
  left: -25px;
  z-index: 2;
  transform: scale(0) translateX(-10vw);
  will-change: transform;

  animation-name: fly-right-one;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
  animation-duration: 11s;
  animation-delay: 10s;
}

@keyframes fly-cycle {
  100% {
    background-position: -900px 0;
  }
}

@keyframes fly-right-one {
  0% {
    transform: translateY(0%) translateX(-10vw) scale(0.5);
  }

  10% {
    transform: translateY(0%) translateX(0vw) scale(0.5);
  }

  20% {
    transform: translateY(0%) translateX(15vw) scale(0.5);
  }

  30% {
    transform: translateY(0%) translateX(30vw) scale(0.5);
  }

  40% {
    transform: translateY(0%) translateX(45vw) scale(0.5);
  }

  50% {
    transform: translateY(0%) translateX(55vw) scale(0.5);
  }

  60% {
    transform: translateY(0%) translateX(60vw) scale(0.5);
  }

  70% {
    transform: translateY(0%) translateX(70vw) scale(0.5);
  }

  80% {
    transform: translateY(0%) translateX(80vw) scale(0.5);
  }

  90% {
    transform: translateY(40%) translateX(90vw) scale(0.5);
  }

  100% {
    transform: translateY(0%) translateX(110vw) scale(0.5);
  }
}

I set the Top position for the birds in % because they are positioned Absolute in a Relative container. The % should work on all screens but it doesn’t. As the screen width narrows, the birds move downwards. As a partial workaround, I reset their heights on smaller screens. What point am I missing? Thanks.

I don’t think you can have that amount of fine control because although you are using percent on the container the actual bird image has a fixed height of 125px and obviously the smaller the screen the more the 125px takes up room.

You can make it a little better by positioning the bird at the top of its own container.

.bird{
position:absolute;
top:0;
}

To be perfect the birds themselves would need to be defined in percentages and not use fixed px width and heights. Also there is the scaling and transform being taken into account so fine control will be very difficult to achieve.

1 Like

Thanks. For sizing the birds by percentages. What would it be a percentage of? 100% would equal what?

It’s not that simple unfortunately because as this is a background image you would need to know the spect ratio of the bird image and then convert its width and height into the correct percentage aspect ratio to match the size of the bird. You would need the padding-top trick once again to maintain that aspect ratio correctly.

However your background image is actually 10 images stuck together and you animate between each of those sprites to get the illusion of movement. Therefore working out an aspect ratio that matches each of those images will be awkward (unless the 88px x 125px is the actual sprite size). That will likely also compound the animation problem in that you have to move from one image to the next smoothly

I’d need to deconstruct that whole animation and work out what goes where in order to make it truly responsive.

If I get a couple of spare hours I’ll have a look later this afternoon and see what/if can be done to make it more fluid. Unless someone else jumps in beforehand :slight_smile:

I’ve been playing around with the problem and may have found a solution. It really matters how the Top position of the birds is specified.

There are three selectors involved for bird number four:

.bird
.bird-container
.bird-container--four

The original syntax was:

.bird-container.bird-container--four {

That resulted in the position problem.

I found a syntax that seems to work well for all screens. The birds’ height postion is not changing from the original set %:

.bird {
  position:absolute;
  top:0%;
  }

  .bird-container--four {
    position:absolute;
    top:4%;
  }

I did make the birds smaller for smaller screens.