Search code examples
htmlcssfont-size

CSS font-size: Set it for * as multiple of rem and body font-size is multiplied twice


See the console output of the code snippet below. I use a multiplier of 0.5 in the example because it makes the multiplication straightforward and illustrates that it can double-shrink the font-size as well as double-increase it.

I set font-size to 0.5rem using the * universal selector. No other settings. The documentElement font-size is 8px, as I would expect when the default for 1rem at 16px (8 = 16 x 0.5). But the body font-size is 4px, which is 16 x 0.5 x 0.5. Why does this happen?

I realize that the * selector is not always good practice, and if I use the html selector both values are correctly set to 8px here; but then in my actual page the font-size does not inherit to all elements. I'm open to suggestions on the best practice here.

I have tested this in Chrome and Firefox on Windows with the same results.

EDIT: I just discovered that using the combined html * selector I can achieve my desired result: global setting without the double multiplier.

console.log("doc:  " + getComputedStyle(document.documentElement).fontSize);
console.log("body: " + getComputedStyle(document.body).fontSize);
* { font-size: 0.5rem; }


Solution

  • According to here:

    rem stands for root em, which is a measurement unit that refers to the font-size of the root element of a document. It is a relative unit, which means all values that use it change when the root's font-size changes. The root element in this case refers to the html element.

    If you add more element, you will find that rem and em are different.

    When use rem, font-size will change basic on html.

    console.log("doc:  " + getComputedStyle(document.documentElement).fontSize);
    console.log("body: " + getComputedStyle(document.body).fontSize);
    console.log("div: " + getComputedStyle(document.querySelector('div')).fontSize);
    console.log("p: " + getComputedStyle(document.querySelector('p')).fontSize);
    * {
      font-size: 0.5rem;
    }
    <div>
      <p></p>
    </div>

    When use em, font-size basic on parent element

    console.log("doc:  " + getComputedStyle(document.documentElement).fontSize);
    console.log("body: " + getComputedStyle(document.body).fontSize);
    console.log("div: " + getComputedStyle(document.querySelector('div')).fontSize);
    console.log("p: " + getComputedStyle(document.querySelector('p')).fontSize);
    * {
      font-size: 0.5em;
    }
    <div>
      <p></p>
    </div>

    And html{font-size:0.5rem} is also different from *{font-size:0.5rem}.

    When use *, it changes all elements. So:

    1. the default <html> font-size is 16px.

    2. <html> is 0.5rem = 8px (half of html default, now <html> is 8px)

    3. <body> also become 0.5rem = 4px (now <html> is 8px, 8px * 0.5 = 4px)

    4. other element like <div>, <p> are 0.5rem = 4px (<html> is 8px, 8px * 0.5 = 4px).

    When use html, it only change <html>'s font-size, so <html> is 0.5rem = 8px, and all other elements are same font-size(8px) as <html>