The web is a fluid place. Different sized screens, yadda yadda yadda. Fortunately for us, the web is ready for it. Text wraps. CSS gives us control over how to size things. What we don’t get (easily, anyway) is a way to scale whole element (and it’s children) proportionally—retaining its exact layout as it changes size.
We can do it though.
Proportional scaling of a *container* is fairly easy
.parent {
height: 0;
padding-bottom: 56.25%; /* 16:9 */
position: relative;
}
Then if you want content inside, you can absolutely position a covering container inside:
.child {
position: absolute;
top: 0; left: 0;
width: 100%; height: 100%;
}
This can be quite useful for things like images, containers that can independently scroll, or containers with so much spare room that it can handle dramatic changes in shape.
If the content of this container was, say, an image, it works great!

But things aren’t so happy if there are a bunch of HTML element children just doing what regular ol HTML elements do.

Proportional scaling of everything
Let’s say this is the kind of thing we’re after:

CSS alone can’t really do this. But CSS is still the answer! transform: scale();
is what we need. It scales things perfectly proportionally. We just need to give it a number to scale it by, and that scale we can figure out with some JavaScript.
The trick is:
var scale = Math.min(
availableWidth / contentWidth,
availableHeight / contentHeight
);
Here’s one possible approach to that, using jQuery and jQuery UI Resizeable (because that’s easy and comfortable for me):
See the Pen Resize with Scale by Chris Coyier (@chriscoyier) on CodePen.
Other ways…
SVG does this all by itself. Let’s cover this in an article really soon. I have some things to say. ;)
Also, you may be able to size everything with vw/vh units maybe, but that sounds like a pain in the butt and a whole lot of magic numbers.
It’s probably a bit rare that you’d need this
The reason I’m all into this idea is because I noticed that embeddeddable slide decks from Slides.com work like this.
@chriscoyier Thanks! Content scales proportionally but the background size is flexible to fill 100% of avail space. pic.twitter.com/1CybHUBdoS
— Slides (@slides) November 18, 2015
That’s a perfect use case. Slides.com gives you a fixed size canvas to create your slides on, which completley makes sense. Then those slides can scale up if needed, to present in a larger space. Or scale down to fit on smaller screens (like if you embed them into a blog post with a narrow content column or view on a mobile device).
I think about Embedded Pens as well. Sometimes people design Pens to work in a larger area, and the design breaks down when it’s embedded. I could use this to proportionally resize the guts, but only as much as needed to fit.
Maybe iframes? Probably mostly third-party or user-generated stuff, and in situations where the proportion matters, otherwise, carry on with regular RWD action.
I’ve worked with REMux (https://css-tricks.com/remux-an-experimental-approach-to-responsive-web-design/). And it does the job. But, like you said, it requires Magic Numbers, specially if you want text to continue to be readable within certain screen widths. Check it out in action at https://labdoor.com
It’s possible to get some
max-width
/-height
on with this, but that requires something like 4 wrapper<div>
s, since there’s no such thing asmax-padding
.Twitter uses a stretched
<canvas>
to achieve this effect, but that requires some gunk in your HTML and explodes when JS is off. (<canvas>
acts like a reverse<noscript>
.)It’s possible to do it in pure CSS using pseudo-elements and inlined SVG, but it’s kind of a mess. I wonder if it would be more popular with a Sass mixin readymade…
@Kun I suspect the answer for you is “Use SVG”
I’ve personally used a pure CSS method, viewport units (and
calc()
and a bit of Sass) for keeping my HTML slides and everything on them proportional. I like the viewport units method because I’ve found it to be pretty flexible, all I have to do is change the values of the arguments passed to the mixin for a different aspect ratio. All dimensions for anything on the slide are either set in viewport units or inem
and the basefont-size
is also set in viewport units – a pretty random value set to just be a certain part of the smallest dimension. I never gave it much thought to because I never have that much stuff on just one slide anyway, so for slides it works in most cases and, most importantly, in all of the relevant ones, the situations where it breaks are way too extreme (nothing is legible anymore anyway at that size).I agree with @Ana — a viewport unit/SASS (or LESS)/CSS calc() combination is what I like to do here because it leaves out the JS factor (JS, though, would have to be used when supporting browsers without .
If the “magic number” issue above has to do with margins/paddings/border-widths of container objects that would effect the calculations, putting all those values in SASS/LESS variables and then putting them into the calc() statement has done the trick for me.
The only issues I have found with older Android browsers that have an issue with multiply and divide inside a calc statement, but a lot of time this can be handle by calculating all the constant values (i.e. the margins/padding/border-widths) in SASS/LESS. Of course, there is IE8 issues with support, but luckily most of us don’t have to worry about that anymore.
This is something we have to do on a daily basis with animated “responsive” HTML banners that have to scale proportionally and – hold on to your pants – are not embedded in iframes, but inlined with JS.
That kinda sorta rules out viewport units which would make everything less painful…
The JS+scale method is easy to use (Adobe Edge Animate uses that for responsive banners) BUT if you use transforms for your animations, especially rotate and scale and then scale the parent container you’ll end up with a ton of rendering issues in webkit (different on desktop mobile safari and chrome mind you) – blur, pixelation etc – the usual stuff.
I experimented with a method of using some JS to set the size of parent containers and using % for EVERYTHING. Like, seriously, not using px or other units at all. This way you can avoid using transforms on parent containers, so you do away with a lot of webkit rendering related pain, but there are a a lot of drawbacks. CSS is more difficult to write, you have to use some extra rectangular containers/wrappers, but it renders and scales wonderfully.
Will post a pen soon.
:)
Yeap, the ratio padding trick it’s really useful if you want to display an embedded video.
As far for scaling everything i am using svg as well :p (html in foreignObject). Works great if you want to scale font size to parent div (something that’s not possible with css alone).
Glad to see you’re finally catching on to this! Yes SVG can do this way better, but until the substandard WebKit rendering engine is upgraded to handle UHD capabilities, and supports SVG, Apple and Android tablets, which are cheap consumer grade OS systems, can not be used.
For an example of using SVG to do this exact thing with minimal CSS and no Javascript computations see: http://svgdesign.guru
Wow.
I’ve had to so some simple text-with-image scaling before and ended up using a viewport-based equation with calc to pull it off. Seemed crazy at first and then I kind of got used to it. Now I pretty much use it for really awkward transitions (like 650-960) and let smaller and larger be more fixed.
Here’s a pen with the mixinn I used: http://codepen.io/dsongman/full/VvWzdP
I’ve used this for ads on the web. We have only two types of ads: mobile and desktop, so on tablets I scale down the desktop ads to fit the screen. (The iframes are fixed width and height).
I’ve used similar, though more complicated, technique for popup content, e.g. youtube-video: http://codepen.io/anon/pen/epwrNQ It keeps original aspect ratio of the element and resizes it based on aspect ratio of the window.
To avoid unnecessary cropping on sizes below 1366px I used same technique on background images within grid accordion on this site: http://varegg.no/ (For best performance please use Firefox on Windows .)
The CSS unit em, solves this issue. Using it means you can scale the element and everything inside it using font-size on the parent.
We worked on REMux and it does the job we will soon apply this on real time at our website http://helpbase.in/ . But, like what you mansion here it may required because if you want text to continue to be readable within certain screen width.
Thank You
Regards Jiya
Can anyone share an example of major enterprise level site using any of these concepts or similar? Would love to see if there are any real world applications out there.