45

It is made of 9 boxes, with the middle on has text it in. I've made it so the boxes so they will resize with the screen resize so it will remain in the same place all the time.

The text, however, doesn't resize - even when I use percentage.

  1. How do I resize the text so it will always be the same ratio from the entire page?
  2. Is this a proper solution to handle multiple resolutions? or should I have many @media checks in the CSS and have many layouts for each media types?

html,
body {
  height: 100%;
  width: 100%;
}

#launchmain {
  width: 55%;
  display: inline-block;
  position: relative;
  top: 10%;
  left: 25%;
}

#launchmain:after {
  padding-top: 79.26%;
  display: block;
  content: '';
  margin-top: 10px;
}

#box1 {
  border: 1px solid #000000;
  position: absolute;
  width: 25.37%;
  height: 21.88%
}

#box2 {
  border: 1px solid #000000;
  width: 48.48%;
  height: 21.88%;
  position: absolute;
  left: 25.64%
}

#box3 {
  border: 1px solid #000000;
  width: 25.37%;
  height: 21.88%;
  position: absolute;
  left: 74.39%;
}

#box4 {
  border: 1px solid #000000;
  width: 33.235%;
  height: 53.84%;
  position: absolute;
  top: 22.07%;
}

#maininvite {
  border: 1px solid #000000;
  width: 33.53%;
  height: 53.84%;
  position: absolute;
  top: 22.07%;
  left: 33.235%;
}

#box6 {
  border: 1px solid #000000;
  width: 33.235%;
  height: 53.84%;
  position: absolute;
  top: 22.07%;
  left: 66.765%;
}

#box7 {
  border: 1px solid #000000;
  width: 25.37%;
  height: 21.88%;
  position: absolute;
  top: 76.2%;
}

#box8 {
  border: 1px solid #000000;
  width: 48.48%;
  height: 21.88%;
  position: absolute;
  left: 25.64%;
  top: 76.2%;
}

#box9 {
  border: 1px solid #000000;
  width: 25.37%;
  height: 21.88%;
  position: absolute;
  top: 76.2%;
  left: 74.39%;
}

#maininvite h2 {
  font-size: 180%;
}

p {
  position: relative;
  font-size: 80%;
}
<div id="launchmain">
  <div id="box1"></div>
  <div id="box2"></div>
  <div id="box3"></div>
  <div id="box4"></div>
  <div id="maininvite">
    <h2> header</h2>
    <p>not a lot of text here but still overflowing</p>
  </div>
  <div id="box6"></div>
  <div id="box7"></div>
  <div id="box8"></div>
  <div id="box9"></div>
</div>
Penny Liu
  • 15,447
  • 5
  • 79
  • 98
Nick Ginanto
  • 31,090
  • 47
  • 134
  • 244
  • 4
    Your text size will not adjust by using a percentage, it will remain constant. This is not a percentage of it's container div, it is a percentage of the text size that is set in the container. – Luke Nov 13 '12 at 09:26
  • 1
    Its not possible with just CSS. You would need to use Javascript. Have a look at this, I know it keeps the text on 1 line in the following question but it should get you on the right lines http://stackoverflow.com/questions/3401136/resize-font-to-fit-in-a-div-on-one-line – Adam Nov 13 '12 at 09:27

6 Answers6

75

My answer does not require Javascript and only relies on CSS3 (available in most modern browsers). I personally like it very much if design is not relying on Javascript too much.

My answer is a "pure CSS3 , no Javascript required"-solution:

