
REM vs. EM – The Great Debate - mmastrac
http://zellwk.com/blog/rem-vs-em/
======
have_faith
I use REM for pretty much everything but still fall back to px for padding and
margins which hasn't been a problem for me so far although I can see why
selective use of EM could actually be useful.

Tangentially related. It bothers me a lot that we have to add classes like
header--large onto a component. The classname header--large should be able to
automatically switch depending on it's parent containers size (and not the
window size like media queries work). My component may be presented it 3
different styles depending on the size constraints of it's container and hard-
coding --large into the classname just makes it a hack. It's not large on
mobile so why am I overriding the styles of my desktop header--large
classname.

Ideal situation, parent container media queries so that variations can be kept
solely in css and you could just drop a component into anywhere. I'm guessing
there are some circular dependency issues stopping this from working maybe?

~~~
bbx
_" hard-coding --large into the classname just makes it a hack"_

You're gonna infuriate lots of CSS people! That's the basis of modularity: you
can just move around a component anywhere on the page, it will keep its
styling (thanks to classes like _header--large_ ) and not be disturbed by its
surroundings.

Personally, I agree with you, and think it's a bad approach. Elements should
be able to be styled according to _context_.

Let's say I have 2 columns: "main" and "sidebar". I have a list of my latest
articles in "main". I want to show another list of articles in my "sidebar",
but display them smaller, because it's secondary content.

Why should I have to add the ".post--small" class to all my posts? Why can't I
use the context of the parent ".sidebar" and use that in my CSS? I could then
keep the _exact_ markup for _all_ posts across the website.

 _" Ideal situation, parent container media queries"_

Yes, that's exactly what CSS is missing, but you found the reason why it
hasn't been implemented: circular dependency issues.

