CSS Breakpoints and em unit - css

When I tried to use em units with media queries I noticed that the unit is based on browser's default font size, not on the html root.
It working odd when I'm gonna to set 20em for element width when breakpoint is min-width: 20em. Both units in this case ar not equal because the element's 20em is based on the html font-size and media query is based on the default browser font size.
Is there a way to achieve the same size for both using em unit without defining additional, separate variable only for breakpoints (#bp-size: 16.250em)?
html {
font-size: 0.813em; // 13px (assume default browser font-size: 16px)
}
.box {
width: 1em; // 13px x 13px
height: 1em;
background-color: #000;
// Problem
#size: 20em;
#media screen and (min-width: #size) { // 320px (20 x 16px) why not 260px?
width: #size; // 260px (20 x 13px)
background-color: #f00;
}
}
<div class="box"></div>

I asked this question not long after yours. I finally found the definitive answer from the html-gods buried deep in the Media Queries page.
Relative units in media queries are based on the initial value, which means that units are never based on results of declarations. For example, in HTML, the ‘em’ unit is relative to the initial value of ‘font-size’.
It doesn't matter what you set in your html, media queries will always be set on the browsers initial font-size attribute.

This is very possible -- What you're looking for is rem rather than em:
#size: 20rem;
rem is relative to the root element, whereas em is relative to the current element. See W3 and TutsPlus for further information in this regard.
Hope this helps! :)

Related

Angular CSS mat-icon-button calc() setting auto increase and decrease with min max

I am implementing mat-button in my css to use calc() to auto increase or decrease the font-size
When I first add the .mat-icon-button without calc(),
at max, I use font-size: 1.5vw. When the window resizes or container width is resized to a smaller width, I like font-size: 0.75vw
.mat-button {
...
font-size: font-size: 1.5vw;
}
I have many buttons and of course the crowded look appears as the container width is shrunken.
I looked up If I can use conditional inside CSS but no luck. Then I tried calc() like so
.mat-button {
...
font-size: calc(100%);
}
Made progress and the button width and height will shrink according to the container size
But the font-size is too small and the buttons are too tiny. Not a great UX experience
I am looking up if I can do min and max in CSS button but the min is not working
.mat-button {
...
font-size: min(calc(100%), 2rem);
}
I was thinking in CSS I can do min/max like the following but no luck so far
.mat-button {
...
font-size: min(max(calc(100%), 2rem), 1rem);
}
Any help is appreciated.
Thanks in advance
This can be done best using media query, so you can set the font size according to your needs. like this:
#media only screen and (max-width: 600px) {
body {
font-size: 1.5rem;
}
}
if you need a more precise size, you will need to use SASS for adding conditional to your styling.

Using rem units in media queries and as width

