Maintain aspect ratio according to width and height

You can achieve a responsive square using the vw & vh units (viewport-percentage lengths) to size it.

Check for browser support: http://caniuse.com/viewport-units


Solution that implements both horizontal and vertical scaling

Live sample page: http://sample.easwee.net/responsive-square/

.container {
    display:table;
    width:100%;
    height:100%;
}

.container-row {
    display:table-row;
}

.container-cell {
    display:table-cell;
    vertical-align:middle;
    text-align:center;
}

.square {
    display:inline-block;
    background:red;
    border: 3px solid blue;
}
@media(orientation:landscape) {
	.square {    	   
	    width: 100vh;
	    height: 100vh;
	}
}
@media(orientation:portrait) {
	.square{
	    width: 100vw;
	    height: 100vw;
	}
}
<div class="container">
	<div class="container-row">
		<div class="container-cell">
    		<div class="square"></div>
    	</div>
	</div>
</div>

I've combined the excellent answers from @ken-sharpe and @easwee to create a version for non-square aspect ratios: https://codepen.io/anon/pen/GyqopP

div {
  position: absolute;
  top:0;bottom:0;
  left:0;right:0;
  margin: auto;

  width: 100vw;
  height: 50vw;
  background: #326384;
}

@media (min-aspect-ratio: 2/1) {
    div {          
        width: 200vh;
        height: 100vh;
        background-color:green;
    }
}

The aspect-ratio property (2022)

To maintain the aspect ratio of a div according to width and height, you can use the aspect-ratio property (MDN reference).
This allows you to maintain any aspect ratio according to the viewport size or to the size of the parent element.

Maintaining aspect-ratio according to the viewport size (width and height) :

.ar-1-1 {
  aspect-ratio: 1 / 1;
  background: orange;
}

.ar-1-19 {
  aspect-ratio: 16 / 9;
  background: pink;
}

div {
  max-width: 100vw;
  max-height: 100vh;
  margin-bottom: 5vh;
}


/** For the demo **/

body {
  margin: 0;
}
<div class="ar-1-1">Aspect ratio 1:1</div>
<div class="ar-1-19">Aspect ratio 1:19</div>

Maintaining aspect ratyio according to the parent elements size (width and height) :

section {
  width: 50%;
  margin: 0 auto 5vh;
  height:250px;
}
.ar-1-1 {
  aspect-ratio: 1 / 1;
  background: orange;
}

.ar-1-19 {
  aspect-ratio: 16 / 9;
  background: pink;
}

div {
  max-width: 100%;
  max-height: 100%;
}


/** For the demo **/

body {
  margin: 0;
}
<section>
<div class="ar-1-1">Aspect ratio 1:1</div>
</section>
<section>
<div class="ar-1-19">Aspect ratio 1:19</div>
</section>

Previous answer with vmin units

This still works fine but it doesn't allow to maintain the aspect ratio according to a parent element size.

To maintain the aspect ratio of a div according to width and height in the viewport, you can use one HTML tag with:

  1. vmin units for the sizing :

    vmin 1/100th of the minimum value between the height and the width of the viewport.
    (source : MDN)

  2. position: absolute and margin: auto; for the centering

DEMO (resize both window height and width to see it in action)

Features :

  • keeps it's aspect ratio according to width and height
  • stays centered in viewport horizontaly and verticaly
  • never overflows the viewport

Browser support :

vmin units are supported by IE10+ (canIuse) for IE9 support, you need to use a fallback with vm units instead of vmin like this :

width: 100vm; /* <-- for IE9 */
height: 100vm; /* <-- for IE9 */
width: 100vmin; 
height: 100vmin;

Full code:

body {
  margin:0; /* To prevent scrollbars */
}

div{
  /* Aspect ratio */
  height:100vm; width:100vm; /* IE9 fallback */
  width: 100vmin; 
  height: 100vmin;
  /*Centering */
  position: absolute;
  top:0;bottom:0;
  left:0;right:0;
  margin: auto;
  /* styling */
  background: gold;
}
<div>whatever content you wish</div>