0

I want to make an image width the same as the viewport width for any device, however, it should shrink or grow if someone zooms in or out

I've tried setting the html element font size and then setting the image to a slightly bigger-than-the-viewport size in rem. Then, to make sure it doesn't get bigger than the viewport, I've set max-width: 100%. This works great for any device size and also when zooming out, however bugs pretty bad when zooming in and does not work at all.

Is there any way to disable the max-width rule when zoom level is above 100%? Or perhaps there is a better way of doing this that doesn't involve rem?

Here is the code I'm using:

html {
  font-size: 10px;
}
.section {
  margin: 0;
  width: 160rem;
  max-width: 100%;
}
.section>img {
  width: 100%;
}
<html>
  <head>
    <meta charset="utf-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1">
  </head>
  <body>
    <section class="section">
      <img src="https://photographylife.com/wp-content/uploads/2017/07/Hasselblad-X1D-50c-Image-Sample-10.jpg" alt="Image">
    </section>
  </body>
</html>

To witness the effect run the snippet in "full page" and try zooming in

Isidor
  • 26
  • 2
  • 1
    Since it's been an hour and no one has suggested anything, I will suggest that you post your source code, as a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example), preferably as a Snippet directly within your post (the `<>` icon from the toolbar). It can be very hard to decipher the question that someone is truly asking from plain English alone (I can think of several different ways to interpret your question as-is), and an example will almost certainly help you get a better response. – Jake Mar 11 '23 at 01:28
  • I thought the question was clear enough without the code, but that was probably subjective. I added the relevant code now – Isidor Mar 11 '23 at 21:05
  • Ok, thank you for providing some code. I ran your snippet, went to the full-page view, and was able to zoom in and out without seeing anything that looked unintended. The image fills the viewport and doesn't introduce any scrollbars or wacky effects. Are you trying to allow a state where the image actually takes up more than 100% of the parent width when you zoom (so that you can see individual pixels and stuff when zoomed all the way in, ala the Microsoft Photos/Media Viewer apps)? – Jake Mar 11 '23 at 21:12
  • Yes, that is exactly what I meant – Isidor Mar 11 '23 at 21:38
  • Ok. So if you just remove `max-width: 100%`, that seems (to me) to be pretty close to what you're looking for. What part of that behavior is non-ideal? I guess to answer your original question though, it doesn't seem like there will be a way to remove the max-width based on zoom level, since [there isn't a good way to observe zoom level from JS](https://stackoverflow.com/questions/1713771/how-to-detect-page-zoom-level-in-all-modern-browsers). [This post](https://stackoverflow.com/questions/22223866/media-queries-for-different-zoom-levels-of-browser) maybe also be informative. – Jake Mar 11 '23 at 21:49
  • I don't think the usage of `rems` specifically is important in this context - they are just another measurement unit, like px or pt. – Jake Mar 11 '23 at 21:50
  • Depending on your exact goal, you might be able to spoof removal of the `max-width` at "higher zoom levels" by saying something like `if (document.body.clientWidth < image.hardCodedWidth) image.style.maxWidth=""`, which would read as "if the current width of the document is less than the desired width of the image, remove the max-width restriction" – Jake Mar 11 '23 at 21:57
  • Basically, i wanted the image to be 100% of the viewport by default, but to scale up or down just like text would. I guess it's just not possible, thanks anyway for your time :) – Isidor Mar 11 '23 at 22:39
  • Would it be possible to detect the viewport width in pixels on page load and page resize and set the width of the image accordingly? Then, because the value is in pixels it should behave properly on zoom (and as far as i know zooming does not send resize events?) – Isidor Mar 11 '23 at 22:42
  • Yes. I wouldn't recommend using the viewport specifically, unless your image is always guaranteed to consume the full size of the window (eg, no sidebar or anything). I used the `
    ` in [this example](https://jsfiddle.net/n3yrxm6h/11/), but you can modify it to read the size of different parent elements. One thing to keep in mind is that if the user launches the page at a zoom level that isn't 100% to begin with, this is probably gonna have some problems. You may be better off implementing your own image zoom functionality within your webpage, rather than relying on the browser zoom
    – Jake Mar 11 '23 at 22:52
  • nope, zooming does send resize events... browsers really don't want us working with zoom levels... – Isidor Mar 11 '23 at 22:53
  • i guess my idea would have worked using outerWidth if not for certain browser's sidebar options... don't supposed there is any way to measure does – Isidor Mar 11 '23 at 22:56

1 Answers1

0

So... After quite a few hours of searching and testing and frying neurons, I've managed to come up with a solution to my own question that:

  • works for all screen sizes
  • it automatically calculates zoom level
  • sets width of "section" so that when zoomed back to 100% it would actually be 100% of the viewport
  • accounts for sidebar width (opera/edge) and scroll bar
  • it resizes every time the page loads, gets resized or is zoomed

I'm going to leave this here in case anyone finds it useful:

var scroll_width = 0.7; //vw
var sidebar = window.outerWidth - window.innerWidth;
var zoom_level = window.outerWidth / window.innerWidth * 100;

if (zoom_level < 29) zoom_level = 25;
if (zoom_level >= 29 && zoom_level < 41) zoom_level = 33.3;
if (zoom_level >= 41 && zoom_level < 58) zoom_level = 50;
if (zoom_level >= 58 && zoom_level < 71) zoom_level = 66.6;
if (zoom_level >= 71 && zoom_level < 78) zoom_level = 75;
if (zoom_level >= 78 && zoom_level < 85) zoom_level = 80;
if (zoom_level >= 85 && zoom_level < 95) zoom_level = 90;
if (zoom_level >= 95 && zoom_level < 105) zoom_level = 100;
if (zoom_level >= 105 && zoom_level < 118) zoom_level = 110;
if (zoom_level >= 118 && zoom_level < 138) zoom_level = 125;
if (zoom_level >= 138 && zoom_level < 162) zoom_level = 150;
if (zoom_level >= 162 && zoom_level < 188) zoom_level = 175;
if (zoom_level >= 188 && zoom_level < 225) zoom_level = 200;
if (zoom_level >= 225 && zoom_level < 275) zoom_level = 250;
if (zoom_level >= 275 && zoom_level < 350) zoom_level = 300;
if (zoom_level >= 350 && zoom_level < 450) zoom_level = 400;
if (zoom_level >= 450) zoom_level = 500;

function resize() {
  var width_with_scroll = window.outerWidth - sidebar;
  var width_no_scroll = (width_with_scroll - (scroll_width / 100) * width_with_scroll);
  var width_integer = width_no_scroll * (zoom_level / 100);
  var width_string = width_integer.toString().concat("px");

  const section_list = document.querySelectorAll('.section');
  section_list.forEach(element => {
    element.style.width = width_string;
  });

}

window.onload = resize();
window.addEventListener('resize', function(event) {
  resize();
}, true);
html {
  font-size: 10px;
}

.section {
  margin: 0;
  width: 160rem;
  max-width: 100%;
}

.section>img {
  width: 100%;
}
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
</head>

<body>
  <section class="section">
    <img src="https://photographylife.com/wp-content/uploads/2017/07/Hasselblad-X1D-50c-Image-Sample-10.jpg" alt="Image">
  </section>
</body>

</html>
F. Müller
  • 3,969
  • 8
  • 38
  • 49
Isidor
  • 26
  • 2