skip to Main Content

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

2

Answers


  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.

    Login or Signup to reply.
  2. 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search