19

I have a situation where I have a container element (div) that contains text. This text will sometimes be really large - not paragraph large, but it can potentially exceed the width of the text.

Obviously, in most situations it will just knock parts of the text to the next line, but I wanted to see if calc() can be used on font-size to change the size of the font to make sure it is always fitting within the bounds of the div it is in. Can this be done?

.name { width: 500px; font-size: 64px; }

<span class="name">Sometimes it is short</span>

<span class="name">Sometimes it is going to be really long, and people put long names</span>

I could just limit the number of letters people can use for a name - and to an extent I will, but I am curious to see if this can even be accomplished.

I found this post to do it with Javascript, but that was a long time ago, and I think CSS3 has a lot of new things that may let this be accomplished without any scripting. AutoFill

2
  • This cannot be done in pure CSS. calc() is for generating CSS property values based on different units (i.e. 100% - 400px), not this sort of thing (CSS is presentation layer and it doesn't have any kind of perspective on the text content, nor the widths of individual characters in any given font face). There are an array of easy to use jQuery plugins (fitText among others) that will make this a snap though. Commented Apr 8, 2014 at 18:52
  • 1
    That's not true. It's not possible to detect how much size in pixels will a piece of text take with javascript. fitText is bullshit. It only generates a font-size value between the min and max you provide Commented Apr 8, 2014 at 19:02

8 Answers 8

19

Here a possible solution:

http://codepen.io/CrocoDillon/pen/fBJxu

p {
  margin: 0;
  font-size: calc(4vw + 4vh + 2vmin);
  /* See:
   * http://codepen.io/CrocoDillon/pen/jgmwt
   * For some math behind this
   */
}

Font-size is calculated with available size using a function that is not perfect, but may be adjusted to work well in some cases.

Sign up to request clarification or add additional context in comments.

1 Comment

Similar: font-size: calc(14px + 0.5vw); worked great in my case.
11

Calc is still in it's infancy in terms of support & usefulness. By design it's really just there for doing simple math, like (100% - 20px). It really won't do the math complex enough to make the calculations possible. You are looking for a solution that will size the text based on the amount of space the letters physically take up horizontally (which depends on the letter's individual sizing) and the amount of space available for the containing div.

CSS is abstracted away from the actual element's contents, and it has no way to really discern if something currently "fits" or not. It can layout guidelines for how to handle things when they do or don't fit, but it can't adjust itself according to the content like you want it to. (It's not just you, we've all faced this problem or a similar version of it at some point.)

Check out Chris Coyer's post on what Calc might be handy for: http://css-tricks.com/a-couple-of-use-cases-for-calc/

1 Comment

Thanks, this actually helped me a lot! I learned quite a bit from this post.
4

This can be done in pure css using the vi and vb properties.

https://developer.mozilla.org/en-US/docs/Web/CSS/length

These allow the font-size to be scaled in proportion to the container div's inline (vi) or block (vb) dimensions.

Presently supported on browsers covering ~92% of users (caniuse.com).

e.g.

.name { font-size: 0.5vi;}

5 Comments

This is a good answer but unfortunately not supported by many browsers as of 11/2022: developer.mozilla.org/en-US/docs/Web/CSS/…
@verwirrt thanks, seems that Firefox has added support since April though, have updated answer...
this solution(/idea) looked the best among others when I came here, but turned out it does not work for me. but another unit from the dynamic group cqw does the trick. a big thanks to @Lee for pointing to right direction
no, container queries-based units is definitely for smth other :(
Like most of the suggested solutions, this does not take into account the length of the text, only the size of the container, which is not what the OP asked.
1

Just a clarification:

if you use something like:

font-size: -webkit-calc(100% + 30px);
font-size:        -calc(100% + 30px);

what this does is add 30px to the 100% default font size, it can't be linked to the container width.

Although, you can do math there like:

font-size: -webkit-calc( 100% * 0.09479166667 - 6.666666669px );
font-size:        -calc( 100% * 0.09479166667 - 6.666666669px );

... but it will just calculate it against the 1em.

Comments

1

I met with the same problem. Since no existing answer in this thread can work, I overcame the challenges by using cqw.

cqw is now supported by most browsers as of 2024, except for a few less reputable browsers. https://caniuse.com/mdn-css_types_length_container_query_length_units

So, depending on the requirement, this will make at least 99% of end users happy.

Assume the container has the style --

.container {
  width: 100%;
  position: relative;
}

and the child has position: absolute, you will be able to make both banner re-sizable, AND font-size to change as the width of viewport changes with --

.child {
  position: absolute;
  left: 10%;
  top: 20.4%;  // Use percentage so it positions at relative place
  font-size: 2.35cqw;  
  line-height: 2.75cqw; // yes, it applies to other properties, too!
}

Comments

0

This is still nearly impossible in CSS only, as the size of each character in different fonts isn't known to us via CSS. There is a jQuery plugin called fitText that handles this sort of thing very nicely.

Comments

0

I recommend you to use text ellipsis

.name{
    width: 500px;
    font-size: 64px;
    text-overflow: ellipsis;
    overflow: hidden;
    display: block;
}

and if you need to control font-size, do it by @media in different devices

Comments

0

Set the size of your container using vmin units, like so:


:root {
    --vmin: 1vmin;
    --container-length: calc(50 *var(--vmin));
    --factor: 6; /* Set the value according to the font size you want. */
}

.box {
    text-align: center;
    width: var(--container-length);
    height: var(--container-length); /* For a rectangle, use another variable and set the line height using that. */
    border: calc(var(--vmin)) solid black;
}
.box p {
    font-size: calc(var(--container-width) / var(--factor));
    line-height: 1.75;
}

That's it. Now your text will scale smoothly according to the container dimensions everywhere except on Safari, which has a jittery font scaling issue, but it does work anyway!).

Demo

If you want to learn more about --vmin based intrinsic typography, look at the Toucaan CSS framework that replaces all other CSS units like px, em, vw, rem, cqi, etc. completely.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.