~~~
have_faith
Context sensitive components is exactly what I want. At the moment you have to
compute that context on the server and output the correct class names (or on
the front-end with React etc, doesn't matter). It would be nice for a
component to not be told about it's context but it's CSS can infer it either
through parent container breakpoints or something else.

There's too many negotiation between containers because a child component
doesn't understand where it is, components are very "dumb" right now. We need
smart context sensitive components.

------
gonyea
I utterly loathe using em units. Rem is better, but px are nice and locked
down. Em's are neat in theory, but reasoning about them after the CSS has
solidified is so tedious.

Em units begin to feel like a weather app telling you today's forecast as a
multiplier of yesterday's temperature.

Today is going to be 1.1!

[uninstall]

------
plugnburn
Since obsolete unterbrowser users must suffer, rem FTW.

What's REALLY missing in modern CSS3 standard is the ability to reassign CSS
root to any other element than <html>, according to font properties of which
all nested rems would be calculated. So, for now, we have to stick to
assigning base font sizes to <html>, not even to <body>.

My microframework (999.css - [http://999.surge.sh](http://999.surge.sh)) uses
pixels to assign base font size to <html>, rem for <body>, ems for headings
and rems for all other nested typography.

~~~
err4nt
While I don't have a solution that lets you reassign the CSS root to other
elements, I do use a plugin in my own work that lets me use scoped styles, as
well as element queries. It solves a lot of problems.

You should check it out, the learning curve is small, and it is even supported
well in unterbrowsers: [http://elementqueries.com](http://elementqueries.com)

~~~
plugnburn
I would love to check it out, if only your page didn't hang my Firefox. It's
really impossible to scroll. Lags are ~10-15s. Hardly even closed the tab.
What's going on there? Was it really written with performance in mind? :)

~~~
err4nt
Yeah, I'm not the JS dev, but the issue is known and being looked into.

Strangely it didn't affect previous versions of Firefox and whatever is broken
at the moment is already fixed in upcoming beta versions of Firefox. I'm not
sure what or why, but it might become fixed from mozillas end before a
workaround gets diagnosed.

How does it work in IE8 and previous Firefox, but have issues with the current
build, but not with upcoming builds? It baffles me

------
bbx
The main issue I have with _either_ of them, is sometimes having to resort to
using crazy values like 15.974rem or 2.0736rem (taken directly from the
author's website). Using pixels shouldn't be frowned upon, considering all the
preprocessors available, and how CSS variables (the next big thing) are around
the corner.

But I would always use EMs for any WYSIWYG generated value, where the design
solely relies on HTML tags, not CSS classes. It's then easy to alter the
container's font-size while maintaining consistency and balance between all
its children.

For borders, in any case, it's better to stick with pixels. Some people
started writing things like "border: 0.065rem solid #ccc", which would make
the border disappear if you either zoomed out, or set the font-size to
something smaller than 16px.

~~~
evolve2k
After leveling up on typography and what it takes to define a nice typographic
grid I found REMs to be a revelation.

A key concept of good typographic grid design is that the body copy line
height (or font size as a proxy) is a very important measurement to be reused
across your grid.

TLDR; By using your body font size as a basic unit of measure for other
visible distances eg padding, margins it's possibly to make your design look
better and feel more unified.

My crude rule of thumb for beginners is to use REM for everything by default
and then change over to EM anywhere this is not working for you (and this is a
crude summary of key advice in this article)

One style guide I read suggested that pixels were ok for anything up to 5px
and that REM/EM should always be used otherwise (towards ensuring a nice
typographic grid) and I think that's a good practical approach.

If you're essentially thinking in REMs and just translating that to px in
certain circumstances to get around crazy numbers, great,if that works for
you. But I think that generally REMs provide free design benefits for those
that switch to them rather than adding arbitrary non-proportional pixels
lengths everywhere within a design.

------
kristiandupont
Can someone explain to me why I would want to use either over px? I just don't
get it.

"One of the best practices to typography on the web is to use relative units
like rem and em.", it says, but _why_?? I get as a general philosophy that
relative might be preferable over absolute, the way you prefer relative paths
in your build system. But "relative" in this case means relative to the font
size which is either specified or the default, both which makes s using
absolute values just as valid and easier to comprehend..?

~~~
markdown
A font size that looks great on desktop is not often optimal on mobile
devices.

You can change your base font size with a media query and have the rest of the
website adapt accordingly because they're all sized relative to the base font
size.

------
blowski
In my experience most projects that need to worry about things like this are
too big for a high level of consistency to work. Either that, or the design is
sacrificed to make the code easier. Whenever a designer looks at a page they
say "left a bit, down a bit" until they're happy with it, regardless of
consistency.

So, yeah, use rems or ems if it makes your life easier. Use a CSS preprocessor
with lots of helpful variable names and functions. And just don't worry about
it.

------
ccarter84
I got kind of excited at the prospects of a study seeing how EM radiation
affects our REM sleep patterns, eapecially with the degree the IoT and 5G will
envelop us in the very near future. Unfortunately that debate will be another
day...

------
losvedir
What about good old px? I recently came across this article [0] which argues
that after all the "best practices" of rem vs em maybe px is actually the best
way to go, in order to accommodate high density displays and zooming.

[0] [https://mindtheshift.wordpress.com/2015/04/02/r-i-p-rem-
viva...](https://mindtheshift.wordpress.com/2015/04/02/r-i-p-rem-viva-css-
reference-pixel/)

------
davnn
For me, both units are pretty useless. PX is the way to go except for some
cases, e.g. a button's padding that scales with its text or baseline grids.
The following article (not mine) explains why pixel win:
[https://mindtheshift.wordpress.com/2015/04/02/r-i-p-rem-
viva...](https://mindtheshift.wordpress.com/2015/04/02/r-i-p-rem-viva-css-
reference-pixel/)

------
jlukic
In Semantic UI we include two distinct header types that sized using either
REM or EM. Page headings which are generally consistent across a site and
usually specified with H1-H5, are sized using REMs so they display
consistently. Sizing variations, (tiny, small, large, huge etc) however use EM
to allow them to be sized relative to its content container.

------
FormFollowsFunc
If you do the following:

    
    
      html {
        font-size: 62.5%;
      }
    

You can convert from pixels to rems (or ems) quite easily:

    
    
      p {
        font-size: 1.4rem; // 14px
      }
    

I use rems for stuff that needs to scale with text, ems for line-height and
pixels for everything else.

------
evunveot
I rarely use rem since I only stopped needing to support IE8 recently.
Instead, to deal with the pain of em calculations I use these sass mixins
(feel free to use; license CC0
[https://wiki.creativecommons.org/wiki/CC0](https://wiki.creativecommons.org/wiki/CC0))
(below is my first attempt at "sassdoc," which I happened to discover while
preparing this comment):

    
    
        $current-font-size: 16;
        
        // Remove the units from a value (pretty sure someone else wrote this originally)
        @function strip-units($number) {
            @if unit($number) == '' {
                @return $number;
            }
            @return $number / ($number * 0 + 1);
        }
        
        /// Sets font-size and line-height using percentage and unitless values respectively, with support for nesting.
        /// @param {Number} $new-font-size - Desired new font size in pixels (units ignored)
        /// @param {Number} $new-line-height - New line height in pixels (units ignored)
        /// @param {Number} $context-font-size - Current font size where you're including this mixin, if it isn't the global $current-font-size
        @mixin font-scale($new-font-size, $new-line-height:null, $context-font-size:$current-font-size) {
    
            // Set the font size
            $context-font-size: strip-units($context-font-size);
            $new-font-size: strip-units($new-font-size);
            $font-ratio: $new-font-size / $context-font-size;
        
            font-size:$font-ratio * 100%;
        
            // Set the line height
            @if $new-line-height != null {
                $new-line-height: strip-units($new-line-height);
                // Honestly don't remember why the "+ 0.0001" here:
                $line-ratio: $new-line-height / $new-font-size + 0.0001;
    
                line-height:$line-ratio;
            }
        
            // Include nested content with global $current-font-size set to the new value
            $last-cfs: $current-font-size;
            $current-font-size: $new-font-size !global;
        
            @content;
        
            // Reset the global $current-font-size to what it was before
            $current-font-size: $last-cfs !global;
        }
        
        /// Convert a pixel length to ems at the current (or given) font size
        /// @param {Number} $px-length - Length in pixels (units ignored)
        /// @param {Number} $font-size - Current font size in px, if it isn't the global $current-font-size (units ignored)
        @function ems($px-length, $font-size:$current-font-size) {
            $px-length: strip-units($px-length);
            $font-size: strip-units($font-size);
            @return ($px-length / $font-size)*1em;
        }
    

(Those are modified slightly and haven't been tested in this exact form.) This
lets me do, for example:

    
    
        .title {
            
            // Make the text in .title 112.5% (18 ÷ 16) with a line-height of 1.22 (22 ÷ 18)
            @include font-scale(18, 22) {
    
                // Give it 15 pixels of padding using em units
                padding:ems(15);
                
                // Make the text of a .subtitle inside a .title 14px (112.5% × (14 ÷ 18) = 87.5%)
                // (line-height remains 1.22 in this case, working out to 17.11px)
                .subtitle {
                    @include font-scale(14);
                    
                    // Give .subtitle 5 pixels of padding, but instead of nesting
                    // the mixin again, I'll just tell ems() that the current
                    // font size is 14 directly.
                    padding:ems(5, 14);
                }
                
            }
        }
    

The nesting isn't attractive and `ems(15)` is a little more typing than `15em`
(though not more than `(15/18)×1em`), but I think just using em for everything
reduces some cognitive load.

It also lets you do some tricks, like you can set the root element of some
component to `font-size:(16/1024)*100vw` and it'll have a "normal" size when
the viewport is 1024px wide but scale up smoothly in every dimension when the
viewport is larger (and down when smaller). And you can still scale the whole
page, including that component, by changing the font-size of html/body.

Thus far I only use rem when I need to override something for an inner
element, like if a piece of the aforementioned vw-sized component gets too
small when the viewport is less than 640, I would set the font-size for just
that piece in a media query using rem, allowing the rest of the component to
continue to scale down.

------
hetfeld
This blog has 3 FOUTs - first - the default fonts appear, next - all fonts
disappear and after this everything appears as it was at the first time and
only after it the correct fonts are loaded.

~~~
wanda
That's Typekit for you, I guess.

This is why

    
    
        font-display: < auto | block | swap | fallback | optional >
    

is going to be useful.

More info: [https://tabatkins.github.io/specs/css-font-
display/](https://tabatkins.github.io/specs/css-font-display/)

\----------

Alternatively, something I've been trying is loading fonts in an embedded
stylesheet (<style></style>) in the <body> element, loading critical CSS in
the <head>.

This results in content being displayed in a base/system font initially, and
then when the web font is loaded in the body, it replaces the base font, but
without blocking render and at the same time resulting in only one brief FOUT.

------
seivan
REM was easier for me to keep track of and understand. But it didn't work for
media/printer queries.

