spiderman
spiderman

Reputation: 1417

Can I scale a div's height proportionally to its width using CSS?

Can I set any variable in CSS like I want my div height to always be half of width my div scales with the screen size width for div is in percent

<div class="ss"></div>

CSS:

.ss {
    width:30%;
    height: half of the width;
}

This 30% width scales with screen resolution

Upvotes: 100

Views: 166597

Answers (11)

Stefan H Singer
Stefan H Singer

Reputation: 5504

You can do it with the help of padding on a parent item, because relative padding (even height-wise) is based on the width of the parent element.

CSS:

.imageContainer {
    position: relative;
    width: 25%;
    padding-bottom: 25%;
    height: 0;
}
 
img {
    width: 100%;
    height: 100%;
    position: absolute;
    left: 0;
}

Upvotes: 138

Pipisasa
Pipisasa

Reputation: 349

use aspect-ratio

.container {
  display: flex;
  align-items: flex-start;
  gap: 10px;
}

.box{
  width: 100px;
  background-color: #000;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
}

.box-1 {
  aspect-ratio: 16/9;
}

.box-2 {
  aspect-ratio: 3/4;
}

.box-3 {
  aspect-ratio: 1/1;
}

.box-4 {
  aspect-ratio: 1/2;
}
<div class="container">
  <div class="box box-1">16/9</div>
  <div class="box box-2">3/4</div>
  <div class="box box-3">1/1</div>
  <div class="box box-4">1/2</div>
</div>

Upvotes: 35

Shahriar
Shahriar

Reputation: 2380

Just found this great article by Ahmad Shadeed, which uses css var and math to do so:

.rect {
      --size: 186px;
      --aspect-ratio: 2.35;
      width: var(--size);
      height: calc(var(--size) / var(--aspect-ratio));
    }

Upvotes: 1

d13
d13

Reputation: 10077

You could assign both the width and height of the element using either vw or vh. For example:

#anyElement {
    width: 20vh;
    height: 20vh;
}

This would set both the width and height to 20% of the browser's current height, retaining the aspect ratio. However, this only works if you want to scale proportionate to the viewport dimensions.

Upvotes: 3

Joe Giusti
Joe Giusti

Reputation: 179

You can use the view width to set the height. 100 vw is 100% of the width. height: 60vw; would make the height 60% of the width.

Upvotes: 3

GDavoli
GDavoli

Reputation: 606

You can use View Width for the "width" and again half of the View Width for the "height". In this way you're guaranteed the correct ratio regardless of the viewport size.

<div class="ss"></div>

.ss
{
    width: 30vw;
    height: 15vw;
}

Fiddle

Upvotes: 17

Skulio
Skulio

Reputation: 21

One way usefull when you work with images, but can be used as workaround otherwise:

<html>
<head>
</head>
<style>
    #someContainer {
        width:50%;
        position: relative;
    }
    #par {
        width: 100%;
        background-color:red;
    }
    #image {
        width: 100%;
        visibility: hidden;
    }
    #myContent {
        position:absolute;
    }
</style>
<div id="someContainer">
    <div id="par">
        <div id="myContent">
            <p>
            Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
            </p>    
        </div>
        <img src="yourImage" id="image"/>
    </div>
</div>
</html>

To use replace yourImage with your image url. You use image with width / height ratio you desire.

div id="myContent" is here as example of workaround where myContent will overlay over image.

This works like: Parent div will adopt to the height of image, image height will adopt to width of parent. However image is hidden.

Upvotes: 2

brubs
brubs

Reputation: 1357

For anyone looking for a scalable solution: I wrote a small helper utility in SASS to generate responsive proportional rectangles for different breakpoints. Take a look at SASS Proportions

Hope it helps anybody!

Upvotes: 3

Lee Gunn
Lee Gunn

Reputation: 8656

This answer is much the same as others except I prefer not to use as many class names. But that's just personal preference. You could argue that using class names on each div is more transparent as declares up front the purpose of the nested divs.

<div id="MyDiv" class="proportional">
  <div>
    <div>
      <p>Content</p>
    </div>
  </div>
</div>

Here's the generic CSS:

.proportional { position:relative; }
.proportional > div > div { position:absolute; top:0px; bottom:0px; left:0px; right:0px; }

Then target the first inner div to set width and height (padding-top):

#MyDiv > div { width:200px; padding-top:50%; }

Upvotes: 3

jdavis
jdavis

Reputation: 8655

Another great way to accomplish this is to use a transparent image with a set aspect ratio. Then set the width of the image to 100% and the height to auto. That unfortunately will push down the original content of the container. So you need to wrap the original content in another div and position it absolutely to the top of the parent div.

<div class="parent">
   <img class="aspect-ratio" src="images/aspect-ratio.png" />
   <div class="content">Content</div>
</div>

CSS

.parent {
  position: relative;
}
.aspect-ratio {
  width: 100%;
  height: auto;
}
.content {
  position: absolute;
  width: 100%;
  top: 0; left: 0;
}

Upvotes: 20

zlovelady
zlovelady

Reputation: 4097

If you want vertical sizing proportional to a width set in pixels on an enclosing div, I believe you need an extra element, like so:

#html

<div class="ptest">
    <div class="ptest-wrap">
        <div class="ptest-inner">
            Put content here
        </div>
    </div>
</div>

#css
.ptest {
  width: 200px;
  position: relative;
}

.ptest-wrap {
    padding-top: 60%;
}
.ptest-inner {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: #333;
}

Here's the 2 div solution that doesn't work. Note the 60% vertical padding is proportional to the window width, not the div.ptest width:

http://jsfiddle.net/d85FM/

Here's the example with the code above, which does work:

http://jsfiddle.net/mmq29/

Upvotes: 6

Related Questions