1

How do you make font size automatically adjust so that the text doesn't overflow?

const h1 = document.getElementsByTagName('h1')[0];
const content = document.getElementById('content');
let size = parseInt(window.getComputedStyle(h1).getPropertyValue('font-size'));
while (checkIfOverflows(h1, content)){
    size--;
    h1.style.fontSize = size + 'px';
}

function checkIfOverflows(element, parent){
    const oldWidth = element.style.width;
    element.style.width = 'fit-content';
    const parentRect = parent.getBoundingClientRect();
    const elementRect = element.getBoundingClientRect();
    const overflows = (parentRect.right - elementRect.right < 0);
    element.style.width = oldWidth;
    console.log(overflows);
    return overflows;
}

The h1 has a stable left edge and nowrap, checkIfOverflows works when checking once, but not in this loop, where if it overflows at first it loops forever, meaning it's most likely a timing thing or some other weird stuff like that

3
  • Keep in mind that a user-agent could force minimum font size you won't be able to go below. Scaling font size to fit content is generally a bad idea. Commented Jun 1, 2024 at 22:17
  • Does stackoverflow.com/questions/21055840/… answer your question? Commented Jun 1, 2024 at 22:19
  • Please include a runnable snippet that shows the problem. In particular the relevant HTML. Are you certain element.style.width is set? Commented Jun 2, 2024 at 4:52

2 Answers 2

0

You can create a virtual ruler that measures text width, like this...

function GetTextWidth(Str,Font,Size){

let Ruler=document.createElement('div');

Ruler.style.cssText='visibility:hidden;position:absolute;top:0;left:0;wdth:auto;height:auto;padding:0;margin:0;font:normal 400 '+Size+'px "'+Font+'";';

Ruler.textContent=Str;

document.body.appendChild(Ruler);

let Width=Ruler.offsetWidth;

Ruler.remove();

return Width;

}

NB: If you're gonna be doing a lot of measuring then you might want to not remove the ruler from the document so you'll have to modify this function a bit.

Also, it’s probably tempting to use display:none and maybe modify some other CSS properties of the ruler, but keep in mind that doing so may render it useless.

ie: Firefox doesn’t consider a container to exist when display:none so be careful with any changes.

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

Comments

-1

It looks like the issue is related to the dynamic nature of the DOM and the way CSS properties are being updated. A possible solution is to use a combination of requestAnimationFrame and a more robust check for overflow. Here's how you can modify your code to achieve this:

  • Use requestAnimationFrame to ensure the style changes are properly rendered before checking for overflow again.
  • Simplify the checkIfOverflows function.

Here is the updated code:

javascript

const h1 = document.getElementsByTagName('h1')[0];
const content = document.getElementById('content');
let size = parseInt(window.getComputedStyle(h1).getPropertyValue('font-size'));

// Use a function to resize the text
function adjustFontSize() {
    if (checkIfOverflows(h1, content)) {
        size--;
        h1.style.fontSize = size + 'px';
        // Use requestAnimationFrame to ensure the style changes are rendered before the next check
        requestAnimationFrame(adjustFontSize);
    }
}

function checkIfOverflows(element, parent) {
    const parentRect = parent.getBoundingClientRect();
    const elementRect = element.getBoundingClientRect();
    return elementRect.right > parentRect.right;
}

// Start the adjustment process
adjustFontSize();

Explanation:

  • requestAnimationFrame: This function is used to make sure that the font size adjustment happens in sync with the browser's repaint cycle. It schedules the adjustFontSize function to run before the next repaint, ensuring that all style changes are rendered before the next iteration of the loop.

  • checkIfOverflows: This function calculates the bounding rectangles of the element and its parent to check if the element's right edge exceeds the parent's right edge.

Steps to ensure the code works correctly:

  • Initial Font Size: Ensure that the initial font size of the h1 element is set large enough that it might overflow. This way, the adjustFontSize function has a chance to reduce the font size if necessary.

  • CSS Properties: Ensure that the h1 element's white-space property is set to nowrap if you want to prevent the text from wrapping.

Here's a simple CSS example to ensure the h1 does not wrap:

css

h1 {
    white-space: nowrap;
}

With these adjustments, your font size should decrease incrementally until it fits within the parent container without overflowing.

1 Comment

If you are going to get an AI service to help its a good idea to run the code it produces to ensure it answers the question as set. Then you can include it as a runnable snippet which strengthens your answer.

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.