-
Notifications
You must be signed in to change notification settings - Fork 50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Complete Support for Font relative length units: rem, em, ex, ch, cap, ic + more #47
Comments
Thanks for your suggestion! The way that At the moment, it's not clear to me how the additional units could be supported in a cross-browser way. Ideally, we'd just be able to set a custom property to e.g. Another thought would be to just create children elements that we can use to measure. Unfortunately, without using ShadowDOM, this would be quite brittle. And that has its own issues with e.g. elements that you can't attach a ShadowDOM to, elements that already have a ShadowDOM attached to them, etc... The last thing we might be able to do is find all of properties that could change the value of e.g. Would love to hear any other ideas! |
not sure about the actual "brittleness" or if that's hypothetical, but in a project also in need to translate anything to pixels I used the following quiet successfully. /**
* @param {HTMLElement} scope the container element
* @param {Number} size
* @param {String} [unit='em'] any (font based) CSS unit.
*/
const toPixels = memoize((scope, size, unit = 'em') => {
const test = document.createElement("div");
test.style.position = 'absolute';
test.style.fontSize = `1${unit}`;
test.style.width = `1${unit}`;
scope.appendChild(test);
const val = test.offsetWidth;
scope.removeChild(test);
return val * em;
}); Absolute positioning is required to prevent the test element from being "squished" by a sibling. const elt = document.querySelector(`.container`);
elt.style.fontSize = '20px'; // or whatever the CSS said
const em = toPixels(elt, 1); // 20
const px = toPixels(elt, 10, 'px'); // 10
const ex = toPixels(elt, 1, 'ex'); // 6
const ch = toPixels(elt, 1, 'ch'); // 8
const cap = toPixels(elt, 1, 'cap'); // 11 Results will likely vary and depend on the font family used as expected. While this is untested with a gazillion container elements using all different widths to be measured, in "real life" this wasn't a bottleneck nor "brittle". Any modern frontend framework like React or Vue will do worse things while fiddling with the DOM. The result of this snippet is virtually instant. Even if scope referred to an element with display flex or grid, there was no (noticeable) layout shift when the temporary test element was added. Thanks. |
I think something like that certainly would work in a lot of cases. My concern about brittleness though is mostly that it's really easy to accidentally break in real world code. You just need a rule like... .container * {
font-weight: lighter;
} And there's a chance that the measurements will be subtly wrong. The polyfill could try to detect this, but then you might as well just copy the relevant styles from Personally, I think I would lean toward the ShadowDOM approach. It's already expected that the polyfill should be loading early enough to hook It has a bonus that we can actually keep the dummy measurement element around too and have the browser tell us when something changed the value (via ResizeObserver). Edit: Corrected |
well... that's a huge understatement as it would be a total show-stopper for us and presumably anyone who intends to ship semantic, accessible code. I understand that developers love predictability and this mix of font relative units don't provide that. For some they're counter intuitive. The moment content design is based on font relative units, pixel perfection is irrelevant: every other font family on any system would change the final pixel result anyways, as could properties like The point is: a size of 20ch will be consistent for any specific font setting in each browser on the very page for the element it's used. We eventually had very little use for the 0.1.2 release because of its limitation to pixels. Our designs rely on these various internal font metric values and we would have to add "magic numbers" when converting them to rem/em in the hopes to get close to the same natural scales and harmonies we get by using proper and robust |
Oops, I meant
No -- but
Let me spend some more time thinking and looking into the alternatives and get back to you. Thanks! |
of course it can, which is the whole point of using this unit in the first place :D That's also part of responsive design: respond to the various fonts available on the target system and only then will a ch be a ch (extended Codepen). For the same reasons it's often a bad idea to mix pixels and percentages1, it's a bad idea to mix certain font metrics. Just because it all ends up with pixels at the end of the food chain does not mean that designs (should) depend on pixel values or any other fixed unit, and luckily in 2022 they no longer have to. Simply drop the idea that layouts only work with "fixed" units. Leave it to the (UI) designer what unit is best for a given container. Hopefully designers know what they're doing... thanks 4 ur ⏲, much appreciated Enjoy! Footnotes
|
I believe @argyleink may have valuable insight working on VisBug and he knows a thing or two about CSS |
From what I've learned while waiting for the But, to devils advocate my own comment, that's all a polyfill can do, is synthetically attempt as best it can, so maybe that's not a good enough reason to reject the feature. Definitely up to the authors of the plugin here, to let them assess their own amount of fidelity and complexity they want to balance and manage over time with this polyfill. So I see both sides here! Sorry if that's not helpful lol. But it's a fair request to want to use relative fonts in a container query, the spec allows it and the final implementations will too, but it's also on a fine line cusp for maintenance and management from a maintainer POV, and few folks may actually leverage this feature. ⚖️ hope this was helpful 🙂 |
Thank you, Adam, for the input!
I don't want the Polyfill to query font internals or to include a mini wakamaifondue and we're not (yet) dealing with line blocks and the trouble this could bring (hence no There sure are tons of shitty fonts out there and "garbage in, garbage out", but that's also my point: no matter how shabby the font might be, the browser figured out "something" and uses defined fallback calculations, like 0.5em for 1ex if the x-height isn't properly encoded in the font. In any case, it's the designer's job and responsibility to choose a proper font, for the same reason s/he decided to go for a 20ch or 36ex container width. I'm sure people who understand Typography are aware of the issues bad and broken fonts can have (on the web and in design apps), and therefore use quality web fonts and a good fallback stack. So even garbage font results will be consistent for that font on that page and produce something very close to the intended design. It will of course be different with a nice perfectly font. With great power bla bla bla ... Thanks. We are in the middle of a complete redesign, so unfortunately I have little time for elaborate tests, but I eventually cloned the repo to play with the original code. |
With 0.2.0 alpha of the polyfill now supporting the poster childs
rem
andem
for responsive designs, it would be nice to have complete support for font size relative length units to complete the picture.With the ability to use the element related
em
unit for container widths, adding other font size relative units should be just a matter of "while-listing" and performing the same logic as forrem
(root element font-size) orem
(selected element font-size) respectively.These are also long supported by browsers. For the selected element (like
em
):ex
: Equal to the used x-heightch
: Equal to the used advance measure of the “0” (ZERO, U+0030) glyph (Latin fonts), seeic
belowcap
: Equal to the used cap-height (capital Latin letter)Browser support for additional font size relative sizes of CSS Values 4 is unknown / unavailable on caniuse or MDN, but could be added preemptively to be available when support is eventually implemented. Rules are virtually the same.
Selected element font:
ic
: Equal to the used advance measure of the CJK water ideograph (CJK fonts), seech
aboveRoot element font:
rex
rch
rcap
ric
https://drafts.csswg.org/css-values-4/#font-relative-lengths
https://drafts.csswg.org/css-values/#relative-lengths
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Values_and_Units#dimensions
https://developer.mozilla.org/en-US/docs/Web/CSS/length
Thank you!
Some may argue that Point
pt
and Picapc
are also "font related". While certainly standard in print and PostScript, both are actually absolute units based on the inch. Given their straight forward computation into pixels, both could be easy to implement, despite being highly inaccurate for modern screen resolutions. However, designers coming from print might find them useful.pt
: 1/72nd of 1in.pc
: 1/6th of 1in == 12pt.The text was updated successfully, but these errors were encountered: