Responsive HTML Containers That Scale Proportionally
A problem that surfaces every now and again in CSS is the inability to make containers scale responsively while maintaining proportional height to width ratio. Usually these are image containers that live side-by-side with siblings that should be the same dimensions. With images, there are “built-in” dimensions that act as constraints when browsers resize them, but you don’t have that convenience when working with divs. Thanks to an odd little quirk in CSS, however, there is a workaround to make your divs behave like images when resized.
There are a couple of situations where this might come in handy. First, when you have home page callouts and you want to use existing images of varying sizes, instead of cropping and saving three new ones. Another one is if you have containers that have hovers over them that might “swipe” up an overlay animation or the images themselves might do a scale animation within the container. The overflow would have to be hidden in that situation so you’d probably use a parent div.
To get a better idea of what I’m going to be talking about, check out this little demo in a browser where you can scale the window and pay particular attention to the heights of the divs as they scale with the widths, but maintain correct aspect ratio.
CSS Padding Does What? Seriously?
When you add padding to an element as a percentage, the amount calculated is based on the width of the browser window. What’s strange about that is that this is the case no matter to which side you’re adding padding. So if you specify something like, “padding-bottom: 5%;” that 5% is based on the width of the window, and not the height as you might expect. It seems a little counter-intuitive but it does guarantee you have an equal amount of space on all sides (imagine having to write two separate rules for left/right and top/bottom).
First, a Bit of Math
Let’s say you have a set of three divs in your static design layout that are 300px wide by 250px high. To get the height scaling properly, start with base dimensions and figure out the height’s relationship to the width, and to do this you divide 250 by 300. Once again, take a look at the demo for reference.
Height ÷ Width = Ratio
Next, multiply the base height (from our hypothetical mockup) by that ratio. In our example that’s 0.83 (rounded). So, the height of each of our divs is 0.83 of the width, or 83% if we convert to percent by multiplying by 100. Now that you have the height’s relationship to the width you apply it to the div’s relationship to the container. That sounds pretty confusing, so let’s work it through. You want these divs to be fluidly responsive, and you want them to take up a third of the screen (or container div but for the sake of simplicity we’ll use window width). So each div will have a width of 33.33%. All you have to do is apply our ratio to that number and we’ll have fluidly responsive height. In this case, 27.66%.
Width Percentage of Container Width × Ratio = Height Percentage of Container Width
Obviously we normally wouldn’t really care what the div height’s direct relationship is to the window width, but since the div’s width is being calculated by the window width, we do care.
Since the CSS height property uses the window’s height for reference, you can’t just say height: 27.66%. It won’t work and your div’s height and width won’t have any relationship to each other. But thanks to that CSS padding-based-on-window-width quirk, we can apply it to the window’s padding-bottom. To finally see our fluid, responsive, and proportional divs, set the div’s height to zero and padding-bottom to 27.66%. Voila! Your CSS should look something like this:
There are a few things to take note of before wrapping up. Make sure when rounding your numbers that you don’t go over 100% or you’ll get scroll bars. If you want space between your containers, you’ll have to figure their percentages into your calculations. If you want fixed margins, you’ll have to use them as “invisible” parents, adding style to their inner divs and the fixed margins on those. If you want to apply some of the animations to their inner divs like those mentioned above, just set their overflow to hidden. Finally, if you want additional padding or borders, make sure you set box-sizing to “border-box.” In addition to the demo, take a look at the portfolio thumbnails on the VisionSpark home page to see a real-world example of this method. Thanks for reading!