CSS: make div width proportional to height

2019-01-22 07:12发布

问题:

This is a little tricky to explain, but: I want a responsive-height div (height: 100%) that will scale the width proportional to the height (not vice versa).

I know of this method utilising a padding-top hack to make the height proportional to the width, but I need it to work the other way around. Having said that, I'm not hugely keen on the additional requirement of absolutely-positioned elements for the content in that method, so I realise I may well be asking for the moon on a stick here.

To help visualise, here is an image:

...and here is a jsFiddle, illustrating pretty much the same thing.

It is worth noting that I am already using the :before and :after pseudo-elements to vertically-align the content of the box I want to scale proportionally.

I would really, really enjoy not having to revert to jQuery, just because there's going to be an inherent requirement for resize handlers and generally more debugging all round... but if that's my only choice, then fiat.

回答1:

I've been wondering about a pure-css solution to this problem for a while. I finally came up with a solution using ems, which can be progressively enhanced using vws:

See codepen link for full working demo and explanation:

http://codepen.io/patrickkunka/pen/yxugb

Simplified version:

.parent {
  font-size: 250px; // height of container
  height: 1em;
}

.child {
  height: 100%;
  width: 1em; // 100% of height
}


回答2:

Oh,you could probably use that "padding-top" trick.

width: 50%;
height: 0;
padding-bottom: 50%;

http://absolide.tumblr.com/post/7317210512/full-css-fluid-squares

Or:

.square-box{
    position: relative;
    width: 50%;
    overflow: hidden;
    background: #4679BD;
}
.square-box:before{
    content: "";
    display: block;
    padding-top: 100%;
}

http://codeitdown.com/css-square-rectangle/

The vertical padding in CSS is related to the width of the element, not the height.



回答3:

The font solution requires that the height is known. I have found a solution for making an element proportional inside a parent div with unknown widths and heights. Here is a demo.

The trick I'm using is to have an image used as a spacer. The code explained:

<div class="heightLimit">
 <img width="2048" height="2048" class="spacer"
  src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAA
       P///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7">
 <div class="filler">
  <div class="proportional">
  </div>
 </div>
</div>

So it is not the prettiest with two extra divs and a useless image. But it could be worse. The image element needs to have width and height with the desired dimensions. Width and height need to be as large as the maximum size allowed (a feature!).

The css:

.heightLimit {
 position: absolute;
 top: 0;
 left: 0;
 height: 100%;
 width: auto;
 max-width: 100%;
 overflow: hidden;
}

This element is to limit the height, but to expand horizontally (width: auto) although never beyond the parent (max-width). Overflow needs to be hidden because some children will protrude outside the div.

.spacer {
 width: auto;
 max-height: 100%;
 visibility: hidden;
}

This image is invisible and scaled proportionally to the height, while the width is adjusted and forces the width of the parent to also be adjusted.

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

This element is required to fill the space with an absolutely positioned container.

.proportional {
 position: relative;
 width: 100%;
 height: 0;
 padding-bottom: 100%;
}

And here our proportional element gets a height proportional to the width with the familiar padding-bottom trick.

Unfortunately, there is a bug in Chrome and IE so if you modify the parent element using Javascript, such as in my demo, the dimensions will not be updated. There is a hack that can be applied to solve that, as shown in my demo.



回答4:

Based off of @kunkalabs's answer (which is really smart) I've come up with a solution that lets you preserve the inherited font-size.

HTML:

<div id='rect'>
    <div id='content'>Text</div>
</div>

CSS:

#rect {
    font-size: 1000%;
    height: 1em;
    width: 1em;
    position: relative;
}

#content {
    font-size: 10%;
}

So basically the font-size of #content is (100 / $rectFontSize) * 100 percent of the rectangle. If you need a definite pixel size for the rectangle, you can set the #rect's parent's font-size…otherwise just adjust the font-size until it's about where you want it to be (and enrage your designer in the process).



回答5:

You can use view height (vh) as the unity for the width.

Here is an example with the 20px margin you asked for.

 .parent {
   margin : 20px;
}
.child {
   width: calc(100vh - 40px);
   height : calc(100vh - 40px);
   margin:0 auto;
   background: red;
   box-sizing:border-box;
   padding:10px;
}

See the fiddle : https://jsfiddle.net/svobczp4/



回答6:

Make the parent DIV behave like a table cell and align the child element vertically. No need to do any padding tricks.

HTML

<div class="parent">
<img src="foo.jpg" />
</div>

CSS

.parent { width:300px; height:300px; display:table-cell; vertical-align:middle; }