0

I am trying to get the padding pixel perfect to the baseline and top of the capital letters in a font (in this case Google Roboto). This means that if i want 100px padding, I need to subtract the amount of "built-in padding" that the font has.

I was able to open the font in glyphs trial version and get some useful numbers, however the numbers that give the best results are far from intuitive, and I'd like to know how it really works.

Here is an image of the codepen where i am exploring: screenshot of codepen

Text is 100px and desired padding is 100px (to the edges of the E) Left block is with line-height: 1em Middle is with line-height:1.4em Right is an image showing the calculation method using info from glyphs

The red background shows the size of the paragraph element. The blue background around the dash "-" is because it is selected - also indicates an interesting size, which most closely matches the apparent size of the whole "art-board" when opened in glyphs.

I found out that if I calculate the distance between the midline guide and the top and bottom of the letter, then i can calculate how much space there is above and below the letter and then divide by 2048 (the number of units the font indicates for 1 em).

.div1 {
  padding-top:    calc( 1em - 0.132em  );
  padding-left:   calc( 1em - 0.081em  );
  padding-bottom: calc( 1em -  0.157em );
  padding-right:  calc( 1em - 0.081em  );
}

The results seem solid, but is it really needed to dive into such detail to get the numbers??

Isn't there a way to calculate this in css or js?

gotjosh
  • 831
  • 3
  • 9
  • 18
  • what you've done works, but the far more important question is *why* are you trying to do this, because you're trying to do alignment based on content, which isn't a thing that browsers can do: they style text in entire inline blocks, not using individual letter boxing like LaTeX. You can change that, of course, with some JS to chop up the text and then created `` boxes for each letter, but then you've broken the font's ability to typeset words, rather than individual letters. So: why are you doing this? – Mike 'Pomax' Kamermans Mar 04 '17 at 19:31
  • _why_? because I want the padding to LOOK even... which may not be "a thing that browsers can do"... still, I want to know how the browser(s) calculate the placement of the font within their "inline blocks" and I want to know the best way to calculate padding - taking this into account. – gotjosh Mar 05 '17 at 12:21
  • They don't. They ask whatever text engine dependency they use to shape the text, and then they break the result box sequence based on word boundary rules (which differ per locale). The browser itself has zero knowledge of what's *in* those boxes, the only way to tell is to somehow tap into what the Text Engine does, and there are (currently) no APIs for that. So your other option is to use a parallel engine such as a JavaScript-implementation of a shaper (opentype.js, fontkit.js, etc) and then *rerender* the text in that and hope it did it the same way as the browser's. – Mike 'Pomax' Kamermans Mar 05 '17 at 17:54
  • Or, you mirror the text on a canvas, and do your negative space computations on that, which is very "expensive" and makes things really slow. Browser content is not LaTeX, trying to make web content have perfect layout based on box content, rather than box, is pretty much trying to fight river rather than going with the flow. – Mike 'Pomax' Kamermans Mar 05 '17 at 17:57
  • @Mike'Pomax'Kamermans, thanks for engaging here. I am not so sure that the info I need is really tied to "content". The amount of "built-in padding" that a specific font face has, is inherent to the design of the font. The numbers that I am looking for need to work regardless of which words are rendered. Because the Top of all Ts and H's and E's are basically the same distance from the top of the inline block. Perhaps one could use one of the js "shapers" that you mentioned to extract the numbers that are needed to infer the "built-in padding"... I'll look into that... – gotjosh Mar 06 '17 at 13:52
  • Fonts don't particularly have "built in padding", though. They have maximum ascender and em quad height metrics, but those are *completely* overruled when you explicitly set `line-height`. If you need more precision, you're going to have to examine the actual glyph using opentype.js or fontkit.js or the like. – Mike 'Pomax' Kamermans Mar 06 '17 at 15:47
  • Fair enough, they don't have anything that is technically termed "built in padding" however, they do have space above, below and beside the glyphs... Which, when I want to use proper 2D design principles, i need to be able to account for. So I coined the term on the fly, as it describes what I am hoping to be able to calculate... – gotjosh Mar 07 '17 at 18:14
  • In the mean time, I have used fonkit.js to get access to some of the font metrics. Still, I have been unable to calculate the numbers to my satisfaction. In the case of Roboto Light (Roboto Regular - weight 300), 702 was my magic number. I found it in Glyphs as a guide that was just below half the capHeight (but only in the source UFO - not in the TTF). – gotjosh Mar 07 '17 at 18:17
  • Thereafter, I started to look into how does Firefox actually size the box around the text, and so far got about this far down the rabbit hole: https://dxr.mozilla.org/mozilla-central/source/layout/generic/nsTextFrame.cpp#5545 – gotjosh Mar 07 '17 at 18:18
  • It must have something to do with baselineOffset and overflowRect and baseFontMetrics... and it seems that there is quite a bit of calculation happening in the browser logic. eg: https://dxr.mozilla.org/mozilla-central/source/layout/generic/nsTextFrame.cpp#9475 – gotjosh Mar 07 '17 at 19:08
  • you might want to use opentype.js then, and compute a glyph's metrics based on its glyph path bounding box, the quad baseline, and the glyph's lsb/rsb values (where both can of course wildly differ if there are any GPOS rules for kerning pair repositioning) – Mike 'Pomax' Kamermans Mar 07 '17 at 19:41
  • thanks for the tips Mike, when i look at http://opentype.js.org/glyph-inspector.html, I can understand lsb and rsb are leftSideBearing and rightSideBearing, and the bounding box i understand, but i did not find a reference to "quad baseline" can you explain? – gotjosh Mar 08 '17 at 08:23
  • glyphs are set to an em quad, where y=0 is considered the baseline, and is the "fixed" point that is used when setting line-heights. Line-height is actually the "baseline to baseline" distance, irrespective of the em quad dimensions. For purely English fonts, that's probably the only baseline there is, but if you have a font that supports multiple scripts there can be a "base" table that gives *different* quad baselines for different scripts (https://www.microsoft.com/typography/otspec/base.htm). – Mike 'Pomax' Kamermans Mar 08 '17 at 16:28

0 Answers0