43

How can I scale a div to fit inside the browser view port but preserve the aspect ratio of the div. How can I do this using CSS and/or JQuery?

Thanks!

ʇsәɹoɈ
  • 19,708
  • 6
  • 48
  • 58
  • I provided the solution for this here: http://stackoverflow.com/questions/643500/html-ie-stretch-image-to-fit-preserve-aspect-ratio/19390489#19390489 – tommybananas Oct 15 '13 at 20:36
  • 1
    Can you accept an answer below? Seems a shame some very good answers go unaccepted – gillytech Mar 20 '14 at 05:02
  • Not a single one of the answers to this question achieve the desired result. Preserving the aspect ratio is trivial but getting it to be the correct aspect ratio AND always fitted to or smaller than the viewable area in both directions is more tricky. – atomless May 06 '15 at 16:01
  • Top answer here (from Danield) is the best solution : http://stackoverflow.com/questions/20590239/maintain-aspect-ratio-of-div-but-fill-screen-width-and-height-in-css – atomless May 06 '15 at 16:58

4 Answers4

45

You don't need javascript for this. You can use pure CSS.

A padding-top percentage is interpreted relative to the containing block width. Combine it with position: absolute on a child element, and you can put pretty much anything in a box that retains its aspect ratio.

HTML:

<div class="aspectwrapper">
  <div class="content">
  </div>
</div>

CSS:

.aspectwrapper {
  display: inline-block; /* shrink to fit */
  width: 100%;           /* whatever width you like */
  position: relative;    /* so .content can use position: absolute */
}
.aspectwrapper::after {
  padding-top: 56.25%; /* percentage of containing block _width_ */
  display: block;
  content: '';
}
.content {
  position: absolute;
  top: 0; bottom: 0; right: 0; left: 0;  /* follow the parent's edges */
  outline: thin dashed green;            /* just so you can see the box */
}

The display: inline-block leaves a little extra space below the bottom edge of the .aspectwrapper box, so another element below it won't run flush against it. Using display: block will get rid of it.

Thanks to this post for the tip!


Another approach relies on the fact that browsers respect an image's aspect ratio when you resize only its width or height. (I'll let google generate a 16x9 transparent image for demonstration purposes, but in practice you would use your own static image.)

HTML:

<div class="aspectwrapper">
  <img class="aspectspacer" src="http://chart.googleapis.com/chart?cht=p3&chs=160x90" />
  <div class="content">
  </div>
</div>

CSS:

.aspectwrapper {
  width: 100%;
  position: relative;
}
.aspectspacer {
  width: 100%; /* let the enlarged image height push .aspectwrapper's bottom edge */
}
.content {
  position: absolute;
  top: 0; bottom: 0; right: 0; left: 0;
  outline: thin dashed green;
}
Lipis
  • 19,958
  • 18
  • 88
  • 117
ʇsәɹoɈ
  • 19,708
  • 6
  • 48
  • 58
  • 1
    can you put up a jsFiddle example with a perfect box (all sides euqal) resizing using the first method? I didn't quite get how it can be done using your first method. – vsync Mar 28 '12 at 15:40
  • 4
    Here you are: http://jsfiddle.net/ks2jH/1/ Note that the key to making it a perfect box is the `padding-top: 100%` which means the height should be 100% of the size of the `.aspectwrapper` width. Since that width is set to 50%, it will resize with its parent. I also added `overflow: hidden` so the text wouldn't deform the box at small sizes. – ʇsәɹoɈ Mar 28 '12 at 20:30
  • If you wanted a rectangle half as tall as it is wide, you would use `padding-top: 50%`. In my example above, I made a 16:9 rectangle, suitable for wide screen video, using `padding-top: 56.25%` (9/16 = 56.25%). – ʇsәɹoɈ Mar 28 '12 at 21:58
  • great, thanks! you should update your answer to include this test page – vsync Mar 29 '12 at 14:26
  • 6
    this only seems to resize against the width. so it doesn't resize the width of the div so that the height fits. so it is not really fit-into-viewport but just rather boring old easy to achieve aspect ratio maintain. – Lassi Kinnunen Nov 14 '13 at 07:39
  • @LassiKinnunen Hint: You can build more complex things out of simpler things. – ʇsәɹoɈ Aug 13 '17 at 01:10
  • @ʇsәɹoɈ sure you can, but it doesn't seem to do what the topic of this question is. I've forgot the exact scenario I needed it for, but I think the thing was that I had a div and had to take that div and just plonk it inside another for one reason or another so that it fit entirely and whichever side didn't fit was made to fit while the other side was scaled in the same aspect. not that the other answers in this thread are too great either mind you. – Lassi Kinnunen Aug 23 '17 at 05:16
  • One very useful addition to the first variant: if you use `padding-top: 25%` in `.aspectwrapper::after` and `max-width: 400vh` in `.aspectwrapper`, the aspect wrapper fits not only the width of the viewport, but also its height (whichever constrains more). This is extremely useful when scaling a mostly fixed layout like presentation slides. – Palec Aug 24 '20 at 16:08
6

Thanks to Geoff for the tip on how to structure the math and logic. Here's my jQuery implementation, which I'm using to size a lightbox so it fills the window:

var height = originalHeight;
var width = originalWidth;
aspect = width / height;

if($(window).height() < $(window).width()) {
    var resizedHeight = $(window).height();
    var resizedWidth = resizedHeight * aspect;
}

else { // screen width is smaller than height (mobile, etc)
    var resizedWidth = $(window).width();
    var resizedHeight = resizedWidth / aspect;      
}

This is working well for me right now across laptop and mobile screen sizes.

TRMW
  • 61
  • 1
  • 4
  • 1
    Your check of `height < width` is only correct for an aspect ratio of 1:1. – talljosh Mar 07 '12 at 11:00
  • with little refinery this works, but your IF doesnt check for the right thing var vw=$("#absoluteSized").width(); var vh=$("#absoluteSized").height(); var divAspect=vw/vh; if(divAspect > aspect) { resizedHeight = vh; resizedWidth = resizedHeight * aspect; } else { // screen width is smaller than height (mobile, etc) resizedWidth = vw; resizedHeight = resizedWidth / aspect; } – Lassi Kinnunen Nov 14 '13 at 08:10
1

This is possible with JQuery and a bit of maths.

Use JQuery to get the view ports width and height as well as the divs current dimensions.

$(document).width();

Calculate the divs current aspect ratio. eg width/height

You need a bit of logic to determine whether to set the width or height first, then use the initial ratio to calculate the other side.

Geoff Appleford
  • 17,742
  • 4
  • 58
  • 83
1

jQuery has a plugin that grows an object until one of it's sides reaches a certain px-value. Coupling this will the viewport's height, you could expand any element to that size: jQuery MaxSide.

Sampson
  • 251,934
  • 70
  • 517
  • 549