How granular are CSS rem units? - css

I am developing a scalable mobile/desktop friendly website using CSS rem units based on the average viewport size of the site.
I have been setting rem sizes as low as 0.001rem for certain padding and margins, which is working fine in my Firefox browser... but will it work in all modern browsers?
I am only questioning the ability to use 0.001rem units because the highest granularity I have seen prior to thousandths is hundredths of opacity... like opacity:0.25 for example.
How low can rem units go? Is 0.00000001rem an acceptable value in modern browsers?

Ultimately, your granularity is 1 physical pixel (well technically the sub-pixel in modern browsers, but I will ignore that for purposes of this discussion). You can have different calculated pixel values based on em or rem even down to several digits of precision. You then run into the real-world problem of, when rendering, that decimal precision would be lost when the browser ultimately rounds off to fit the pixels available at whatever the device pixel density is relative to the reference pixel density (96ppi).
In essence, this reference pixel is 1/96th of an inch. So 1px in CSS terms basically means 1/96" at 96ppi. On screens with higher pixel densities (say like 326 ppi of many Apple "retina" screens), scaling takes place to convert the CSS reference pixel to physical pixels. For the retina display mentioned, this scaling factor would be ~3.4. So if you specified a CSS rule to set something to say 10px, the retina display browser should display on 34 physical pixels (assuming no other HTML changes (i.e. meta-elements) that would change display behavior). Because of this scaling behavior, the physical size of the element would still be 10/96" which is exactly the same physical size as if the element were rendered on a 96ppi screen.
Now let's add em and rem to the mix. So let's use an example of 10px root element font size with a declaration on some other element of .001rem. That would mean you are trying to render this element at 0.01 (10px * .001rem) reference pixels, which would translate to 0.034 physical pixels in the retina display. You can clearly see that the rem value of 0.001 is at least one order of magnitude away from making a significant difference in physical display, as .01rem in this case would translate to 0.34 physical pixels - no difference when rounded for display than for the "more precise" .001rem specification.
So I think you are defining rem-based CSS rules with far more specificity than can actually be accommodated in real-world terms when physical pixels are being painted, unless you either have a very high root element size defined and/or you have a physical screen with pixel densities an order of magnitude greater than what you have in a retina display. I am guessing this latter case is not true.
Just because the CSS can be calculated to 3 decimals worth of precision or whatever, that doesn't mean that physical rendering can occur at that same level of precision.

A simple example on JSBin shows that a height of 1.001 rem renders to 18.0156 px, while a height of 1.0001 rem renders 18 px (which would be the same as using just 1 rem).
This means that you can have a 3-decimal accuracy (at least in the desktop version of Chrome and with regular font size).
I was also trying to write a JavaScript test to measure the accuracy, but the element.offsetHeight it an integer, so it's useless for this matter. Unless there is a different way to measure element dimensions in pixels (with decimal places).
EDIT 1: According to CSS specification (see this and this), there seems to be no limit regarding the number of decimal places.
But in the end, I think you are limited by the device's pixel density. The physical pixels on the screen are indivisible and all computed dimensions are therefore rounded to the nearest integer.

"CSS theoretically supports infinite precision and infinite ranges for all value types; however in reality implementations have finite capacity. UAs should support reasonably useful ranges and precisions." w3.org
In practice, however, my conclusion is: In Chrome, you can get to the thousandths place unlimited precision, until the fractional portion of the pixel value drops below 0.015.
EDIT: Original conclusion found to be flawed once the font size was increased to a larger number.
Test it yourself (I used Element.getBoundingClientRect()):
var l = [
"normal",
"tens",
"hundreds",
"thousands",
"ten-thousands",
"hundred-thousands"
];
var o = document.getElementById("output");
for (var i = 0; i < l.length; i++) {
o.innerHTML += l[i] + ": " + document.getElementById(l[i]).getBoundingClientRect().height + "px<br>";
}
body,
html {
font-size: 1000px;
}
#normal {
height: 1rem;
}
#tens {
height: 1.1rem;
}
#hundreds {
height: 1.01rem;
}
#thousands {
height: 1.001rem;
}
#ten-thousands {
height: 1.0001rem;
}
#hundred-thousands {
height: 1.00001rem;
}
#output {
font-size: 16px;
}
<div id="output"></div>
<br>
<div id="normal">Hello</div>
<div id="tens">Hello</div>
<div id="hundreds">Hello</div>
<div id="thousands">Hello</div>
<div id="ten-thousands">Hello</div>
<div id="hundred-thousands">Hello</div>
My output was:
normal: 1000px
tens: 1100px
hundreds: 1010px
thousands: 1001px
ten-thousands: 1000.09375px
hundred-thousands: 1000px
Indicating that the ten-thousandths place (0.00001) is beyond the precision that my browser supports.
After increasing the font size further, and playing around with it, I can't find a value that will yield a pixel value having a fractional portion < 0.015. (Try setting font-size: 1556px and 1557px)

Related

Letters displayed ridiculously huge (or small) when using 'em' to specify font-size

I'm experiencing some pretty bizarre behaviour from my CSS font-size rules. I'm probably doing something silly myself [this must be the case ;-) ], but I hope someone can point it out for me.
Currently (for testing purposes) I have only one rule for font-size in the stylesheet, that regulates ALL font-sizes, and this is it:
p, div, a, span {
font-size:3em;
}
Now I know 3em is a pretty big font-size (for all I know it should correspond to a width of about 3*16 = 48 pixels on the big screen browsers), but what you see in reality is simply ridiculous. Have a look: http://www.svvreewijkdevaan.nl/nl/
If you think the font size in the menu (which you see on top of the page) is big, scroll down a bit, and you'll find that the letters become so huge that they're not really recognizable as letters anymore.
And in fact, looking in the Firefox inspection tool, I find that '3em' letters are computed to have a font-size of (get this) 34992px, i.e. almost 35 thousand. What does that even mean?
In fact, the real (displayed) font-size (i.e. the width) seems to grow - at the very least - exponentially with the specified em number, rather than proportionally. So for example, if I replace 3em by 3.5em, the displayed font-size becomes at least two times as wide (actually more). Conversely, if I reduce the specified font-size to 1em I get the - normal and expected - size of about 16px. But if I make it 0.7em, the width reduces to maybe 2px (absolutely unreadably small).
Why don't the real (displayed) font-sizes grow proportionally with font-size (in terms of 'em') specified in my stylesheet?
em is based on the font-size of the parent element. Now, if you nest elements for which you have set the font-size in em into each other – those values get multiplied.
Either don’t nest element with font-sizes set in em that much;
set it for less elements (for example only for div or p, and let the descendants inherit the size);
or look into the rem unit instead.

rem, px, mediaqueries for browsers >=IE9

I have a project where IE9 is the minimal compatibility browser. That means that I can use the rem unit.
In my experience on large projects, involving many dev, the use of "em" creates quite a mess. I do not say that it is bad in itself, just that it seems to "naturally" happened on over time, when there is different people with varying skills working on a project. Dom elements tend to pile up, and that do not work well with the compounding behavior of "em".
After having looked at a lot of resources online, it seems that there is a lot of cargo cult on the question.
there is the temptation of solution 1:
start with this (suggested here css3files.com comment - David Buell ):
solution 1 :
html { font-size: 10px;}
body { font-size: 1.3rem;}
Rem for anything text-related and px for the rest.
But even though, I am not sure where I am really contrained to use another unit than "rem". I did some zooming test, and did not notice differences between "rem" and "px". The advantage of "rem" over "px" seems to be that "rem" will be relative to the a size set with "%" on the body, and this allows to change all text sizes in one line for a specific breakpoint.
Default text size change IS seemingly an issue, since "px" and "rem" text remains unchanged. But I wonder is there is usage statistics about this (this SO user thinks nobody). If it is really used then, I think I should drop the "easy math" font-size definition on the html tag.
solution 2 :
body { font-size: 0.8125rem;}
That gives 13px size with the browsers default size of 16px - and users can still change the default setting. (and maths aren't that hard starting with 16)
What I am really unsure of is the case of different screen resolution, and the case of different pixel density (which I know can be changed on windows).
to sum up:
No need to accomodate anything below IE9.
reponsive design.
handle zoom well.
handle user text size change if that's really used.
no magic, as barebone as possible (I use a css preprocessor but I want to avoid crazy use of it).
I think many frontend developer adapt their interface to browser zoom. But what is the practice with text-only zoom ? Its a somewhat more hidden browser feature. How many devs actually test it and code for it ?
I see that SO supports it but that it sorta breaks beyond a certain scale.
What the right base setup for a IE9+ interface, that supports responsive web design?
keep a rule - All font sizes must be specified using rem only with a pixel fall back. Do not use percentages, ems or pixels alone.
font-size: 14px; /* pixel fall back rule should come first */
font-size: 1.4rem;
more infor - https://github.com/stubbornella/oocss-code-standards
I did some testing here : http://codepen.io/Olivvv/full/aGDzI
a few interpretations :
solution 1 : WRONG
html { font-size: 10px;}
prevents the permanent browser/user font-size setting to be applied. If the user has requested a bigger font-size,it should take effect.
See here with the SO website, things break a little with very big fonts, but at least the user gets the font-size increase.
solution 2: OK
body { font-size: 0.8125rem;}
is actually the same as
body { font-size: 0.8125em;}
since the can only inherit from the element "em" as the same value as "rem" ("rem" stands for root em, the em value of the root element, i.e the element)
solution 3: INTERESTING
html{font-size: 62.5%;}
body{font-size: 1.6em;}
---> 1 rem == 10px
(if the browser is set to default, i.e 16px; - (62.5/100)*16 == 10)
Now about the possible strategies :
1. rem only
html{font-size: 6.25%;}
body{font-size: 16em;}
+ only working with rem; for font-size, width, padding, margin, borders. This seems to be the easiest way to go.
Here 1 rem equates to 1px in defaut setting. It responds to user change of the default setting, so it is accessible.
When doing responsive design, the interface can be zoomed by changing the % value of the . for instance:
html
the whole interface is zoomed. Zoom is vertical and horizontal.
div.foo{
font-size: 16rem;
border: 16rem solid;
width: 350rem;
border-color: limegreen;
}
That will create a box that expands both vertically and horizontally.
Issue: What about vertical zoom ?
2. rem and em (in order to get vertical zoom)
rem -> interface elements, width essentially
em -> text (can be resized independently from interface elements (which are in rem) by changing the font-size value on the body)
px -> seperators, borders essentially
This way we achieve interfaces that respond well to both browser zoom and browser font-size setting
Some comments on ideas read on some blogs and
"just use px, if your brain works in pixel" --> Very Wrong. Font-size in px will be unreadable for some users who have explicitely requested bigger font size. (and what about dpi different from 96 ?)
"layout in em" --> average wrong, since a different user font size will make appear horizontal scrollbars or not use the full viewport space. Such behavior relates to zoom, not font size. (note that I am not considering browsers older than IE9 - just let them fall back on their default values )

how to always have a 40-70 characters wide page? scren, mobile, print

How to balance a decent font-size regardless of the media (small vertical phone screen or full page printing) and a comfortable 40~80 char per lines using the current CSS best practices?
I think I know the drill for regular screens, set body's font-size to some percentage, mark your main content element with width being 70em and min-width 40em...
but then, i know nothing about the accepted standards for mobile and print for this problem.
All my search attempts take me to (now) futile discussions from 2002~2011 about the benefits of [em,pixel,%,pt] over the other...
body {
min-width: 16em;
min-width: 40ch;
max-width: 28em;
max-width: 70ch;
}
Use the ch unit for “width of a character”, and back it up with a setting in em units, with a numeric value that is about 40% of the desired number of characters.
The em unit means the size of the font. For texts in Latin letters, this is about 40% of the average width of characters, maybe a little more.
The ch unit means the width of the digit 0. It is generally the best available approximation for “average width of characters” in CSS. It is supported by modern browsers, but for less than modern browsers, set first the width in em units.
This answers the question in the heading of your message. The body of the message is vague and does not pose a question that could be addressed constructively.
Setting a page width relative to the character size would only make sense with a monotype font. Consider these two strings "iiiiiiiiii" and "WWWWWWWWWW" - both consist of 10 characters, but clearly require a container of different width!
You could play around with ex/em/ch units, but they would not give you full control to accomplish what you're trying to do. Also: ch isn't even fully supported!
Fiddled sample

Using fractional em's in CSS's font-size property

Say, I have the following CSS rule defined:
.className {
font-size:0.89em;
}
My question is, how "deep" into fractions can I go while specifying 'em's for browsers actually to support it and for the font size to be rendered differently for a small fractional change in the em's value?
JohnB is right. We're still rendering in pixels whatever the size unit we use, and small changes in ems will not change the displayed size:
For example, for text originally displaying at a height of 20px*, we can see that there is no effective change when a rule is added to make it .99em of its original height:
20 * 0.99 = 19.8
The browser can't display .8 of a pixel, so (assuming it will round up) it will still display it as 20px high.
Though it appears that browsers do not always round off as expected:
http://meyerweb.com/eric/thoughts/2010/02/10/rounding-off/
http://ejohn.org/blog/sub-pixel-problems-in-css/
*Yep, I know a font-size of 20px doesn't alway mean it's displayed at 20px!
It should be kept in mind though, that fractional em values, like all floating point numbers, are susceptible to rounding error.
I found that out while setting my media query boundaries, where one max-width was 0.00001em away from another min-width, and it was rounded up and both queries were activated. After changing the difference to 0.001em the queries worked as expected, exclusively.

What is the difference between px, em and ex?

What is the difference between px, em and ex? And when you define font-size in CSS, do you use px, pt or em?
em : the font-size of the relevant font
ex : the x-height of the relevant font
px : pixels, relative to the viewing device
Pixels (px) are browser dependent. It is the absolute size that you would see on your screen.
Em are sort of like percentages. Ems is referring to the base text size. The value of 1 em means the same thing as a value of 100 percent. But you can also say it in the opposite way: A percentage value is just an em multiplied by 100.
Points(pt) are what you would want to use in print media.
CSS Length Units:
Absolute: Inches(in), centimeter(cm), milimeter (mm), points (pt), picas (pc)
Points are standard typographical measurements that have been used by printers and typesetters for decades and by word-processing programs for many years. Traditionally, there are 72 points to an inch (points were defined before widespread use of the metric system). Therefore, the capital letters of text set to 12 points should be one-sixth of an inch tall. For example, p {font-size: 18pt;} is equivalent to p {font-size: 0.25in;}.
Picas are another typographical term. A pica is equivalent to 12 points, which means there are 6 picas to an inch. As just shown, the capital letters of text set to 1 pica should be one-sixth of an inch tall. For example, p {font-size: 1.5pc;} would set text to the same size as the example declarations found in the definition of points.
These units are really useful only if the browser knows all the details of the monitor on which your page is displayed, the printer you're using, or whatever other user agent might apply. On a web browser, display is affected by the size of the monitor and the resolution to which the monitor is setand there isn't much that you, as the author, can do about these factors. absolute units are much more useful in defining style sheets for printed documents, where measuring things in terms of inches, points, and picas is common. As you've seen, attempting to use absolute measurements in web design is perilous at best.
Relative: em (em-height), ex (e-height), px. The first two stand for and "x-height," which are common typographical measurements; however, in CSS, they have meanings you might not expect if you are familiar with typography.
em: one "em" is defined to be the value of font-size for a given font. If the font-size of an element is 14 pixels, then for that element, 1em is equal to 14 pixels.
ex: refers to the height of a lowercase x in the font being used. Therefore, if you have two paragraphs in which the text is 24 points in size, but each paragraph uses a different font, then the value of ex could be different for each paragraph. This is because different fonts have different heights for x
px: tiny boxes of color in a monitor are pixels. In general, if you declare something like font-size: 18px, a web browser will almost certainly use actual pixels on your monitor after all, they're already there but with other display devices, like printers, the user agent will have to rescale pixel lengths to something more sensible. In other words, the printing code has to figure out how many dots there are in a pixel, and to do so, it may use the 96ppi reference pixel.
Conclution
Because of this potential for rescaling, pixels are defined as a relative unit of measurement, even though, in web design, they behave much like absolute units.
Rrefrence: css the definite guid by eric meyer
what is the difference px,em and ex?
http://www.w3.org/TR/CSS21/syndata.html#length-units describes those and the other length units available in CSS
And when you define font-size in css, do i use px,pt or em?
As a rule of thumb, use percentages on screen and pt for print.

Resources