Height equal to dynamic width (CSS fluid layout) [duplicate]
Asked Answered
H

9

619

Is it possible to set same height as width (ratio 1:1)?

Example

+----------+
| body     |
| 1:3      |
|          |
| +------+ |
| | div  | |
| | 1:1  | |
| +------+ |
|          |
|          |
|          |
|          |
|          |
+----------+

CSS

div {
  width: 80%;
  height: same-as-width
}
Hodson answered 26/3, 2011 at 21:35 Comment(1)
After Nathan's solution, there is a solution by ❝Kristijan❞ that is even more simpler. Without dummy-elements.Cardioid
A
83

Using jQuery you can achieve this by doing

var cw = $('.child').width();
$('.child').css({'height':cw+'px'});

Check working example at http://jsfiddle.net/n6DAu/1/

Apogeotropism answered 26/3, 2011 at 21:46 Comment(0)
R
795

[Update: Although I discovered this trick independently, I’ve since learned that Thierry Koblentz beat me to it. You can find his 2009 article on A List Apart. Credit where credit is due.]

I know this is an old question, but I encountered a similar problem that I did solve only with CSS. Here is my blog post that discusses the solution. Included in the post is a live example. Code is reposted below.

#container {
  display: inline-block;
  position: relative;
  width: 50%;
}

#dummy {
  margin-top: 75%;
  /* 4:3 aspect ratio */
}

#element {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  background-color: silver/* show me! */
}
<div id="container">
  <div id="dummy"></div>
  <div id="element">
    some text
  </div>
</div>
Rattigan answered 7/7, 2011 at 19:28 Comment(4)
It works because margin/padding-top/bottom, when specified as a percentage, is determined according to the width of the containing element. Essentially, you have a situation where "vertical" properties can be sized with respect to a "horizontal" property. This isn't an exploit or a hack, because this is how the CSS specification is defined.Rattigan
This can be improved by using the :before pseudo-element. #container:before{content:"";display:block;margin-top:100%;}Keller
Here's a fiddle for the pseudo-element solution: jsfiddle.net/B8FU8/2441Cornered
☹️ when used with an image it cuts the excess like overflow:hidden.Copolymerize
A
549

There is a way using CSS!

If you set your width depending on the parent container you can set the height to 0 and set padding-bottom to the percentage which will be calculated depending on the current width:

.some_element {
    position: relative;
    width: 20%;
    height: 0;
    padding-bottom: 20%;
}

This works well in all major browsers.

JSFiddle: https://jsfiddle.net/ayb9nzj3/

Aryan answered 29/11, 2012 at 12:28 Comment(1)
If you put a child div into in, and set its height to 100% of the parent's height, its height will be 0.Preliminary
A
318

Best method now : the aspect-ratio property

div {
  aspect-ratio : 1 / 1;
  width:50%;
  border:1px solid red;
}
<div>Aspect ratio : 1 / 1</div>

This is the most simple and flexible solution. It directly specifies a fixed width to height (or height to width) aspect ratio for an element. This means you can also specify an aspect ratio according to the elements height.
It doesn't rely on the parent width (like the padding technique) or the viewport size (like the following vw unit technique) it relies on the element's own width or height More info on MDN. That is what make it so powerfull compared to other workarounds.

This is a modern property (2021). All modern browsers support it, see caniuse for precise browser support.


Other method with vw:

You can use vw units for a responsive height/width according to the viewport width.

vw : 1/100th of the width of the viewport. (Source MDN)

You can also look into vh, vmin and vmax units to se apsect ratio according to other viewport sizes (see here)

div{
    width:20vw;
    height:60vw; /* <-- 3 x width */
    background:gold;
}

div > div{
    width:15vw;
    height:15vw; /* <-- same as width */
    background:red;
}
<div>
  1:3 aspect ratio
  <div>1:1 aspect ratio</div>
</div>

Table to calculate height according to the desired aspect ratio and width of element.

   aspect ratio  |  multiply width by
    -----------------------------------
         1:1      |         1
         1:3      |         3
         4:3      |        0.75
        16:9      |       0.5625

