2

So, I have an art website, with each work getting its own page. The works are mostly photos, meaning they have higher resolutions than most screens are capable of displaying - so they need to be resized down to scale, obviously.

To make works easier to look through, I display them such that they take up most of the screen (minus 100px in either dimension), scaling to fill whichever dimension is more limiting:

  • Work X is square-shaped, and on the average monitor it gets resized so that its height fills the entire vertical space, and its width scales accordingly - preserving the aspect ratio
  • Work Y is tapestry-shaped, and gets resized so that its width fills the entire horizontal space, and its vertical space gets resized to match that aspect ratio.

I'm currently using a straightforward Javascript script for this, calling a function on the img tag's onload (as well as whenever the window is resized) to calculate the desired width/height of the image and apply that. The problem with using Javascript for this is that there's a delay between when the image begins to load and when it resizes, which makes the page look really ugly for a while, especially when viewing the site on a poor internet connection.

Leading to my question: is there a way to resize images to a certain percentage of screen size, while preserving aspect ratio, in pure CSS?

This answer provides another Javascript solution, but I'd prefer to find a way to do this in pure CSS if possible.


My current script is this:

function setGoodHeight (element) {
    if( on mobile ) {
        ...
    }
    else {
        height_buffer = 100
        width_buffer = 100
        height_diff_pct = element.naturalHeight / window.innerHeight
        width_diff_pct = element.naturalWidth / window.innerWidth
        if(height_diff_pct > width_diff_pct) {
            var h = element.naturalHeight;
            var w = element.naturalWidth;
            element.height = window.innerHeight - height_buffer;
            element.width = w * element.height / h;
        }
        else {
            var h = element.naturalHeight;
            var w = element.naturalWidth;
            element.width = window.innerWidth - width_buffer;
            element.height = h * element.width / w;
        }
        if(element.width < 540) {
            element.parentNode.setAttribute("style","width:" + 540 + "px");
        }
        else {
            element.parentNode.setAttribute("style","width:" + (element.width + 40) + "px");
        }
    }
}
Green Cloak Guy
  • 23,793
  • 4
  • 33
  • 53
  • did you try to get the screem size, then set the photo to that size? – NoobDEV-GBL May 08 '19 at 16:28
  • Yeah, essentially my script gets `window.innerWidth` and `window.innerHeight`, computes ratio between image width/height with window width/hight and takes whichever ratio is smaller, then adjusts the entire image to that. – Green Cloak Guy May 08 '19 at 16:37
  • Have you tried using the `vw` and `vh` units in CSS? `100vw = 100% of browser viewport width`. Using `height: auto;` also preserves the aspect ratio. – Romen May 08 '19 at 16:42
  • Post the HTML and code you currently have. – disinfor May 08 '19 at 16:54
  • I have posted the javascript code. The HTML is literally just an `img` tag, in this case. – Green Cloak Guy May 08 '19 at 16:57
  • @Romen this was the solution: turns out that doing `max-width:90vw; max-height: 80vh;` worked perfectly. If you can add that as an answer I'll accept it – Green Cloak Guy May 08 '19 at 17:50

4 Answers4

3

Using the vw and vh units in CSS allow you to size things based on the browser viewport rather than parent elements.

If you set the max-width and max-height for the image it should constrain the image to be no bigger than the browser viewport size for any browser size.

#image-id {
    max-width: 80vw;
    max-height: 80vh;
}
Romen
  • 1,617
  • 10
  • 26
1

Tell your images to be at most 100% width of the container they are in, and height set to auto will maintain aspect ratio.

.my-image-class {
  max-width: 100%;
  height: auto;
}
BugsArePeopleToo
  • 2,976
  • 1
  • 15
  • 16
  • By my understanding, if the container was the width of the screen here, then an image could be resized to be larger than the screen - whereas I would want it to scale based on height if that was the case – Green Cloak Guy May 08 '19 at 16:38
  • @GreenCloakGuy There is no HTML markup provided. The immediate container around the images should be set to the desired width. The code I provided is simple and effective to have the images conform. – BugsArePeopleToo May 08 '19 at 16:40
0

How about using background-size: cover; for this? Every image can be the background of a div, which in turn has the following properties set.

  1. height
  2. width
  3. background-size: cover;
  4. background: url('img.png') center center no-repeat;
Raghav Kukreti
  • 552
  • 5
  • 18
  • Is there a way to provide the url at runtime through the html? I have a templated .html page (so I fill the image source in when I serve the page) but a static css document, and filling this all in in the `style` attribute didn't work. – Green Cloak Guy May 08 '19 at 17:04
  • Also when I tested this it didn't seem to do what I wanted. Horizontal scaling worked but vertical scaling didn't, and also the image didn't *scale*, it just got cut off. – Green Cloak Guy May 08 '19 at 17:10
0

JavaScript is the best answer but if you really want to only use css you can use percentages rather then px these will scale to a given container.

.img {
max-width:100%;  
max-height:100%;

}

here is a similar question and answer: StackPost

MrBabbels
  • 29
  • 6