简体   繁体   中英

Javascript: How can I get a browser's minimum font size?

What is the best way to get a browser's minimum font size? I whipped up the following code, which does a binary search. It works, but I would like to know if there is a standard or more efficient method.

function getMinimumFontSize() {
  var el = document.createElement('div');
  document.body.appendChild(el);
  el.innerHTML = "<div><p>a b c d e f g h i j k l m n o p q r s t u v w x y z</p></div>";
  el.style.fontSize = '1px';
  el.style.width = '64px';
  var minimumHeight = el.offsetHeight;
  var least = 0;
  var most = 64;
  var middle; 
  for (var i = 0; i < 32; ++i) {
    middle = (least + most)/2;
    el.style.fontSize = middle + 'px';
    if (e.offsetHeight === minimumHeight) {
      least = middle;
    } else {
      most = middle;
    }
  }
  return middle;
}

Just setting the style and reading it back does not work, because it will return the setting rather than what the browser is actually using.

I need the minimum font size so that I can dynamically re-size content to keep everything on one page, without scrolling. That is hard to do if the browser ignores my font size changes because I have gone below the minimum. So for that situation, I will shrink other content instead, such as graphics.

I did it this way:

var ta = document.createElement('textarea');
ta.style.display = 'none';
ta.style.fontSize = '6px'; // I think this is the smallest possible, if not put smaller value
document.body.appendChild(ta); // needs to be part of DOM to be able to calculate
var minimumFontSize = window.getComputedStyle(ta, null).getPropertyValue('font-size'); // returns '20px' for me when I set minimum font size to 20px

EDIT: this doesn't work on firefox, so I created a new, slightly different method:

var ta = document.createElement('div');
ta.style.fontSize = '6px';
ta.style.lineHeight = '1';
ta.innerHTML = 'a';
document.body.appendChild(ta);
var minimumFontSize = ta.clientHeight;

6 years later, and a minimum font-size of zero is allowed in both Chrome and Firefox. This is my basic approach, similar to the first example in the first answer here:

element.style.fontSize = 0;
let actualMinSize = getComputedStyle(element).fontSize;

You must strip the "px" off the computed result to get a number, and the element must be displayed, but it can be off screen via position:absolute; This seems to work in both Chrome and Firefox now, so there is no need for the clientHeight workaround AFAICT.

Earlier this year, in Chrome 73, there was an issue with root em space sizing and the minimum font size setting in Chrome. Since then, Chrome changed their minimum font-size policy and user interface. They now support a zero minimum value, as does Firefox.

My app has a user-sizable window that scrolls text vertically, and the width of the element is set indirectly via the font-size, so that a wider element equals a bigger font size. If a user tries to size the window below the configured min font size, I need to handle that as a minimum element width.

Though I can set the font-size to zero for an element, font sizes below 3px are problematic because the smaller the font size, the less proportional it is to the text width, among other reasons I haven't fully debugged yet. At a certain point, a requested 1px reduction in width allows me to change the font size, but the <div> clientWidth freezes: changing the font-size has no effect on the width. A 2px reduction is OK, because the change is bigger, or so it seems. I can set the style.width to the desired value in the Watch pane in the debugger, and that gets me out of an endless loop.

The strangest part is that I can cause this problem at different font sizes/widths, there is no precise tipping point. It's more of a range in which small changes are problematic. It might be a Chrome bug, but sizes below 3px seem unlikely to me anyway. I might enforce my own minimum of 3px in this element, to simply sidestep these problems.

My problem occurs in the following browsers: QQBrowser *¹ and Sogou Explorer *².

If you insert or change any element to a font below 9px it ignores and keeps the 9px.

Maybe my problem is a little different from the ones mentioned, but I solved it with this polyfill:

// get-min-visible-font-size.js v1
function getMinVisibleFontSize() {
    var spanFS = document.createElement('span');
    spanFS.setAttribute('style', 'font-size:1px!important;display:none!important;');
    document.body.appendChild(spanFS);
    var minFontSize = parseInt(getComputedStyle(spanFS).fontSize);
    document.body.removeChild(spanFS);
    return minFontSize;
};

I chose to return an integer value because it makes testing later easier:

if( getMinVisibleFontSize() > 6){
    [...]
};

But all returned values ​​are actually in pixels.

How it works : simply spam it with font-size = 1px, add it to the body and check the font-size size. If it's larger than 1px then you're in a browser that limits the minimum font size (9px OR 12px in these cases). It is important that the value is not zero because if you check zero in all cases the text disappears and you get zero even in these browsers.

It may be that in the future there is some CSS to define min-font-size as well as min-width, so I put the function name as minVisibleFontSize.

Works on IE-11 but I didn't do it for old browsers...

¹ = QQBrowser v10.8.3, based on Chromium 70.0.3538.25. (9px) ² = Sogou Explorer v11.0.1.34700, based on Chromium 80.0.3987.87 I think because it's in userAgent. (12px)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM