2

I'm wondering if there is a CSS-only solution to make contents scale to fit their container, be they images or text, like so:

.container {
    display: inline-block;
    width: 2in;
    height: 1in;
    font-size: fit-to-container /* <- what should this be? */
}

<div class="container">Some Text</div>
<div class="container">Another container with significantly 
more content, and so the font should scale down to fit</div>

Alternatively, with images:

.container {
    display: inline-block;
    width: 2in;
    height: 1in;
    overflow: resize-to-fit /* <- not really, overflow can't do it */
}

<div class="container">
 <img src="one.png"/>
</div>

<div class="container">
 <img src="one.png"/>
 <img src="two.png"/>
 <img src="three.png"/>
 <img src="four.png"/>
 <img src="five.png"/>
 <img src="six.png"/>
 <img src="seven.png"/>
 <img src="eight.png"/>
</div>

As a visual example, see https://jsfiddle.net/jarrowwx/jemxLqyL/94/. But that fiddle doesn't exactly pull it off perfectly, and it was overly complicated to create. It uses SVG because I was experimenting with just making the contents as a single image and then setting max-width, but that didn't work, either, it just cropped the image.

Is there is a pure CSS solution to create this effect?

John Arrowwood
  • 2,370
  • 2
  • 21
  • 32
  • Yes, it is possible. And the best way would be to use [flexboxes](https://css-tricks.com/snippets/css/a-guide-to-flexbox/). – pol Nov 20 '16 at 16:04
  • Here is an updated fiddle: https://jsfiddle.net/jarrowwx/jemxLqyL/148/ - the flex box doesn't appear to be able to auto-shrink the images. It seems to shrink the boxes around content, but not shrink the content itself. If I'm missing something, please tell me what I missed. – John Arrowwood Nov 22 '16 at 15:03
  • 1
    [Here's something](http://stackoverflow.com/questions/30788131/css3-flexbox-maintain-image) to help you with the image height:width ratio problem . One answer in particular, came very simple, you will only need to add `object-fit: contain;`, but it only works on Firefox 36+, chrome 31+ and opera 11.6+ with `-o-object-fit: contain;`. [Take a look](https://jsfiddle.net/jemxLqyL/150/). Ofcourse you could look for a fallback. [This one uses](http://stackoverflow.com/questions/33473978/alternate-option-object-fit) the `background` property (`background-size: contain` in your case), to do the trick. – pol Nov 23 '16 at 19:27

1 Answers1

1

I'm wondering if there is a CSS-only solution to make contents scale to fit their container

Short answer:

No.

Longer answer:

You can scale a font-size:

  • relative to the viewport (using vw, vh, vmax and vmin)
  • relative to the font size of the current element (using em or %)
  • relative to the font size of the root element (using rem)

You can also scale a font-size relative to its parent element, if the parent element in question is also sized relative to the viewport.

eg. if the stylesheet reads:

p {
width: 20vw;
font-size: 2vw;
}

then the width of the p will always be 20% of the viewport width and the font-size of the p will always be 2% of the viewport width... so the font-size of the p will always be 10% of the width of the p.

You can also (self-evidently) scale the font-size relative to a fixed width parent:

eg. if the stylesheet reads:

p {
width: 200px;
font-size: 20px;
}

then the font-size of the p will always be 10% of the width of the p.

But there is no unit which enables the font-size of a fixed-width element to be inversely proportional to the amount of text present in the element.

That's not to say you can't build a javascript-based solution of course...

So, here is a quick script which decreases the font-size of a div as the textual content of that div increases:

var containers = document.getElementsByClassName('container');

for (var i = 0; i < containers.length; i++) {
var text = containers[i].textContent;

var calculatedFontSize;

switch (true) {
case (text.length < 10) : calculatedFontSize = 50; break;
case (text.length < 20) : calculatedFontSize = 40; break;
case (text.length < 30) : calculatedFontSize = 30; break;
case (text.length < 40) : calculatedFontSize = 24; break;
case (text.length < 50) : calculatedFontSize = 22; break;
case (text.length < 60) : calculatedFontSize = 21; break;
case (text.length < 70) : calculatedFontSize = 20; break;
case (text.length < 80) : calculatedFontSize = 19; break;
case (text.length < 90) : calculatedFontSize = 18; break;
case (text.length < 100) : calculatedFontSize = 17; break;
case (text.length < 110) : calculatedFontSize = 16; break;
case (text.length < 120) : calculatedFontSize = 15; break;
case (text.length < 130) : calculatedFontSize = 14; break;
default : calculatedFontSize = 12; break;
}

containers[i].style.fontSize = calculatedFontSize + 'px';
}
.container {
position: relative;
display: inline-block;
width: 2in;
height: 1in;
margin: 0 6px 6px 0;
background-color: rgb(191,191,191);
vertical-align: top;
}
<div class="container">
Some Text.
</div>

<div class="container">
A little more text.
</div>

<div class="container">
Considerably more text, now something like the size of a sentence.
</div>

<div class="container">
Another container with significantly more content, and so the font should scale down to fit.
</div>

<div class="container">
A fifth container with a very much larger amount of content, which inevitably ends up creating a much longer sentence.
</div>
Rounin
  • 27,134
  • 9
  • 83
  • 108