This technique allows you to :

  • insert any content inside the element without using position:absolute;
  • no unecessary HTML markup (only one element)
  • adapt the elements aspect ratio according to the height of the viewport using vh units
  • you can make a responsive square or other aspect ratio that alway fits in viewport according to the height and width of the viewport (see this answer : Responsive square according to width and height of viewport or this demo)

These units are supported by IE9+ see canIuse for more info

Ardell answered 13/5, 2014 at 20:16 Comment(3)
You may als set line-height:0 for small elementsUplift
None of the other solutions worked for me. My case was a img with width 100% on the container along with some other text. Note: doesn't work if you have max-width insteadWiesbaden
Wow! Every day you find a new CSS property and trick. This thing never ends :))))Larynx
M
129

It is possible without any Javascript :)

The HTML:

<div class='box'>
    <div class='content'>Aspect ratio of 1:1</div>
</div> 

The CSS:

.box {
    position: relative;
    width:    50%; /* desired width */
}

.box:before {
    content:     "";
    display:     block;
    padding-top: 100%; /* initial ratio of 1:1*/
}

.content {
    position: absolute;
    top:      0;
    left:     0;
    bottom:   0;
    right:    0;
}

/* Other ratios - just apply the desired class to the "box" element */
.ratio2_1:before{
    padding-top: 50%;
}
.ratio1_2:before{
    padding-top: 200%;
}
.ratio4_3:before{
    padding-top: 75%;
}
.ratio16_9:before{
    padding-top: 56.25%;
}
Micropathology answered 21/11, 2013 at 9:49 Comment(0)
A
83

Using jQuery you can achieve this by doing

var cw = $('.child').width();
$('.child').css({'height':cw+'px'});

Check working example at http://jsfiddle.net/n6DAu/1/

Apogeotropism answered 26/3, 2011 at 21:46 Comment(0)
G
74

Extremely simple method jsfiddle

HTML

<div id="container">
    <div id="element">
        some text
    </div>
</div>

CSS

#container {
    width: 50%; /* desired width */
}

#element {
    height: 0;
    padding-bottom: 100%;
}
Greenstone answered 26/2, 2015 at 23:52 Comment(1)
If you put a child div into in, and set its height to 100% of the parent's height, its height will be 0.Preliminary
L
12

Expanding upon the padding top/bottom technique, it is possible to use a pseudo element to set the height of the element. Use float and negative margins to remove the pseudo element from the flow and view.

This allows you to place content inside the box without using an extra div and/or CSS positioning.

.fixed-ar::before {
  content: "";
  float: left;
  width: 1px;
  margin-left: -1px;
}
.fixed-ar::after {
  content: "";
  display: table;
  clear: both;
}


/* proportions */

.fixed-ar-1-1::before {
  padding-top: 100%;
}
.fixed-ar-4-3::before {
  padding-top: 75%;
}
.fixed-ar-16-9::before {
  padding-top: 56.25%;
}


/* demo */

.fixed-ar {
  margin: 1em 0;
  max-width: 400px;
  background: #EEE url(https://lorempixel.com/800/450/food/5/) center no-repeat;
  background-size: contain;
}
<div class="fixed-ar fixed-ar-1-1">1:1 Aspect Ratio</div>
<div class="fixed-ar fixed-ar-4-3">4:3 Aspect Ratio</div>
<div class="fixed-ar fixed-ar-16-9">16:9 Aspect Ratio</div>
Lousewort answered 26/11, 2014 at 11:4 Comment(0)
N
5

width: 80vmin; height: 80vmin;

CSS does 80% of the smallest view, height or width

http://caniuse.com/#feat=viewport-units

Northbound answered 4/11, 2014 at 6:17 Comment(0)
V
4

really this belongs as a comment to Nathan's answer, but I'm not allowed to do that yet...
I wanted to maintain the aspect ratio, even if there is too much stuff to fit in the box. His example expands the height, changing the aspect ratio. I found adding

overflow: hidden;
overflow-x: auto;
overflow-y: auto;

to the .element helped. See http://jsfiddle.net/B8FU8/3111/

Venerable answered 12/7, 2013 at 15:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.