# Adjust text size based on length of text

**URL:** <https://discourse.processing.org/t/adjust-text-size-based-on-length-of-text/32411>\
**Category:** Coding Questions\
**Created:** [September 25, 2021, 5:47pm UTC](https://discourse.processing.org/t/adjust-text-size-based-on-length-of-text/32411 "2021-09-25T17:47:57Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Naison](https://avatars.discourse-cdn.com/v4/letter/n/3be4f8/32.png) [@Naison](https://discourse.processing.org/u/Naison)\
**Post date:** [September 25, 2021, 5:47pm UTC](https://discourse.processing.org/t/adjust-text-size-based-on-length-of-text/32411/1 "2021-09-25T17:47:57Z")

</div>

Hello,

I am coding a game and for this, I tryna write code that sizes the text based on the length of the text. My goal is to scale the text (the bigger the text width / the longer the text, the smaller the text size) that every time the whole string can be seen on the screen.

I’ve written this code so far:

```auto
float t = 75;
String s = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. "; //this is only an exapmle for a long string
textSize(t);
println(t);
float w = textWidth(s);

t = sq(w)/sq(s.length());

println(t, w, s.length());

size(1200, 600);
textSize(t);
textAlign(CENTER);
text(s, 0, 0, width, height);

```

But as you can see, my goal isn’t fulfilled…  
Can you guys please help me?

Greetings

---

<div class="post-metadata">

**Author:** ![rapatski](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/rapatski/32/5164_2.png) [@rapatski](https://discourse.processing.org/u/rapatski)\
**Post date:** [September 25, 2021, 9:51pm UTC](https://discourse.processing.org/t/adjust-text-size-based-on-length-of-text/32411/2 "2021-09-25T21:51:29Z")

</div>

Hey man, nice job. It certainly looks like you’re mixing up some of the static/dynamic mode type stuff… Let’s just start by putting things nicely in a setup function etc.

Also looks like you’re complicating stuff. Try this?

```auto
PFont font;

float currentSize = 75;
String currentText = "Lorem Ipsum.";

void setup()
{
  size(1200, 600);
  
  font = createFont("Times", currentSize);
  textFont(font);
}

void draw()
{
  float currentWidth = textWidth(currentText);
  
  float targetWidth = 1000; // what width to we want the text to be?
  float ratio = targetWidth / currentWidth; // so how much bigger should the text be?
  currentSize *= ratio; // let's make it exactly that big
  
  background(0);
  
  textSize(currentSize);
  textAlign(CENTER, CENTER);
  text(currentText, 0, 0, width, height);
}

void keyReleased()
{
  currentText += str(key);
}

```

---

<div class="post-metadata">

**Author:** ![glv](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/glv/32/18785_2.png) [@glv](https://discourse.processing.org/u/glv)\
**Post date:** [September 26, 2021, 10:16am UTC](https://discourse.processing.org/t/adjust-text-size-based-on-length-of-text/32411/3 "2021-09-26T10:16:00Z")

</div>

Hello,

There are lots of resources (tutorials, examples, references, etc.) here:

> **[Welcome to Processing!](https://processing.org/)**
>
> Processing is a flexible software sketchbook and a language for learning how to code within the context of the visual arts. Since 2001, Processing has promoted software literacy within the visual arts…

Example to play with:

```auto
// https://discourse.processing.org/t/adjust-text-size-based-on-length-of-text/32411

float t = 1; //Start with a height of 1 pixel
String s = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. "; //this is only an exapmle for a long string
int lines = 1;

s = s+s; // Double the length of the text
//s = s+s+s;

textSize(t);
println(t);
float w = textWidth(s);

float k = 1; // k can be the ratio of two variables
                     // k set to 1 initially so it is not zero 
//k = s.length()/s; // One possible ratio   
//k = 200/w; // Another ratio using width of text box (below)
//lines = 1;
//t = t*k*lines; // Sames as 1*k*lines for t=1 initially

println(k, t, w, s.length());

size(600, 400);

textAlign(CENTER);
fill(0);

// Left text box
k = s.length()/w; // One possible ratio   
lines = 5; // A factor to increase size 
t = 1*k*lines;
println(k, lines, t);

textSize(t);
text(s, 50, 50, 200, 300); //text box
noFill();
rect(50, 50, 200, 300); //rect() showing text box borders

//Right text box
k = 200/w; // One possible ratio textBoxWidth/w  
lines = 5; // A factor to increase size
t = 1*k*lines;  
println(k, lines, t);

textSize(t);
text(s, 350, 50, 200, 300);

```

![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/7/7209fffce1437afaa20b9d3e7aafa310ba3f58e4.png)

References:

> **[Proportionality (mathematics)](https://en.wikipedia.org/wiki/Proportionality_(mathematics))**
>
> In mathematics, two varying quantities are said to be in a relation of proportionality, 
> multiplicatively connected to a constant; that is, when either their ratio or their product yields a constant. The value of this constant is called the coefficient of proportionality or proportionality constant.
> If several pairs of variables share the same direct proportionality constant, the equation expressing the equality of these ratios is called a proportion, e.g., a/b = x/y = ⋯ = k (for details see Rat...

> **[Welcome to Processing!](https://processing.org/)**
>
> Processing is a flexible software sketchbook and a language for learning how to code within the context of the visual arts. Since 2001, Processing has promoted software literacy within the visual arts…

`:)`

---

<div class="post-metadata">

**Author:** ![Naison](https://avatars.discourse-cdn.com/v4/letter/n/3be4f8/32.png) [@Naison](https://discourse.processing.org/u/Naison)\
**Post date:** [September 26, 2021, 6:05pm UTC](https://discourse.processing.org/t/adjust-text-size-based-on-length-of-text/32411/4 "2021-09-26T18:05:12Z")

</div>

Thanks for your solution @rapatski .  
But now I want to create a half-transparent rectangle which “covers” the text like this:

 ![Screenshot 2021-09-26 200250](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/1/1415b8709b57cd85b7036e88977f121a12f2ea27.png)

The height of the rectangle has to be (y-size) as big as the text is for covering the background and gaining better visibility. Any ideas on how I can get this?

---

<div class="post-metadata">

**Author:** ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)\
**Post date:** [September 26, 2021, 8:16pm UTC](https://discourse.processing.org/t/adjust-text-size-based-on-length-of-text/32411/5 "2021-09-26T20:16:08Z")

</div>

It looks like you want a combination of dynamic line wrapping and shrink-to-fit – is that correct?

Because `text()` does not detect overflow (it just silently fails to display it)

> Text that does not fit completely within the rectangle specified will not be drawn to the screen.

one of the ways to do your own fitting is to do your own layout – if the layout is going to exceed the bounds, reduce the size and try again. Repeat until the layout fits, then draw.

Past forum discussions with examples of doing your own text layout:

- [How to make a String of any length fit within text box? - Processing 2.x and 3.x Forum](https://forum.processing.org/two/discussion/comment/53903/#Comment_53903)
- [Is it possible to set multiple colours within a single function? - Processing 2.x and 3.x Forum](https://forum.processing.org/two/discussion/comment/87679/#Comment_87679)

However this is **advanced**! If you are a new learner, I really don’t suggest trying this.

### Paging, not shrinking:

Instead, consider focusing on limiting your text data and paging with a next button. That is much, much easier to do – check if the String is longer than x characters, and if it is longer, split the string and let the user click to display the second part (or third, et cetera) on a new page.

This also has the advantage of making the text more readable, as the font size isn’t jumping around and long paragraphs don’t become overly tiny.

---

<div class="post-metadata">

**Author:** ![rapatski](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/rapatski/32/5164_2.png) [@rapatski](https://discourse.processing.org/u/rapatski)\
**Post date:** [September 26, 2021, 8:52pm UTC](https://discourse.processing.org/t/adjust-text-size-based-on-length-of-text/32411/6 "2021-09-26T20:52:13Z")

</div>

> The height of the rectangle has to be (y-size) as big as the text is for covering the background and gaining better visibility. Any ideas on how I can get this?

Uh… by drawing a half transparent box that is the height (size) of the text? Like, you already have this information?

---

<div class="post-metadata">

**Author:** ![Naison](https://avatars.discourse-cdn.com/v4/letter/n/3be4f8/32.png) [@Naison](https://discourse.processing.org/u/Naison)\
**Post date:** [September 27, 2021, 3:32pm UTC](https://discourse.processing.org/t/adjust-text-size-based-on-length-of-text/32411/7 "2021-09-27T15:32:04Z")

</div>

Thanks for your help! I created my own version of this, but it doesn’t work perfectly at all, especially when the string is very short…

Here is my code now:

```auto
String str ="Lorem ipsum.";
int x = 0;
int y = 0;
int w = 400;
int h = 250;

String[] words;
float currentSize = 5;
float bestSize = 5;
float sizeIncrement = 0.5;
float fac;

void setup() {
  fullScreen();
  background(20);
  fill(255);
  
  words = str.split(" ");

  w = width;
  h = height/3;
  
  boolean searching = true;  
  while (searching) {
    if (testFontSize(currentSize)) {
      bestSize = currentSize;
      currentSize += sizeIncrement;
    } else {
      searching = false;
    }
  }
  println("Best size: "+ bestSize);
  
  fac = ceil(textWidth(str)/width);
  h = int(fac*(bestSize*1.5));
 
  textSize(bestSize);
  fill(0);
  textAlign(CENTER);
  text(str, x, y, w, h);
  noStroke();
  fill(150, 150);
  rect(x, y, w, h, 0, 0, 30, 30);
}

void draw() {
  background(20);
    words = str.split(" ");

  w = width;
  h = height/3;
  
  boolean searching = true;  
  while (searching) {
    if (testFontSize(currentSize)) {
      bestSize = currentSize;
      currentSize += sizeIncrement;
    } else {
      searching = false;
    }
  }
  println("Best size: "+ bestSize);
  
  fac = ceil(textWidth(str)/width);
  h = int(fac*(bestSize*1.5));
 
  textSize(bestSize);
  fill(255);
  textAlign(CENTER);
  text(str, x, y, w, h);
  noStroke();
  fill(0, 50);
  rect(x, y, w, h, 0, 0, 30, 30);
}

boolean testFontSize(float s) {
  textSize(s);
  int currentLine = 1;
  int maxLines = floor( h / g.textLeading);
  boolean fitHeight = true;
  int nextWord = 0;

  while (fitHeight) {
    if (currentLine > maxLines) {
      fitHeight = false;
    } else {
      String temp = words[nextWord];
      if (textWidth(temp)>w)
        return false;

      boolean fitWidth = true;
      while (fitWidth) {

        if (textWidth(temp) > w) {
          currentLine++;
          fitWidth = false;
        } else {
          if (nextWord < words.length -1) {
            nextWord++;
            temp += " "+words[nextWord];
          } else
            return true;
        }
      }
    }
  }

  return false;
} 

void keyReleased() {
  str+= key;
}

```

As you guys can see, it doesn’t adjust the size. Can someone solve my problem?

---

<div class="post-metadata">

**Author:** ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)\
**Post date:** [September 28, 2021, 2:29am UTC](https://discourse.processing.org/t/adjust-text-size-based-on-length-of-text/32411/8 "2021-09-28T02:29:31Z")

</div>

Your code is definitely on the right track. Getting a good approximation without just reusing Processing’s own code (which is also an option!) can be an extremely fiddly problem because it may rely on specifics of how Processing line leading works with defaults / magic values.

Try this:

```auto
// Default leading value matches Processing default text behavior for the default Font.
boolean isTextOverflow(String txt, float x, float y, float w, float h, float tsize) {
  return isTextOverflow(txt, x, y, w, h, tsize, tsize * 0.525);
}
/**
 * Will the text fit in the box at the given text size?
 * @param txt text string to fit
 * @param x x coordinate of text box
 * @param y y coordinate of text box
 * @param w width of text box
 * @param h height of text box
 * @param tsize text size to test for string fit
 * @param leading vertical space between lines in px
 * @return true if text will overflow
 */
boolean isTextOverflow(String txt, float x, float y, float w, float h, float tsize, float leading) {
  String[] words;
  float xoffset = x;
  float yoffset = y + tsize;
  pushStyle();
  textSize(tsize);
  float spacing = textWidth(" ");
  textLeading(leading);
  words = split(txt, " ");
  // loop through words, move to next line if a word won't fit
  for (String word : words) {
    if (xoffset + textWidth(word) > x + w) {
      xoffset = x;
      yoffset = yoffset + tsize + leading;
      // stopping printing lines beyond the bottom of the box
      if (yoffset > y + h - tsize - leading) {
        popStyle();
        return true;
      }
    }
    ////preview layouts
    //fill(220);
    //text(word, xoffset, yoffset);

    xoffset = xoffset + spacing + textWidth(word);
  }
  popStyle();
  return false;
}

```

Now, if you want to call it like text(), wrap your `while()` loop in another function.

```auto
/**
 * Display text fit into the box -- if needed, shrink textSize repeatedly until it fits.
 * Does not display if text shrinks to textSize(2) without fitting.
 * @param txt text string to fit
 * @param x x coordinate of text box
 * @param y y coordinate of text box
 * @param w width of text box
 * @param h height of text box
 * @param maxTextSize maximum text size to fit
 */
void textFit(String txt, float x, float y, float w, float h, float maxTextSize) {
  float tsize = maxTextSize;
  while(tsize > 2 && isTextOverflow(txt, x, y, w, h, tsize)) {
    tsize--;
  }
  if(tsize>2) {
    println(tsize);
    pushStyle();
    textSize(tsize);
    text(txt, x, y, w, h);
    popStyle();
  }
}

```

Now you can just call textFit()! For example, here is a sketch that prints some lorem ipsum text into the full window.

```auto
String txt = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. FIN.";

void setup() {
  size(600, 600);
  stroke(0);
  surface.setResizable(true);
}

void draw() {
  background(255);
  fill(0);
  textFit(txt, 0, 0, width, height, 60);
}

```

The window is resizeable, so drag the corner around and watch the text reflow into the window!

---

<div class="post-metadata">

**Author:** ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)\
**Post date:** [September 28, 2021, 2:41am UTC](https://discourse.processing.org/t/adjust-text-size-based-on-length-of-text/32411/9 "2021-09-28T02:41:44Z")

</div>

To be clear, this is a solution for:

> [@Naison](#):
>
> code that sizes the text based on the length of the text

not:

> [@Naison](#):
>
> create a half-transparent rectangle which “covers” the text

For that second solution, one way is to try making an altered copy of your overflow detector

```auto
boolean isTextOverflow(String txt, float x, float y, float w, float h, float tsize, float leading)

```

…and instead of returning true / false, returns a value textHeight:

```auto
float textHeight(String txt, float x, float y, float w, float h, float tsize, float leading) {
  // ...
}

```

Note that this works much like `isTextOverflow`, and returns the total height for the full text block when laid out – it is _not_ the visible height of a single line. @micycle has a great explainer thread on precisely calculating [visible line height](https://discourse.processing.org/t/a-more-accurate-approach-to-calculating-text-width-text-height/24879).
