84
This seems trivial but after all the research and coding I can't get it to work. Conditions are:
  1. The browser window size is unknown. So please don't propose a solution involving absolute pixel sizes.
  2. The image's original dimensions are unknown, and may or may not already fit the browser window.
  3. The image is vertically and horizontally centered.
  4. The image proportions must be conserved.
  5. The image must be displayed in its entirety in the window (no cropping.)
  6. I do not wish scrollbars to appear (and they shouldn't if the image fits.)
  7. The image automatically resizes when the window dimensions change, to occupy all the available space without being larger than its original size.
Basically what I want is this:
.fit {
  max-width: 99%;
  max-height: 99%;
}
<img class="fit" src="pic.png">
The problem with the code above is that it doesn't work: the pic takes all the vertical space it needs by adding a vertical scroll bar.
At my disposal is PHP, Javascript, JQuery but I'd kill for a CSS-only solution. I don't care if it doesn't work in IE.

11 Answers

70
Update 2018-04-11
Here's a Javascript-less, CSS-only solution. The image will dynamically be centered and resized to fit the window.
<html>
<head>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        .imgbox {
            display: grid;
            height: 100%;
        }
        .center-fit {
            max-width: 100%;
            max-height: 100vh;
            margin: auto;
        }
    </style>
</head>
<body>
<div class="imgbox">
    <img class="center-fit" src='pic.png'>
</div>
</body>
</html>

The [other, old] solution, using JQuery, sets the height of the image container (body in the example below) so that the max-height property on the image works as expected. The image will also automatically resize when the client window is resized.
<!DOCTYPE html>
<html>
<head>
    <style>
        * {
            padding: 0;
            margin: 0;
        }
        .fit { /* set relative picture size */
            max-width: 100%;
            max-height: 100%;
        }
        .center {
            display: block;
            margin: auto;
        }
    </style>
</head>
<body>

<img class="center fit" src="pic.jpg" >

<script src="http://code.jquery.com/jquery-latest.js"></script>
<script type="text/javascript" language="JavaScript">
    function set_body_height() { // set body height = window height
        $('body').height($(window).height());
    }
    $(document).ready(function() {
        $(window).bind('resize', set_body_height);
        set_body_height();
    });
</script>

</body>
</html>
Note: User gutierrezalex packaged a very similar solution as a JQuery plugin on this page.
37
Here is a simple CSS only solution (JSFiddle), works everywhere, mobile and IE included:
CSS 2.0:
html, body {
    height: 100%;
    margin: 0;
    padding: 0;
}

img {
    padding: 0;
    display: block;
    margin: 0 auto;
    max-height: 100%;
    max-width: 100%;
}
HTML:
<body>
  <img src="images/your-image.png" />
</body>
  • Nice. But it's not vertically centered. – sebnukem Feb 13 '16 at 14:14 
  • 1
    @sebnukem: Was it supposed to be? Somehow I missed this in requirements. That's why people use screenshots/mockups. :) P.S. I don't think any of the answers provided make it vertically centered, even with JS help. – Neolisk Feb 13 '16 at 14:24 
  • 2
    I have tried many solutions out there, even solutions from css-tricks. Yours just perfectly works like a charm ! – Stephan Jun 22 '16 at 1:27 
  • 1
    Best solution ever! – iVela Feb 23 '18 at 11:25
20
CSS3 introduces new units that are measured relative to the viewport, which is the window in this case. These are vh and vw, which measure viewport height and width, respectively. Here is a simple CSS only solution:
img {
    max-width: 100%;
    max-height: 100vh;
    height: auto;
}
The one caveat to this is that it only works if there are no other elements contributing height on the page.
  • Thanks, that's great. Is it any reason why 100vh doesn't let image fit but 97vh works well? – Pavel May 17 '17 at 0:50 
  • Perhaps you have other images contributing height, such as margin and padding on the body? vh literally means the hight of the view, so if any other elements add hight to your page, the entire page will be > 100vh. Does that make sense? – Max May 17 '17 at 4:55
  • Thank you, solved now. If anybody have same problem (.svg file renders well, but renaming it to .htmlcauses inaccuracy): browser automatically adds <body> tag with default margin:8 even if the file hasn't <body> tag. So solution is adding <style>body{margin:0}</style> – Pavel May 17 '17 at 15:36
13
If you are willing to put a container element around your image, a pure CSS solution is simple. You see, 99% height has no meaning when the parent element will extend vertically to contain its children. The parent needs to have a fixed height, say... the height of the viewport.
HTML
<!-- use a tall image to illustrate the problem -->
<div class='fill-screen'>
    <img class='make-it-fit' 
         src='https://upload.wikimedia.org/wikipedia/commons/f/f2/Leaning_Tower_of_Pisa.jpg'>
</div>
CSS
div.fill-screen {
    position: fixed;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    text-align: center;
}

img.make-it-fit {
    max-width: 99%;
    max-height: 99%;
}
Play with the fiddle.
3
My general lazy CSS rule:
.background{
width:100%;
height:auto;
background: url('yoururl.jpg') no-repeat center;
background-position: 50% 50%;
background-size: 100% cover!important;
overflow:hidden;
}
This may zoom in on your image if it is low-res to begin with (that's to do with your image quality and size in dimensions. To center your image, you may also try (in the CSS)
display:block;    
margin: auto 0; 
to center your image
in your HTML:
<div class="background"></div>
2
Resize Image to Fit the Screen by the Longest Side maintaining its Aspect Ratio
img[src$="#fit"] {
    width: 100vw;
    height: auto;
    max-width: none;
    max-height: 100vh;
    object-fit: contain;
}
  • width: 100vw - image width will be 100% of view port
  • height: auto - image height will be scaled proportionally
  • max-height: 100vw - if image height would become more than view port it will be decreased to fit the screen, consequently image width will be decreased because of the following property
  • object-fit: contain - the replaced content is scaled to maintain its aspect ratio while fitting within the element's content box
    Note: object-fit is fully supported only since IE 16.0
1
width: 100%;
overflow: hidden;
I believe that should do the trick.
  • Hi, thanks for your answer, but it doesn't and can't logically work when the image height is greater than the window. – sebnukem May 29 '11 at 18:51
  • 1
    Well... What is it you're intending to do? Do you wich to stretch it? Or should th eoriginal proportions be left intact (I assume this is what you want)? – RobinJ May 30 '11 at 15:12
1
html, body{width: 99%; height: 99%; overflow: hidden}
img.fit{width: 100%; height: 100%;}
1
I had a similar requirement, and had to do it it basic CSS and JavaScript. No JQuery available.
This is what I got working.
<html>
      <head>
            <style>
                   img {
                          max-width: 95% !important;
                          max-height: 95% !important;
                       }
            </style>
            <script>
                   function FitImagesToScreen() {
                      var images = document.getElementsByTagName('img');
                      if(images.length > 0){
                         for(var i=0; i < images.length; i++){
                             if(images[i].width >= (window.innerWidth - 10)){
                                 images[i].style.width = 'auto';
                               }
                            }
                         }
                   }
             </script>
      </head>
      <body onload='FitImagesToScreen()'>
      ----    
      </body>
</html>
Note : I haven't used 100% for image width as there was always a bit of padding to be considered.
  • 2
    With CSS 3 we get the "vh" and "vw" units which are percent viewport-height and percent viewport-width respectively. simply img { max-width: 95vw; max-height: 95vh;} might be sufficient. – bobpaul Jan 31 '16 at 7:57
  • If you can add it up as an answer might be useful for any one coming to this later. – Rohit Vipin Mathews Mar 25 '16 at 13:56
  • You can also stack multiple images in the viewable area. For two images, put two img tags into the body of the page and set max-height to 49vh. Displaying more than two images in the viewable area is left as an exercise for the reader. – Andrew Beals Mar 14 at 17:13 
0
Building upon @Rohit's answer, this fixes issues flagged by Chrome, reliably resizes the images, and also works for multiple images that are vertically stacked, e.g. <img src="foo.jpg"><br><img src="bar.jpg"><br><img src="baz.jpg"> There is probably a more elegant way of doing this.
<style>
    img {
        max-width: 99vw !important;
        max-height: 99vh !important;
    }
</style>
<script>
    function FitImagesToScreen() {
        var images = document.getElementsByTagName('img');
        if(images.length > 0){
            document.styleSheets[1].rules[0].style["max-height"]=((100/images.length)-1)+"vh";
            for(var i=0; i < images.length; i++){
                if(images[i].width >= (window.innerWidth - 10)){
                    images[i].style.width = 'auto';
                }
            }
        }
    }
</script>
</HEAD>
<BODY onload='FitImagesToScreen()' onresize='FitImagesToScreen()'>
<img src="foo.png">
</BODY>
0
Make it simple. Thanks
.bg {
  background-image: url('https://images.unsplash.com/photo-1476820865390-c52aeebb9891?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&w=1000&q=80');
  background-repeat: no-repeat;
  background-size: cover;
  background-position: center;
  height: 100vh;
  width: 100vw;
}
<div class="bg"></div>