The solution as can be seen here (http://jsfiddle.net/uNF3Z/16/) uses the following additions to the CSS styles (which make use of the @media query of CSS3 which)

@media all and (min-width: 50px)   {  body  { font-size:0.1em;  } }
@media all and (min-width: 100px)  {  body  { font-size:0.2em;  } }
@media all and (min-width: 200px)  {  body  { font-size:0.4em;  } }
@media all and (min-width: 300px)  {  body  { font-size:0.6em;  } }
@media all and (min-width: 400px)  {  body  { font-size:0.8em;  } }
@media all and (min-width: 500px)  {  body  { font-size:1.0em;  } }
@media all and (min-width: 600px)  {  body  { font-size:1.2em;  } }
@media all and (min-width: 700px)  {  body  { font-size:1.4em;  } }
@media all and (min-width: 800px)  {  body  { font-size:1.6em;  } }
@media all and (min-width: 900px)  {  body  { font-size:1.8em;  } }
@media all and (min-width: 1000px) {  body  { font-size:2.0em;  } }
@media all and (min-width: 1100px) {  body  { font-size:2.2em;  } }
@media all and (min-width: 1200px) {  body  { font-size:2.4em;  } }
@media all and (min-width: 1300px) {  body  { font-size:2.6em;  } }
@media all and (min-width: 1400px) {  body  { font-size:2.8em;  } }
@media all and (min-width: 1500px) {  body  { font-size:3.0em;  } }
@media all and (min-width: 1500px) {  body  { font-size:3.2em;  } }
@media all and (min-width: 1600px) {  body  { font-size:3.4em;  } }
@media all and (min-width: 1700px) {  body  { font-size:3.6em;  } }

What this in effect causes is that the font-size is adjusted to the available screen width. This adjustment is done in steps of 100px (which is finegrained enough for most purposes) and covers a maximum screen width of 1700px which I reckon to be amply (2013) and can by adding further lines be further improved.

A side benefit is that the adjustment of the font-size is occuring at each resize. This dynamic adjustment (because for instance the browser windows is resized) might not yet be covered by the Javascript based solution.

humanityANDpeace
  • 4,350
  • 3
  • 37
  • 63
  • Interesting approach, I agree it's ugly but it works a treat for my requirements. Thank you. – Jonathan Apr 03 '14 at 08:09
  • Added a LESS version of this to my answer - makes it a little more pretty : ) – Patrick Apr 05 '14 at 04:02
  • 7
    If you are resizing based on window width and not on the container div size as this case addresses using 'vw' units would be much easier. – Evan Cordeiro Apr 19 '14 at 20:55
  • I tweaked your code to use min-height rather than min-width, so that the height of the DIVs is (somewhat) proportional to the height of the font. – alfadog67 May 30 '14 at 17:55
  • I love the thought, but the text is totally unreadable under a certain width. – Costa Michailidis Jul 10 '15 at 19:12
  • As per the other comments, I really don't want to like this - but it does the job. And, arguably, it does a lot more efficiently. –  Mar 08 '16 at 13:17
  • 3
    Breaks zoom behaviour and thus cannot be used if you care for accessibility. – lowtechsun Apr 23 '17 at 16:23
  • This was the solution I ultimately went with to a good degree of success. I like it because sometimes we work so hard to be lazy, but this was the easiest solution and most compatible with my needs. Zoom works fine for me with it. – Altimus Prime Jun 11 '21 at 04:05
43

I was looking for the same funcionality and found this answer. However, I wanted to give you guys a quick update. It's CSS3's vmin unit.

p, li
{
  font-size: 1.2vmin;
}

vmin means 'whichever is smaller between the 1% of the ViewPort's height and the 1% of the ViewPort's width'.

More info on SitePoint

