Reputation: 4767
I have been working on a project for a while and I thought that using em was the de facto unit when it came to expressing length.
The way I usually proceed is to set the body and html elements to the desired px size and all the other elements to 1em. After that the rest is all in em. Until this morning this seemed like a good plan, until I found out that media queries don't seem to take in account the base body and html px value. They seem in fact to take the browser's default font-size which seems to be a very odd behavior. I also found this article which seems to confirm this.
I have done a small JsFiddle example which shows exactly this behavior:
https://jsfiddle.net/5dq3kq2t/2/
html, body {
font-size: 20px;
}
* {
font-size: 1em;
}
#divOf50Em {
width: 50em;
border: solid 1px red;
}
#cell2 {
display: none;
}
@media screen and (min-width: 50em) { /* 1000px, in theory (50 * 20px) */
#cell1 {
display: none;
}
#cell2 {
display: table-cell;
}
}
The experiment is simple, the table by default show the value "1" until the 50em min-width media size has been met. the the value "2" should display. I also placed a div which size is 50em to show when the behavior should be triggered and also to confirm that the CSS works outside of media queries.
If you resize the output of this experiment, you would expect that the shift between the two values would happen at a 1000px value which is 50em * 20px, but it does not, it happens at 800px which is 50em * 16px (the default browsers font-size - if this is your default size of course).
I'm clearly unsure of why this happens but I have two questions:
Otherwise it looks like having a script which would be aligned with media queries for some behaviors is impossible when using media width and ems since we cannot rely that the browser's font size will always be 16px.
Then if this is the case, my last question would be, is there a way to align media queries and JavaScript without going back to pixels? I prefer relative units over static pixels, they usually make styling much simpler.
Upvotes: 3
Views: 362
Reputation: 1
A possible workaround is to set the media query at load
event of window
by getting the font-size
of a child node of body
using getComputedStyle
:root, body {
--size: 20px;
--opt: 50rem;
--def: 1rem;
font-size: var(--size);
}
* {
font-size: var(--def);
}
#divOf50Em {
width: var(--opt);
border: solid 1px red;
}
#cell2 {
display: none;
}
window.onload = function() {
document.getElementById('documentWidth').innerHTML = 'Window width: '
+ document.documentElement.clientWidth + 'px';
var n = 50;
var fontSize = parseInt(getComputedStyle(document.getElementById("divOf50Em"))
.getPropertyValue("font-size"));
var css = `@media screen and (min-width:${fontSize * n}px) {
/* 1000px, in theory (50 * 20px) */
#cell1 {
display: none;
}
#cell2 {
display: table-cell;
}
}`;
var style = document.createElement("style");
style.textContent = css;
document.head.appendChild(style);
window.addEventListener('resize', function() {
document.getElementById('documentWidth').innerHTML = 'Window width: ' +
document.documentElement.clientWidth + 'px';
});
}
plnkr http://plnkr.co/edit/lncvWwBWc18C76UYhPnf?p=preview
Upvotes: 0
Reputation: 4767
After more research,
1em value = browser default font-size in pixel
either in CSS or JavaScript.Upvotes: 1