When using rem units in Google Chrome (or firefox), the result is unexpected. I'v set up a page with the root font-size set to 10px to make it easier the translate a pixel based design to html/css.
This is my css. My expectation would be a page with one 500px wide box and if the screen is wider than 500px the background should turn red.
html {
font-size: 10px;
}
#media screen and (min-width: 50rem){
body{
background-color: red;
}
}
.test{
width: 50rem;
background: black;
height:100px;
}
But, despite both values being defined as 50rem, the results is a 500px wide box with the page turning red at 800px.
https://jsfiddle.net/tstruyf/puqpwpfj/4/
What am I doing wrong or why is this?
It's meant to work like this, it's just a little confusing if you don't know what's going on.
If you're not using rem in media query declarations then they are based off the root html base font size. If you don't declare this, then in most modern web browsers it's 16px.
As you have declared it as 10px a rem will be 10px throughout your code. Unlike em units, where it is based on the closest parent declaration size.
The confusion comes in that media queries declarations do not base themselves on the declared font-size that you apply to html and instead always use the default size - which as I said is 16px in pretty much all browsers.
That's why 50rem is coming out as 800px - 16px * 50.
Note, this is only for the declaration of the media query breakpoint, if you assign something to be 1rem tall inside the media query, then it will base itself on the base html size.
html {
font-size: 10px;
}
#media screen and (min-width: 50rem){ // 800px (uses base font-size)
div.somediv {
width: 50rem; // 500px (uses the declared html font-size)
}
}
You're not doing anything wrong, this is how rem in media queries are meant to work. As per the spec:
Relative units in media queries are based on the initial value, which
means that units are never based on results of declarations. For
example, in HTML, the em unit is relative to the initial value of
font-size, defined by the user agent or the user’s preferences, not
any styling on the page.
So any styling you apply to the base font size doesn't have an effect on the media query calculation.
Here's the relevant part of the spec.
If you really want to use rem and have them use a font-size basis of 10px, you could always write a SASS mixin to do the conversion for you. Other than that, it might be less confusing to stick with px for media queries.
The size of 1rem in media queries is not affected by changes to the base font size. But you could calculate the correct breakpoint yourselves. You can calculate the breakpoint in pixels based on your new base font size and the desired size in rems.
pixels = desired-rem-value * current-base-font-size
For example for a base font size of 18px and a breakpoint at 20 "rem":
20 * 18px = 360px
There are a few options how to calculate the pixel value:
1. calculate by hand:
html {
font-size: 18px;
}
/* For a breakpoint at 20 times your base font size*/
#media(min-width: 360px) {
...
}
2. Use calc():
#media(min-width: calc(20 * 18px)) {
...
}
3. Use a CSS prepocessor function:
(For example in scss or something similar.)
$base-font-size: 18px;
html {
font-size: $base-font-size;
}
#function media-rem($rem) {
#return $rem * $base-font-size; // $rem must be unitless
}
#media(min-width: media-rem(20)) {
...
}
Based on the rem CSS Specification:
When used outside the context of an element (such as in media
queries), these units refer to the computed font metrics corresponding
to the initial values of the font property.
So, in this case, which media query, rem refers to the initial values of the font property (Default browser's font-size = 16px).

Font-size and device-pixel-ratio

Let's say that I have default font size set to 16px (this should be redundant since it's default in most browsers):
For brevity, my site contains some box with size 10em x 10em.
body, html
{
font-size: 16px;
}
.box {
border: 1px green solid;
background-color:green;
width:10em;
height:10em;
}
My site is already responsive with min-width media queries for specific breakpoints targetted at em values (36, 62 and 85em).
The only thing my site does is change width and color of the box.
#media (min-width:36em) {
.box {
width: 36em;
border:1px red solid;
background-color:red;
}
}
#media (min-width:62em) {
.box {
width: 62em;
border:1px blue solid;
background-color:blue;
}
}
#media (min-width:85em) {
.box {
width: 85em;
border:1px orange solid;
background-color:orange;
}
}
Now let's say that I have some device with resolution 1440x900 where browsers decide that the device's pixel density is 2dppx by default. As result, everything looks much bigger than it should be. And I don't like it.
But the solution should be easy, right? Just add a media query at start for 2dppx pixel density and since it's twice as much pixels, I just reduce the font size by half...that should work, right?
And since I use "em" on everything then by changing the font-size by half I automatically reduce size of everything "em"-sized by half...right?
#media ( min-resolution: 2dppx) {
body, html {
font-size: 50%;
}
}
relevant jsFiddle
Well I found it does not work as I thought it would...I tried to google answers but did not find anything relevant, I suspect I misunderstand how font-sizes, ems and pixel density works...
Reducing font-size by 50% reduces the font-size by much more than by half. The original size is 16px but font-size: 50%; results in a font much smaller than font-size:8px ... Tested in Firefox and Chrome. Does anyone know why is that?
When I set font-size:8px; in the media query for 2dppx then media queries for min-width:36em, 62em and 85em do not trigger as I would have expected, at least when I change layout.css.devPixelsPerPx in Firefox. The min-width in media query behaves like the font-size is still at 16px eventhough it's changed with the dppx media query. Tested in Firefox and Chrome. Does anyone know why is that?
UPDATE
Looks like media queries are loaded in 1dppx context, it does not matter if you use "em", it seems they are cached on load and values such as min-width are fixed to the first value and eventhough you change the base font-size in different media query, other queries don't refresh.
The only solution I can think of right now is to multiply all media queries. One media query for px value in 1 dppx context and another media query for px value in 2 dppx context (which is 50% of the first value).
Thanks to Mr Lister in comments, I found out that this:
#media ( min-resolution: 2dppx) {
body, html {
font-size: 50%;
}
}
...is not what I intended to do. The 50% rule works for <html> tag AND for <body> tag. The resulting font size is not 8px in body, but 4px, because 50% in html is 8px and another 50% in nested body tag results in 4px.
What I intended to do was this:
#media ( min-resolution: 2dppx) {
html {
font-size: 50%;
}
}
Font-size issue is solved.
For the media query: I found out that sizes in #media queries ignore pixel density but sizes in the CSS rule body do not. Since I use "em" sizes and SASS, I can simply replace all #media queries with this mixin (example with 2dppx):
#mixin media-min-width($min-width) {
#media(min-width:$min-width), (min-width: $min-width / 2) and (min-resolution: 2dppx) {
#content;
}
}

