How is average character width calculated Code Answer

Hello Developer, Hope you guys are doing great. Today at Tutorial Guruji Official website, we are sharing the answer of How is average character width calculated without wasting too much if your time.

The question is published on by Tutorial Guruji team.

According to the HTML specification, The cols attribute specifies the expected maximum number of characters per line.

This is true when the font used has the same width for every character.

According to w3schools, The cols attribute pecifies the width of the text area (in average character width).

My guess is that they mean the font’s average character width and not the average character width of the text in the textarea.

Now my question is how does the user agent calculate the average character width for a certain font, what characters are included in this calculation, … Is there a way I can get this information or calculate it myself?

What I want to do: calculate the visual number of lines inside a textarea witheout using anything else except the textContent and the cols attribute.

What I already tried:

  • Calculate the average character width of the textContent:

const textSpan = document.getElementById("textSpan");
const textarea = document.getElementById("textarea");

textarea.addEventListener("input", (evt) => {
  textSpan.innerText = evt.target.value;
  console.log("Predicted number of lines: " + (textSpan.getBoundingClientRect().width / (textSpan.getBoundingClientRect().width / textSpan.innerText.length * 10))) // 10 = cols attribute of textarea element;
});
<textarea id="textarea" cols="10" rows="10" style="word-break: break-all;"></textarea>
<span id="textSpan"></span>
  • Calculate the average character width of most characters, this may work but I have to know what characters to use for the calculation…:

const textSpan = document.getElementById("textSpan");
const textSpanACW = document.getElementById("textSpanACW");
const textarea = document.getElementById("textarea");

textarea.addEventListener("input", (evt) => {
  textSpan.innerText = evt.target.value;
  console.log("Predicted number of lines: " + (textSpan.getBoundingClientRect().width / (textSpanACW.getBoundingClientRect().width / textSpanACW.innerText.length * 10))) // 10 = cols attribute of textarea element;
});
<textarea id="textarea" cols="10" rows="10" style="word-break: break-all;"></textarea>
<span id="textSpanACW">abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ,;?.:/=+ù%µ£^¨$*-_)àç!è§('"é&|@#¼½^{[{}</span>
<span id="textSpan"></span>

Once I have figured this out I have to get the number of visual lines without using word-break: break-all;. So that would be nice to have in the answer but not needed.

Answer

Reading further in the HTML specification: The textarea effective width of a textarea element is size×avg + sbw, where size is the element’s character width, avg is the average character width of the primary font of the element, in CSS pixels, and sbw is the width of a scroll bar, in CSS pixels. (The element’s letter-spacing property does not affect the result.).

So the formula for calculating average character width (avg) is: (effectiveWidth - sbw) / size.

Getting sbw:

<style>
    /* way the hell off screen */
    .scrollbar-measure {
        width: 100px;
        height: 100px;
        overflow: scroll;
        position: absolute;
        top: -9999px;
    }
</style>
<script>
    const sbw = getScrollbarWidth();

    function getScrollbarWidth() {
        let scrollDiv = document.createElement("div");
        scrollDiv.className = "scrollbar-measure";
        document.body.appendChild(scrollDiv);
        const scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
        document.body.removeChild(scrollDiv);
        return scrollbarWidth;
    }

</script>

Getting size:

In the HTML specification: The cols attribute specifies the expected maximum number of characters per line. If the cols attribute is specified, its value must be a valid non-negative integer greater than zero. If applying the rules for parsing non-negative integers to the attribute’s value results in a number greater than zero, then the element’s character width is that value; otherwise, it is 20.

So:

let size = parseInt(textarea.getAttribute("cols"));

if (isNaN(size)) {
    size = 20;
}

Getting effective width:

If the element has a cols attribute, and parsing that attribute’s value using the rules for parsing non-negative integers doesn’t generate an error, then the user agent is expected to use the attribute as a presentational hint for the width property on the element, with the value being the textarea effective width (as defined below). Otherwise, the user agent is expected to act as if it had a user-agent-level style sheet rule setting the width property on the element to the textarea effective width.

So:

const effectiveWidth = parseFloat(getComputedStyle(textarea).getPropertyValue("width").slice(0, -2));
We are here to answer your question about How is average character width calculated - If you find the proper solution, please don't forgot to share this with your team members.

Related Posts

Tutorial Guruji