Aaron
Aaron

Reputation: 541

How to Auto-Resize a DIV with CSS while keeping Aspect Ratio?

What I have is a standard form in HTML that allows the user to select a "Width" option and a "Height" option (each with values ranging from 1 to 10). When they send the form, it sends it to a PHP/HTML page where PHP grabs the "Width" and "Height" variables and assigns it to a width and height of a DIV.

But what I'm trying to do is just use the "Width" and "Height" variables to assign an aspect ratio to that DIV, and then have that DIV auto-resize to 100% of the container it is inside, but while keeping that same aspect ratio.

Example: User selects a Width of 4 and a Height of 2, then sends the form. On the receiving PHP page, that DIV (the one receiving the width and height ratios) is inside a container that's 1000px width and 600px height. So now, that DIV resizes to 1000px wide and 500px tall (that would be the aspect ratio of 4 to 2)

Any ideas, codes, scripts would be extremely helpful, thank you very much!

Aaron

Upvotes: 7

Views: 15325

Answers (2)

Oriol
Oriol

Reputation: 288650

You could take advantage of the fact that replaces elements may have an intrinsic aspect ratio. According to the spec,

Otherwise, if 'height' has a computed value of 'auto', and the element has an intrinsic ratio then the used value of 'height' is:

(used width) / (intrinsic ratio)

Therefore, you could

  • Create a replaced element with the desired intrinsic ratio, and then set width:100% to it.
  • Use absolutely positioning to remove all contents from the normal flow of the element, in order to prevent them from increasing the height. Then, make it grow to fill the container.

Then, the container container will have the aspect ratio that you want.

The replaced element could be an image. You could create images of the desired aspect ratio in PHP, or using a third party web service like http://placehold.it/

In the following snippet, I use a 2px width and 1px height image (enter image description here):

.container {
  border: 3px solid blue;
  position: relative;
}
.container > img {
  width: 100%;
  display: block;
  visibility: hidden;
}
.container > .content {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  overflow: auto;
}
<div class="container">
  <img src="https://i.sstatic.net/Lfmr6.png" />
  <div class="content">
    <p>01</p><p>02</p><p>03</p><p>04</p><p>05</p>
    <p>06</p><p>07</p><p>08</p><p>09</p><p>10</p>
    <p>11</p><p>12</p><p>13</p><p>14</p><p>15</p>
    <p>16</p><p>17</p><p>18</p><p>19</p><p>20</p>
  </div>
</div>

You can also use a <canvas> element instead of an image. This way you don't need to create images, but it doesn't work on old browsers (like IE 8 and earlier):

<div class="container">
  <canvas height="1" width="2"></canvas>
  <div class="content">...</div>
</div>

.container {
  border: 3px solid blue;
  position: relative;
}
.container > canvas {
  width: 100%;
  display: block;
  visibility: hidden;
}
.container > .content {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  overflow: auto;
}
<div class="container">
  <canvas height="1" width="2"></canvas>
  <div class="content">
    <p>01</p><p>02</p><p>03</p><p>04</p><p>05</p>
    <p>06</p><p>07</p><p>08</p><p>09</p><p>10</p>
    <p>11</p><p>12</p><p>13</p><p>14</p><p>15</p>
    <p>16</p><p>17</p><p>18</p><p>19</p><p>20</p>
  </div>
</div>

Upvotes: 1

Oriol
Oriol

Reputation: 288650

Since percentage values of the padding-* properties are calculated with respect to the width of the generated box's containing block, you could:

  • Add a dummy element with no content but with a percentage in a vertical padding (padding-top or padding-bottom), corresponding to the desired aspect ratio.
  • Use absolutely positioning to remove all contents from the normal flow of the element, in order to prevent them from increasing the height. Then, make it grow to fill the container.

This idea is taken from http://ansciath.tumblr.com/post/7347495869/css-aspect-ratio

#container {
  position: relative;
  width: 50%;
}
#dummy {
  padding-top: 75%; /* 4:3 aspect ratio */
}
#element {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  background-color: silver;
}
<div id="container">
  <div id="dummy"></div>
  <div id="element">
    some text
  </div>
</div>

Note vertical margin could be used instead of vertical padding, but then there would be margin collapse. To prevent it, add

#container {
  display: inline-block;
}

#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;
}
<div id="container">
  <div id="dummy"></div>
  <div id="element">
    some text
  </div>
</div>

Using ::before pseudo element, there's no need to use a dummy element:

#container:before {
  padding-top: 75%; /* 4:3 aspect ratio */
  content: ''; /* Enable the pseudo-element */
  display: block;    
}

#container {
  position: relative;
  width: 50%;
}
#container:before {
  padding-top: 75%; /* 4:3 aspect ratio */
  content: ''; /* Enable the pseudo-element */
  display: block;    
}
#element {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  background-color: silver;
}
<div id="container">
  <div id="element">
    some text
  </div>
</div>

Upvotes: 8

Related Questions