Em versus px settings for fluid layouts

Im reading about optimal font sizing and layout sizing...and Im looking into em instead of px.
From what I understand, if I make the css like this;
html {
font-size: 16px;
}
body {
font-size: 1em;
}
It will force the browser to make 16px = 1em, and that will enable me to do width and height properties by calculating desired pixels/16, right?
Almost all browsers gave their default font size as 16px.
So if you simply set font-size:100% on your body tag then work from that you'll be golden.
Here's a good site that I use for calculating font-sizes from your base size:
http://riddle.pl/emcalc/
In the settings tabs simply change it to 16px and that's you set.
You are correct, and so is #Billy Moat.
You're not really gaining anything by explicitly declaring the 16px value on the HTML element - browsers tend to do that anyway.
Another trick that you can use is the "62.5%" trick.
If you declare:
body { font-size: 62.5% }
You can make further declarations in em's that map neatly to pixel measurements. e.g.:
h1 { font-size: 3em; /* equals 30px */ }
h2 { font-size: 2.4em; /* equals 24px */ }
.nav { width: 50.5em /* equals 505px */ }
That's because 10/16 = .625. So with this trick, you can rebase your measurements and not have to do the math later of dealing with a 16px base.
The only trick of this method is that once you declare a font size for an element, all children elements have to have their em values based on that parent's value (this is true of all relative units of measurement).

Are rems replacing ems in CSS?

I was reading about rem units in CSS3, and was a little confused. If you use rem, do you still use em or does that replace it?
For example:
.selector {
margin-bottom:24px;
margin-bottom:2.4rem;
font-size:16px;
font-size:1.6rem;
}
or
.selector {
margin-bottom:24px;
margin-bottom:2.4em;
margin-bottom:2.4rem;
}
Just trying to figure out if rem takes the place of em, or if it's just another unit.
Rem is the em size for the root (html) element. That means once you define the html element's font-size, you can define all rem units relative to that.
For example:
html { font-size: 62.5%; }
body { font-size: 1.4rem; } /* =14px */
h1 { font-size: 2.4rem; } /* =24px */
Rem is supported in Safari 5, Chrome, Firefox 3.6+, and even Internet Explorer, but for older browsers you still have to use em, percent or px.
No, it’s a different unit. em is based on the font-size of the parent, while rem is based on the root font-size, which I believe is the font-size of the html element.
Rem is just one more unit, it doesn't replace em like em didn't replace pixel.
Oldish topic, but I think it needs some more clarity.
Both em and rem are relative units, but rem is always relative to the html font size (the “root” element) rather than the inherited font size.
Never use px, or pt for that matter, on the screen. By hard coding the font size, you ignore the user’s personal preferred font settings and make zooming less cooperative.
Both em and rem have a useful role to play. Neither is perfect for all occasions. Here are some examples:
Use rem to avoid compounding sizing:
ul#something li { font-size: 1.2rem; }
… or …
ul#something li { font-size: 1.2rem; }
The first one will result in nested lists having progressively larger sizes, since the em unit will inherit from a parent li element.
Use rem to set sizes independently:
article { font-size: .8rem; } /* article base font size */
article>h2 { font-size: 2rem; } /* … except for h2 */
And, of course you can use both:
div#something { font-size: 1.2rem; } /* based on html size */
div#something>h2 { font-size: 2em; } /* based on div#something */
Two years down the track, now, and we can use it, safely ignoring Legacy Browsers.

Resources