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

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.

Related

How granular are CSS rem units?

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)

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

Should I define CSS margins in pixels or ems? Why? When?

We have a CSS file with some rules similar to the following:
.directory-result ul
{
margin-top: 20px;
width: 60em;
}
.about-text
{
margin-top: 1em;
margin-bottom: 1em;
}
Everything is working ok, but we're wondering specifically about the inconsistencies between the margin-top values. One is 20px and the other is 1em.
Which is the best one to go with? What are the points I should consider when deciding which to use? Thanks.
em units are used for better scalability of the page when the size of the elements depend on the page's scale. It's especially important for old browsers (e.g. IE6) and mobile platforms.
px units are used for absolute values, while em is relative to the font size of the particular element.
1em means one font-line, e.g. you have a box with font-size 12px that means that 1em will be equal to 12px
Also, using px seems easier because you know the exact value, but em units inherit the value of their container.
<p>Text</p>
<div class="box">
<p>Lorem</p>
</div>
p {
font-size: 1.2em;
}
.box {
font-size: 1.2em;
}
In this case, the first <p> will have font-size equal to the basic font-size * 1.2, and the second <p> will display with font-size * 1.2 * 1.2.
They're simply two different ways of measuring. Em is linked to the font size (traditionally, 1em is roughly the width of the letter M in a given typeface), while px is pixels.
If you build everything using em, everything will scale accordingly when the user adjusts their font size (e.g. using IE's Page > Text Size menu). It also makes it easier to work to a vertical rhythm.
Pixels are better when you want to build something "pixel-perfect". Be aware that a CSS pixel doesn't always equal a screen pixel - mainly because modern browsers and mobile devices allow for zooming. This isn't usually a problem though because the entire page is scaled accordingly.
Whatever you do, make sure you're consistent throughout - it makes life much easier later on.
The ems unit is relative to the current font size in the browser. So if the user increases the font size*, or if you change an element’s font size in the CSS, the margins should still look “right” in proportion to the text.
*(This ceases to matter if the user zooms the page instead of increasing the text size (as is the default in Firefox and Chrome now, and is an option in IE).
If you're using a margin to position something a set number of pixels away from something else, then you should obviously stick with pixels.
Also here is a very good in depth tutorial:
px – em – % – pt – keyword
In this example directory-result ul represents a block - some sort of list/menu where pixel dimensions are quite important. We can’t always rely on em which defines the text size, because if we need 20px space due to some background image – well, we need 20px, no compromises.
Note that you can't create and save the image i.e. 10em wide, therefore I see no reason why should I use different units on a web page. It just creates confusion and later on it is very difficult to maintain the layout.
There is a one place though, where using em is advisable – I’m talking about text blocks. I’m guessing in your code about-text is placed within other text where adding top/bottom margin of 1em (height of text) makes sense. It’s like in any text editor (i.e. line spacing in MS Word) – text looks best when spacing between lines is defined by multiplying the height of text
So in my opinion – everywhere where you deal with design and you use images by default measured in pixels – usepixels for all padding/margin.
Everywhere where you deal with text inside a text block, and you want to add even spacing between the text nodes – useem.

Resources