1

I am currently using the following code to make images fill the entire screen while keeping their aspect ratio.

div {
  position: fixed;
  top: 0;
  width: 100%;
  height: 100%;
}

img {
  object-fit: contain;
  width: 100%;
  height: 100%;
  border: thin solid black;
}
<div>
  <img src="https://placekitten.com/200/300" alt="">
</div>

What this does is resize images which are smaller or larger than the screen to fill the entire screen while keeping their aspect ratio. For example, when using a display in landscape orientation (width > height) an image with portrait ratio (height > width) would be as high as the screen, while there is some space on the left and right. My example should illustrate this.

In these cases, I would like to be able to detect if the user clicks on the image or outside of it. However, with this approach the bounding box of the image fills the entire div and the entire screen, even if it looks different to the user.

What I mean by this is: The div is set to have 100 percent of the width and height of its container. Since its position is set to fixed, it will have the same size as the screen. For the object-fit property to work on the image, I need to assign it a width and height too. When I set those values to 100 percent, the image's so-called bounding box will fill the entire parent/screen, and then the image will take up as much space as it can inside this box while keeping its aspect ratio (see this answer for another explanation). That means it may look like the image only has the same height, and not the same width as its parent, but in reality, it does. You can verify this using the developer tools of your browser, and I added a border to the image to visualise it. This means, however, that I cannot attach an event listener to the image and one to the div to differentiate between clicks on the image and on the blank area, since the image counts as filling the entire area.

What would be the best approach to solve this? Is there a CSS-only-way? The only thing I can come up with is using JS to size the image, which means making it bigger/smaller to fit the screen while making it keep its aspect ratio, and also doing this on every resize. This seems like a lot of work for something so simple.

muell
  • 383
  • 1
  • 15
  • *"However, with this approach the bounding box of the image fills the entire div and the entire screen, even if it looks different to the user."* I didn't understand what you mean exactly by this – Yves Feb 08 '23 at 16:35
  • What's your question? What do you want to do? – theonlygusti Feb 08 '23 at 16:56
  • I edited the question and tried to better explain my problem. – muell Feb 09 '23 at 15:50

5 Answers5

2

Try using flex layout. If you change the height and width of div.outer or the dimensions of the image, it will remain centered in one dimension and fill the div.outer in the other. And only a click on the image itself will raise the alert.

div.outer {
  height: 200px;
  width: 100px;
  border: solid 1px black;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

div.inner {
  display: flex;
  flex-direction: row;
  justify-content: center;
}

div.inner,
img {
  max-width: 100%;
  max-height: 100%;
}
<div class="outer">
  <div class="inner">
    <img src="https://placekitten.com/200/300" onclick="alert('click')">
  </div>
</div>
Heiko Theißen
  • 12,807
  • 2
  • 7
  • 31
1

In general sense, if image covers the whole screen then we cant target the click on the parent div.

But if u go for the little space all on four corners, then we can provide the click on the parent.

Please refer to the snippet below.

Use the Flex on the div to center the img(image) tag. I have also provided the maximum width and height so that, the img(image) tag will be in boundary of the parent.

I had even provided you on how to force stretch if needed

* { box-sizing:border-box;}
html,body {height:100%;}
body {margin:0;}

div {
  position: fixed;
  /*stretching the DIV*/
  top: 0;
  bottom:0;
  right:0;
  left: 0;
  /*added the background-color for identification*/
  background-color: #eadefe;
  /*new-props*/
  display: flex;
  justify-content: center;
  align-items: center;
}

img {
  max-width: 100%; /** changed width to max-width **/
  max-height: 100%; /** changed height to max-height **/
  border: thin solid black;
}

/**Below is to force strech and keep image proportions**/

div.force-stretch {
  padding: 10px; /*provided padding so image and div can both get clicks*/
}
div.force-stretch img {
  object-fit:cover; /*added 10px gap so even if stretched there is space for parent div click*/
  width: 100%;
  height: 100%;
}
<div>
  <img src="https://placekitten.com/200/300" alt="">
</div>
YaswanthJg
  • 130
  • 11
1

You can use the strange behavior of flex to produce the desired result.

document.querySelector('img').onclick = () => {alert('you pet the kitten.')}
body {
    margin: 0;
}
.image-holder {
    height: 100vh;
    width: 100vw;
    display: flex;
    justify-content: center;
}
<div class="image-holder">
            <img
                src="https://images.unsplash.com/photo-1592194996308-7b43878e84a6?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=387&q=80"
                alt="kitten" />
        </div>

flex stretches the image's height, if you want to stretch the width use flex-direction: column.

K i
  • 539
  • 5
  • 12
0

This code solves your problem:

.img-container {
  width: 100%;
  height: 100vh;
  text-align: center;
}

img {
  object-fit: contain;
  height: 100%;
  max-width: 100%;
}

.some-text {
  height: 1000px;
}
<div class="some-text"></div>
<div class="img-container">
  <img src="https://placekitten.com/500/100" alt="">
</div>
<div class="some-text"></div>

Supposing that you have some elements before and after the image (element .some-text).

Yves
  • 252
  • 3
  • 6
  • Maybe you misunderstood my question, but this image still takes up the entire width, even though it doesn't look like it. That is exactly what I want to change, or find another way to discern if the image or the space to its left/right was clicked. – muell Feb 09 '23 at 15:48
  • I see. I edited the code accordingly. – Yves Feb 09 '23 at 16:09
  • Let me know what happens to you – Yves Feb 09 '23 at 16:24
  • Okay, this does what I want, but only with images that have greater height and/or smaller width than the screen. If I edit the image to be for example `https://placekitten.com/500/100` then the page becomes horizontally scrollable because the image fills more than the entire width. – muell Feb 10 '23 at 12:50
  • Answer edited again. Check it please. I would appreciate if you give me some points in order for the community to continue assisting people. Thank you – Yves Feb 11 '23 at 08:52
0

You can use the background-size property in CSS to set the size of the background image to fill the entire screen without having a bounding box. You can set the background-size property value to cover to make sure the image covers the entire screen, while maintaining its aspect ratio.

Here's an example:

body {
       background-image: url('your-image-url.jpg');
       background-size: cover;
       background-repeat: no-repeat;
       background-attachment: fixed;
    }

This will set the background image to fill the entire screen, without any bounding box or stretching of the image. The background-repeat property is set to no-repeat to prevent the image from repeating and the background-attachment property is set to fixed to keep the image in a fixed position on the screen.

  • `background-size: cover;` crops the image whereas `background-position: center; background-size: contain; background-repeat: no-repeat;` produces the desired white space. But clicking the image is then not possible. – Heiko Theißen Feb 13 '23 at 12:33
  • Yeah, as @HeikoTheißen said, providing background-image doesn't solve the scenario of clicking on the image. – YaswanthJg Feb 15 '23 at 14:58