ffflabs
  • 17,166
  • 5
  • 51
  • 77
  • 3
    Whilst this is the nicest answer, it's definitely worth noting the [lack of browser support](http://caniuse.com/viewport-units) – Ian Clark Jun 25 '14 at 10:14
  • This doesn't really solve the issue at hand though. But combined with calc() function it could prove quite useful. The browser support nowadays is pretty good, if all you care about is "modern" users, you're pretty much covered. – niieani Nov 20 '14 at 01:14
  • Why do you say it doesn't solve the issue? It should resize the font according to the viewport size. – ffflabs Nov 20 '14 at 01:37
  • Do you know how works the vmin in safari and opera browsers? – user2301515 Dec 02 '15 at 08:03
  • 1
    Well, just a quick update: except for Opera Mini, it works in every browser by now – ffflabs Oct 05 '18 at 11:49
  • As of 2019, `vmin` is now [supported by all major browsers](https://caniuse.com/#feat=viewport-units). It's worth noting that IE doesn't support `vmax`. – Robin Métral Jan 24 '19 at 12:52
29

In regards to your code, see @Coulton. You'll need to use JavaScript.

Checkout either FitText (it does work in IE, they just ballsed their site somehow) or BigText.

FitText will allow you to scale some text in relation to the container it is in, while BigText is more about resizing different sections of text to be the same width within the container.

BigText will set your string to exactly the width of the container, whereas FitText is less pixel perfect. It starts by setting the font-size at 1/10th of the container element's width. It doesn't work very well with all fonts by default, but it has a setting which allows you to decrease or increase the 'power' of the re-size. It also allows you to set a min and max font-size. It will take a bit of fiddling to get working the first time, but does work great.

http://marabeas.io <- playing with it currently here. As far as I understand, BigText wouldn't work in my context at all.

For those of you using Angularjs, here's an Angular version of FitText I've made.


Here's a LESS mixin you can use to make @humanityANDpeace's solution a little more pretty:

@mqIterations: 19;
.fontResize(@i) when (@i > 0) {
    @media all and (min-width: 100px * @i) { body { font-size:0.2em * @i; } }
    .fontResize((@i - 1));
}
.fontResize(@mqIterations);

And an SCSS version thanks to @NIXin!

$mqIterations: 19;
@mixin fontResize($iterations) { 
    $i: 1; 
    @while $i <= $iterations { 
        @media all and (min-width: 100px * $i) { body { font-size:0.2em * $i; } } 
        $i: $i + 1; 
    }
} 
@include fontResize($mqIterations);
Patrick
  • 3,490
  • 1
  • 37
  • 64
  • 4
    I think that "You'll need to use JavaScript", plus your snippet at the end, implies that if you wanted to provide a CSS-only solution as well, it should be a separate answer. – Ian Clark Jun 25 '14 at 09:45
  • 1
    Here's a SCSS version of your mixin: `$mqIterations: 19; @mixin fontResize($iterations) { $i: 1; @while $i <= $iterations { @media all and (min-width: 100px * $i) { body { font-size:0.2em * $i; } } $i: $i + 1; } } @include fontResize($mqIterations);` – niieani Nov 20 '14 at 01:09
15

The answer that i am presenting is very simple, instead of using px, em or %, I'll use vw. In short it might look like this:

   h1 {font-size: 5.9vw;}

when used for heading purposes.

See this: Demo

For more details: Main tutorial

MeSo2
  • 450
  • 1
  • 7
  • 18
Abhishek Sen
  • 338
  • 4
  • 10
  • Can you fix your formatting and maybe add a little more explanation to this please? – khelwood Dec 03 '14 at 19:11
  • 2
    One unit of vw is 1% of the viewport axis. "Viewport" == browser window size == window object. If the viewport is 40cm wide, 1vw == 0.4cm. – Abhishek Sen Dec 03 '14 at 19:35
  • 2
    for example just changed "font-size: 80%" to "font-size: 2.5vw" , [jsfiddle](http://jsfiddle.net/abhisheksen/ojx19s9r/) – Abhishek Sen Dec 03 '14 at 19:51
6

Here's a SCSS version of @Patrick's mixin.

$mqIterations: 19;
@mixin fontResize($iterations)
{
  $i: 1;
  @while $i <= $iterations
  {
    @media all and (min-width: 100px * $i) {
      body { font-size:0.2em * $i; }
    }
    $i: $i + 1;
  }
}
@include fontResize($mqIterations);
niieani
  • 4,101
  • 1
  • 31
  • 22
0

I found a way of resizing font size according to div size, without any JavaScript. I don't know how much efficient it's, but it nicely gets the job done.

Embed a SVG element inside the required div, and then use a foreignObject tag inside which you can use HTML elements. A sample code snippet that got my job done is given below.

<!-- The SVG element given below should be place inside required div tag -->
<svg viewBox='0 2 108.5 29' xmlns='http://www.w3.org/2000/svg'>
    <!-- The below tag allows adding HTML elements inside SVG tag -->
    <foreignObject x='5' y='0' width='93.5%' height='100%'>
        <!-- The below tag can be styled using CSS classes or style attributes -->
        <div xmlns='http://www.w3.org/1999/xhtml' style='text-overflow: ellipsis; overflow: hidden; white-space: nowrap;'>
            Required text goes here            
        </div>
    </foreignObject>
</svg>

All the viewBox, x, y, width and height values can be changed according to requirement.

Text can be defined inside the SVG element itself, but when the text overflows, ellipsis can't be added to SVG text. So, HTML element(s) are defined inside a foreignObject element, and text-overflow styles are added to that/those element(s).