1
votes

I need to scale the height of divs.

How it should work

  • The divs should scale, keep current aspect ratio
  • The width should be 100px always
  • The height should scale in propotion to the 100px width
  • I added some example width and height in the code
  • Add more HTML + CSS if needed

Example

A div block is originally 300px x 600px. When fit the width of 100px it will be 100px x 200px.

The result

The result will be divs equally wide but they will be different height, some taller than others.

https://jsfiddle.net/80pk066L/5/

Notes

If it whould be an image it would contain aspect ratio when setting width to 100%, but this is not an image. It is a div.

HTML

<ul>
    <li class="scale1"><div></div></li>
    <li class="scale2"><div></div></li>
    <li class="scale3"><div></div></li>
    <li class="scale4"><div></div></li>
    <li class="scale5"><div></div></li>
</ul>

CSS

ul {
    width: 300px;
}

li {
    float: left;
    background: red;
    margin: 10px;
    list-style: none;
    display: block;
    height: 100px;
    width: 100px;
    /*REMOVE HEIGHT AND WIDTH HERE, JUST DECORATION
    Width should always be 100px
    Height should be whatever, can be larger than 100px
    */
}

.scale1 div {
    width: 300px;
    height: 500px;
}

.scale2 div {
    width: 400px;
    height: 400px;
}

.scale3 div {
    width: 200px;
    height: 300px;
}

.scale4 div {
    width: 50px;
    height: 60px;
}

.scale5 div {
    width: 150px;
    height: 75px;
}
3
Each li forms a 100px square, and has a child div of a certain aspect ratio, and you want the child div to fit in the li? - Marc Audet
For one, you should remove "div" in your scale definitions - it is implied by the dot. I'm not sure what you mean by scale... if you want height of 200 and width of 100, why not set that? - steve klein
@MarcAudet No, I should probably edit my question. A div can be 100x200, 100x40 but NEVER like 200x100 or 300x500. Width should always be 100px. Height can be whatever. - Jens Törnell
So just don't set a width for your divs, then, nor a height for your list items. - Shaggy
then remove height from li will give you the desired output right? - Aru

3 Answers

2
votes

You can use a bottom padding trick to force a responsive aspect ratio on each individual element. You'll have to calculate the padding-bottom manually of each element, as a percentage of the height to width ratio.

.scale1 div {
    padding-bottom: 166.667%;
}

.scale2 div {
    padding-bottom: 100%;
}

.scale3 div {
    padding-bottom: 150%;
}

.scale4 div {
    padding-bottom: 120%;
}

.scale5 div {
    padding-bottom: 50%;
}

See fiddle here: https://jsfiddle.net/teddyrised/80pk066L/9/

If you want content in each element, though, they have to be wrapped within an absolutely positioned child element — that is because if they are not taken out of the document flow, the content height will add on to the bottom padding, therefore skewing the aspect ratio:

li div {
    position: relative;
}
li div span {
    position: absolute;
    padding: 10px;
    top: 0; 
    left: 0;
    bottom: 0;
    right: 0;
}

https://jsfiddle.net/teddyrised/80pk066L/10/

If using CSS to specify the aspect ratio is too tedious, you can programatically do this using JS. I understand that you might not want to achieve this using JS, but this might be more efficient if you have large number of elements you want to go through. For convenience's sake, I am using jQuery—but any other libraries or even raw JS would work, as long as the same logic is applied:

$(function() {
    $('ul li').each(function() {
        $(this).children('div').css('padding-bottom', $(this).width()/parseFloat($(this).data('aspect-ratio')));
    });
});

I have chosen to store the aspect ratio (in the form of width-to-height) in a HTML5 data- attribute:

<ul>
    <li class="scale1" data-aspect-ratio="0.6"><div><span>1</span></div></li>
    <li class="scale2" data-aspect-ratio="1"><div><span>2</span></div></li>
    <li class="scale3" data-aspect-ratio="0.667"><div><span>3</span></div></li>
    <li class="scale4" data-aspect-ratio="0.833"><div><span>4</span></div></li>
    <li class="scale5" data-aspect-ratio="2"><div><span>5</span></div></li>
</ul>

See proof-of-concept example here: https://jsfiddle.net/teddyrised/80pk066L/11/

1
votes

Instead of specifying exact widths and heights for the divs, use a combination of max-width and padding-bottom to achieve this. I've also taken the liberty of converting your layout from using floats to using flexbox instead to save the hassle of having to clear the floats.

*{box-sizing:border-box;}
ul{
    display:flex;
    flex-flow:row wrap;
    list-style:none;
    margin:0;
    padding:0;
    width:100%;
}
li{
    background:green;
	flex:1 1 calc(33.333% - 20px);
    margin:10px;
    display:block;
    max-width:calc(33.333% - 20px);
}
div{
    background:red;
}
.scale1 div{
    padding:0 0 166.667%;
    max-width:300px;
}

.scale2 div{
    padding:0 0 100%;
    max-width:400px;
}

.scale3 div{
    padding:0 0 150%;
    max-width:200px;
}
.scale4 div{
    padding:0 0 120%;
    max-width:50px;
}
.scale5 div{
    padding:0 0 50%;
    max-width:150px;
}
<ul>
    <li class="scale1"><div></div></li>
    <li class="scale2"><div></div></li>
    <li class="scale3"><div></div></li>
    <li class="scale4"><div></div></li>
    <li class="scale5"><div></div></li>
</ul>
0
votes

You can achieve this using image placeholders: (fiddle if code snippet doesn't work)

ul {
    width: 300px;
}
li {
    float: left;
    background: red;
    margin: 10px;
    list-style: none;
    display: block;
    position:relative;
    width:100px;
}
li img {
    position: relative;
    visibility: hidden; /* make sure it's hidden */
    width: 100%;
    min-width: 100%;
}
li div {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    overflow:hidden;
}
/*.scale1 div {
    width: 300px;
    height: 500px;
}
.scale2 div {
    width: 400px;
    height: 400px;
}
.scale3 div {
    width: 200px;
    height: 300px;
}
.scale4 div {
    width: 50px;
    height: 60px;
}
.scale5 div {
    width: 150px;
    height: 75px;
}*/
<ul>
    <li class="scale1">
        <div></div>
        <img src="http://placehold.it/300x500" alt="" />
    </li>
    <li class="scale2">
        <div></div>
        <img src="http://placehold.it/400x400" alt="" />
    </li>
    <li class="scale3">
        <div></div>
        <img src="http://placehold.it/200x300" alt="" />
    </li>
    <li class="scale4">
        <div></div>
        <img src="http://placehold.it/50x60" alt="" />
    </li>
    <li class="scale5">
        <div></div>
        <img src="http://placehold.it/150x75" alt="" />
    </li>
</ul>
<!-- - The divs should scale - The width of the div should be max 100px - The height should scale to what fit max 100px width - Remove li height and width. They are just for decoration -->