w3c / csswg-drafts

CSS Working Group Editor Drafts
https://drafts.csswg.org/
Other
4.5k stars 666 forks source link

[css-inline] text-layout: glyph-bounding-box #2228

Open tobireif opened 6 years ago

tobireif commented 6 years ago

I need consistent positioning of large and medium-sized text across operating systems.

The large text on the page https://tobireif.com/non_site_stuff/test_case_for_font_position_report/ gets positioned differently eg in Chrome on Mac vs in Chrome on Windows:

The space above the large text is 102px in Chrome on Mac vs 125px in Chrome on Windows.

The space below the large text is 75px in Chrome on Mac vs 52px in Chrome on Windows.

Another test-page: https://tobireif.com/non_site_stuff/test_case_for_font_position_report_yet_another_font/

From the above test-page:

Chrome on MacOS:

35439338-8cb9f178-029a-11e8-86aa-cf19bf836e6c

Chrome on Windows:

35439340-90798dc8-029a-11e8-88a4-5518f09775f3

The large-text positioning / the space above and below the large text should be the same across operating platforms, for this font and for all fonts where the effective position currently is different across operating systems.

In order to not break existing content there needs to be a new CSS property, eg position-of-glyphs: consistent-across-platforms; or eg text-layout: glyph-bounding-box; (The latter would set the same text positioning that browsers use for SVG.)

There are many other pages/sites/layouts where medium/large text and its position is important.

I need a way to ensure the same vertical text position across platforms.

The alternatives are not great:

a) Applying spacing:

eg

if (navigator.platform.startsWith("Win")) {
  var h1 = document.querySelector("h1");
  h1.style.marginTop = "-0.25em";
  h1.style.marginBottom = "0.15em";
}

This is a hack.

b) Fixing each problematic font:

This is not always feasible: There might be no time to do this, many web devs use fonts hosted by external services, and thirdly the font license might not allow any modifications.

c) Using SVG text instead of HTML text:

Replacing each respective text with SVG has major drawbacks: Some might fear that it might impact eg search engine visibility. Imagine a newspaper considering to use SVG for its headlines while search engines handle h1/h2/etc well - they probably wouldn't take that risk. And it might also impact accessibility, see https://www.google.com/search?q=svg+text+screen+readers . It's a potential issue as far as I can see (eg in a given specific screen reader), while HTML text can be expected to just work. Also, SVG is meant for graphics (which might contain text or not) - a pure text page (eg an article) coded in HTML shouldn't have to use SVG just to get consistent cross-OS text-layout (for its large text instances).

Thus it would be great if consistent cross-OS text-layout would be available in HTML as well (not just in SVG as is currently the case).

I hope that CSS will support opting into the glyph-bounding-box-based layout (which browsers already have implemented for SVG) as option for (typically large) HTML text.

eg h1 {text-layout: glyph-bounding-box} or h1 {glyph-positioning: glyph-bounding-box} (The exact names for the property and value could be different.)

That would solve the issue completely.

tobireif commented 6 years ago

Should the browser position the large text in the above example screenshots consistently across OSs?

Or could CSS offer a property?

fantasai commented 6 years ago

@litherum might have some insight on this...

tobireif commented 6 years ago

Just to clarify: I don't have a preference.

I need consistent positioning (the same visual position) of large and medium-sized text in all browsers across all OSs.

If that should and will be ensured by all browsers then that'd be fine with me.

If instead (or eg for a specific category of fonts) CSS can and will offer some property that allows me to ensure this (and if all browsers then support it) then that'd be fine with me as well.

tobireif commented 6 years ago

I hope that the two screenshots show that the issue is quite severe in some cases.

There are workarounds, but I hope that there will be a solution.

tobireif commented 6 years ago

Perhaps CSS could offer eg "text-metrics: platform-independent" or eg "text-position: platform-independent".

No matter the name, I need a solution 😀

kojiishi commented 6 years ago

Rather than picking one metrics, I prefer to allow authors to set the length from the top of box to the baseline. If we consider this is for web fonts, it should solve, and it also solves some other cases I've heard of.

WDYT? @FremyCompany @fantasai @litherum @dbaron

tobireif commented 6 years ago

allow authors to set the length from the top of box to the baseline

If that would solve the issue I describe then yes that would be a good option.

A detail: Let's say I work on a website/webapp on Mac OS. There's a large word on the page, and the spacing and layout is set just right for the visual text position. Now I want to ensure that the text stays in that same y-position no matter on which platform. I'd set the new property - but to which value? I'd have to measure the length from the top of box to the baseline on Mac OS before I could set it for all OSs.

That measuring would be tedious eg if there are several web fonts.

Instead I need a non-numerical value that ensures that the position of the text (of the glyphs) are always the same on all OSs. The workflow would then be simpler: Right away after setting up the webfont I'd set eg "position-of-glyphs: same-on-all-platforms". Then I'd set my spacing and layout based on that reliable text position. Then when I test the page/site/webapp on other OSs there'd be no issue regarding the position of the text / of the glyphs - the glyph position would be same in all browsers, on all OSs, and on all devices == there would be no mismatch with the spacing of my layout.

What do you think? @kojiishi @FremyCompany @fantasai @litherum @dbaron

dauwhe commented 6 years ago

In case it's helpful, here are the font metrics (via FontForge and the OS/2 table) for two of your examples:

font name em size typo ascent typo descent win ascent win descent cap height
Frankfurter 1000 976 -24 1143 35 667
Hetilica-Bold 2048 1536 -512 1953 326 1415

Does this happen for all fonts? Do you get better results with line-height: normal or with less mixing of units?

tobireif commented 6 years ago

Thanks for caring!

Does this happen for all fonts?

To the extreme extent shown in the screenshots it happens to just a subset of the web-fonts I checked. But sometimes I do use fonts where it happens to that extreme extent, and for these cases it would be really great to have some (nice and quick to use) solution. It should be as easy as adding one line of CSS, without having to get the font metrics, for example 😀

Do you get better results with line-height: normal or with less mixing of units?

Here's a version with line-height:normal and only em units (both regarding the h1):

https://tobireif.com/non_site_stuff/test_case_for_font_position_report_yet_another_font_line-height_normal_just_em_units/

Screenshot of that page in Chrome on MacOS:

z90c075c7a1c62e3f10b

Screenshot of that page in Chrome on Windows:

zce0ac738eca40d4ab87

tobireif commented 6 years ago

Here's code from a website where I used a hack to compensate the difference in glyph-positioning:

(Warning: it's from an older website of mine, uses jQuery 😮)

(function() {

/*
The font rendering/spacing is different across OSs and browsers, so
here goes a hack:
*/

var svg = $('#svg');
var javascript = $('#javascript');
var css = $('#css');
var pixi = $('#pixi');
var angular = $('#angular');

var ua = navigator.userAgent.toLowerCase();
// Firefox:
if($.browser.mozilla) {
  angular.css({
    'margin-top': '10px',
    'left': '-170px'
  });
}
if(/windows/.test(ua)){
  // Firefox:
  if($.browser.mozilla) {
    svg.css({'margin-top': '-24px'});
    javascript.css({'margin-top': '-3px'});
    css.css({'margin-top': '-12px'});
    pixi.css({'margin-top': '36px'});
  }
  // Chrome:
  if(/chrome/.test(ua)) {
    svg.css({'margin-top': '-22px'});
    javascript.css({'margin-top': '-1px'});
    css.css({'margin-top': '-12px'});
    pixi.css({'margin-top': '38px'});
  }
  // IE, Edge:
  if(/msie|trident|edge/.test(ua)) {
    svg.css({'margin-top': '-14px'});
    angular.css({
      'margin-top': '10px',
      'left': '-180px'
    });
    javascript.css({'margin-top': '12px'});
    css.css({'margin-top': '1px'});
    pixi.css({'margin-top': '28px'});
  }
}

}());

I think the horribleness of the above hack demonstrates that a solution is required 😀

tobireif commented 6 years ago

In the above hack there's (shortened)

if($.browser.mozilla) {
  angular.css({
    'left': '-170px'
  });
}

and

if(/windows/.test(ua)){
  if(/msie|trident|edge/.test(ua)) {
    angular.css({
      'left': '-180px'
    });
  }
}

So it seems that for that word & that font I had to apply x-axis compensation.

I need a way to ensure that the glyphs in medium/large text get placed in the same position, regarding the x-axis and regarding the y-axis, in all browsers on all OSs on all devices. The property and value could be named eg "position-of-glyphs: same-on-all-platforms".

(Sub-pixel differences are negligible. And: I never noticed an issue regarding the glyph positions in small text - just in medium/large text. Perhaps the property could be ignored for small text.)

tobireif commented 6 years ago

Is it inside the scope of the CSS WG to offer some solution for the (sometimes drastic) difference in large-text positioning across OSs?

kojiishi commented 6 years ago

One question; what do you expect if font cascading or fallback occurs? Should the baseline position stay, or should it be adjusted according to the used font?

tobireif commented 6 years ago

I need a way to ensure that the glyphs in medium/large text get placed in the same position, regarding the x-axis and regarding the y-axis, in all browsers on all OSs on all devices.

If the following tests pass, in all bowsers on all OSs on all devices, then the issue would resolved well enough as a first step.

https://tobireif.com/non_site_stuff/test_case_for_font_position_report/ https://tobireif.com/non_site_stuff/test_case_for_font_position_report_yet_another_font_line-height_normal_just_em_units/ https://tobireif.com/non_site_stuff/test_case_for_font_position_report_yet_another_font/

And (right away or later) consistent glyph-positioning should also be ensured for the cases you list.

(I don't know what you mean by "font cascading", but I guess that both "font cascading" and "fallback" both mean that a different font is used eg until the respective web-font is loaded and applied.)

The fix / the property should work for all fonts on all pages for any type of font, for fonts supplied via @ font-face, and for fonts loaded from the local system (eg "non-web-fonts") (including "-apple-system" and BlinkMacSystemFont).

The default (eg in the absence of the new property) should be consistent glyph-positioning for all fonts used on a page, in all stages of the loading phase, in all browsers on all platforms (OSs and devices).

Should the baseline position stay, or should it be adjusted according to the used font?

The glyphs should always get positioned in the same position (x-axis and y-axis, not just baseline) across platforms - per used font.

kojiishi commented 6 years ago

per used font.

Thank you, that was what I wanted to ask, sorry for not being clear. So in your use case, the position should change if the used-font is changed.

tobireif commented 6 years ago

No problem! Yep, I think that glyph positioning should always be correct - per font, and across all browsers/OSs/devices.

tobireif commented 6 years ago

@fantasai wrote on January 27:

@litherum might have some insight on this...

Nobody has posted objections since ~seven weeks, and I have shown that the issue can be quite severe for large-text based layout and needs a solution, thus perhaps it would be OK to add this to the agenda?

dauwhe commented 6 years ago

It's hard to discuss this without understanding what's being done differently in different browsers. Are line layout rules from CSS 2.1 actually being violated? Is this only a problem with certain unusual font metrics? I don't have access to Windows, so it's hard for me to test.

jonjohnjohnson commented 6 years ago

@tobireif Aside from specs, I've solved similar text-rendering inconsistencies by replacing text with svg text. -> http://jsbin.com/xequz/edit?js,output Here, control the sizes by altering the height/width of the li tags the text is within, figured it couldn't hurt to share.

kojiishi commented 6 years ago

While I agree to solve this problem, and I'm fine to put on F2F agenda, I think this will take some time to get to conclusion. fantasai and I had some early rough discussion last week, but we hope to solve similar related requests as well, and we need to design carefully about overflow, fallback, etc. The new property is likely to be added to CSS inline level 4, but we still have work for CSS inline level 3.

The "per used font" is a bit challenging. I was hoping to solve one feature to solve two requests, but this makes it impossible. Re-thinking what the best feature would be.

tobireif commented 6 years ago

@dauwhe wrote:

I don't have access to Windows, so it's hard for me to test.

Trying to reproduce the issue is a great first step! I use https://crossbrowsertesting.com/ - it's a great service for testing websites on many different device/OS/browser combinations. (I can not imagine doing web development without such a service - or a huge local device lab.)

It's hard to discuss this without understanding what's being done differently in different browsers. Are line layout rules from CSS 2.1 actually being violated? Is this only a problem with certain unusual font metrics?

I'm a web developer. The issue has been bugging me for years - I coded elaborate workarounds, and I hope that there will be a real solution for the future.

I submitted the issue description including exact pixel measurements of the cross-OS difference of one case, provided three test pages, and eight screenshots. I should (and have to) leave the rest - including further investigations and including the solution - to the CSS WG and to the browser vendors.

Is this only a problem with certain unusual font metrics?

I need consistent glyph positioning across OSs, browsers, and devices - no matter whether the font and it's metrics can be considered unusual or not 😀

tobireif commented 6 years ago

@jonjohnjohnson

Thanks for your input! That's a workaround, I had coded a different workaround, and there might be more options for workarounds. Now I need a solution 😀

tobireif commented 6 years ago

@kojiishi wrote:

While I agree to solve this problem, and I'm fine to put on F2F agenda, I think this will take some time to get to conclusion. fantasai and I had some early rough discussion last week,

Sounds promising!

but we hope to solve similar related requests as well, and we need to design carefully about overflow, fallback, etc. The new property is likely to be added to CSS inline level 4

It would be a dream come true. Seriously.

For me it is one or the main issues in web development (because many layouts contain large text) and the issue has been existing for many years, so a solution would be most welcome.

but we still have work for CSS inline level 3.

The "per used font" is a bit challenging. I was hoping to solve one feature to solve two requests, but this makes it impossible. Re-thinking what the best feature would be.

I'm confident that you and @fantasai etc can find a great solution.

tobireif commented 6 years ago

Adding a hack again in a current project 🙁

if (navigator.platform.startsWith("Win")) {
  var h1 = document.querySelector("h1");
  h1.style.marginTop = "-0.25em";
  h1.style.marginBottom = "0.15em";
}
litherum commented 6 years ago

You are right that consistent font metrics across the Web are valuable. However, it is also true that it is valuable for a platform’s web browser to follow the platform conventions for font metrics. This is particularly important for Web Views inside native apps. It is very common for apps to use Web Views to draw content as-if it was native (and it should look like native content). Similarly, it’s impossible for the implementation of a Web View to know if a Web View being used by a particular app should have web-like font metrics or native-like font metrics.

In addition, on a more pragmatic note, changing the metrics of every font used in a browser would change the layout of every website, which is super scary.

litherum commented 6 years ago

I need a way to ensure that the glyphs in medium/large text get placed in the same position, regarding the x-axis and regarding the y-axis, in all browsers on all OSs on all devices.

This is undesirable. Browsers shouldn’t be required to have exactly compatible shaping engines and rendering engines. Consider a browser that is bundled with the OS - such a browser shouldn’t have to include its own independent shaping engine and font rasterizer that are only used for that browser and not for the rest of the OS (for reasons of binary size, performance, and correctness). There is industry competition in text engines, which is only possible if browsers have the freedom to innovate.

tobireif commented 6 years ago

This is a problem:

chrome on windows

It's not an issue that has an effect only inside the scope of anti-aliasing / font-smoothing / etc - instead it's an issue that has an effect which in some cases causes the large text glyphs to end up in a drastically different location: It can even obscure more than a full line of text (as in the screenshot). That overlapped/obscured text could be extremely important text, eg a warning.

Which solution to the problem do you propose?

Requiring web developers do use hacks such as the following one can't be the state of affairs that you deem acceptable.

A hack I recently had to add to a website:

if (navigator.platform.startsWith("Win")) {
  var h1 = document.querySelector("h1");
  h1.style.marginTop = "-0.25em";
  h1.style.marginBottom = "0.15em";
}

Or eg this workaround: https://github.com/w3c/csswg-drafts/issues/2228#issuecomment-373479054 "replacing text with svg text. -> http://jsbin.com/xequz/edit?js,output "

We do need some sort of solution for being able to ensure consistent vertical positioning of large and medium-sized text across OSs/platforms (this includes eg Web Views inside native apps) and browsers.

It (obviously) should be opt-in so that no existing content is broken.

The property and value could be named eg "position-of-glyphs: consistent-across-platforms" or eg "position-of-glyphs: platform-independent". The name or the property/value is up to you / the CSSWG, it doesn't matter too much to me.

We need some kind of solution. Which options do you see?

By the way, I never had an issue with the exact glyph positioning of small text (eg normal-sized paragraph content). If the new property would (eg for performance reasons) only have an effect on medium and large text that that'd be fine with me. In that case the property name should perhaps reflect that it doesn't affect text below eg 20px.

And: For text where it applies, eg medium and large text, the browsers (etc) would still be allowed to innovate in the ~ sub-pixel range. But the new property would solve the issue where medium/large text can eg obscure a full line of important text because the current state of large-text-positioning across platforms is in such bad shape. And where the new property is not applied, browsers (etc) are still free to position the glyphs in such drastically inconsistent ways as they're doing now. By the way the following can not be called innovation in any sincere way - instead it is a real problem that needs to be solved:

chrome on windows

tobireif commented 6 years ago

...and to address this as well:

Consider a browser that is bundled with the OS - such a browser shouldn’t have to include its own independent shaping engine and font rasterizer

Fixing the grave issue shown eg in the above screenshot should be possible without that. I'm talking about medium/large text that's displaced by ~ a whole centimetre, not about sub-pixel differences eg inside the scope of anti-aliasing. Also, I'm not talking about text smaller than eg 20px - below eg that size I don't see any relevant issue.

litherum commented 6 years ago

Which solution to the problem do you propose?

This is a broken font file. The solution is that the creator of the font file should not create broken font files.

tobireif commented 6 years ago

Is the font file in the following test page broken as well?

https://tobireif.com/non_site_stuff/test_case_for_font_position_report/

The font "Frankfurter" is quite a prominent font, I hope that the font file is not broken 😀

kojiishi commented 6 years ago

I have a mixed feeling on this.

The font designer is saying "I want my font to have different metrics per platform". The web author is saying "I want to use this font, but ignore what the font designer wants for the metrics, and use Windows (or one of others) metrics on all platforms".

I agree with @litherum that the best solution is to use the font that doesn't have platform-specific metrics.

I see other requests to set baseline at the very specific position, using absolute length, and I think it's a valid request. I originally thought this issue is in the same bucket, but as discussion goes, it turns out this issue is asking to pick one of platform-specific metrics on all platforms. That is more complicated than controlling baseline positions using absolute length.

litherum commented 6 years ago
screen shot 2018-04-12 at 12 21 32 pm

The ascent is clearly too high.

The font designer is saying "I want my font to have different metrics per platform". The web author is saying "I want to use this font, but ignore what the font designer wants for the metrics ..."

@kojiishi is totally right.

tobireif commented 6 years ago

The ascent is clearly too high.

Not by that much:

screenshot
litherum commented 6 years ago

That's fair. The font author is saying "It's more important that adjacent lines don't overlap than to have each line hug the ink tightly" which is a totally legitimate design decision.

Does this font have different metrics on different OSes? If so, we should be clear whether or not we are discussing: 1) The concept of fonts exposing different metrics on different OSes 2) Various ways fonts may cause undesirable renderings

litherum commented 6 years ago

I think we could solve this with a new descriptor inside @font-face that takes a raw number that represents the font ascent (and another one for descent). The raw number would be a multiplier on the used font-size. If present, the browser would use this number instead of whatever is in the font file.

tobireif commented 6 years ago

Does this font have different metrics on different OSes?

I don't know. If it does I need to override that.

I need a way to ensure consistent large-text positioning across platforms, no matter what the respective font says.

It is not feasible for me to fix (or change or replace) each font file I use.

I need some kind of solution, eg a CSS property that allows me to request consistent text positioning across platforms - independent of what the font file says. An opt-in that overrides anything that causes the cross-OSs differences regarding the vertical positioning of large text.

Here's a hack from an older website (put on protective glasses, it uses jQuery). It applies workarounds to a set of text strings where each text string uses a different font:

(function() {

/*
The font rendering/spacing is different across OSs and browsers,
so here goes a hack:
*/

var svg = $('#svg');
var javascript = $('#javascript');
var css = $('#css');
var pixi = $('#pixi');
var angular = $('#angular');

var ua = navigator.userAgent.toLowerCase();
// Firefox:
if($.browser.mozilla) {
  angular.css({
    'margin-top': '10px',
    'left': '-170px'
  });
}
if(/windows/.test(ua)){
  // Firefox:
  if($.browser.mozilla) {
    svg.css({'margin-top': '-24px'});
    javascript.css({'margin-top': '-3px'});
    css.css({'margin-top': '-12px'});
    pixi.css({'margin-top': '36px'});
  }
  // Chrome:
  if(/chrome/.test(ua)) {
    svg.css({'margin-top': '-22px'});
    javascript.css({'margin-top': '-1px'});
    css.css({'margin-top': '-12px'});
    pixi.css({'margin-top': '38px'});
  }
  // IE, Edge:
  if(/msie|trident|edge/.test(ua)) {
    svg.css({'margin-top': '-14px'});
    angular.css({
      'margin-top': '10px',
      'left': '-180px'
    });
    javascript.css({'margin-top': '12px'});
    css.css({'margin-top': '1px'});
    pixi.css({'margin-top': '28px'});
  }
}

}());

I can continue to apply such hacks, but I'd strongly prefer writing one line of CSS which prevents the case where a large-text based layout is OK on MacOS but broken on Windows.

Even if it is the intent of the respective font designer to have large text on Windows in a drastically different vertical position than on Mac so that the spacing of the layout is broken (which can't really be the intent of any font creator), I still need a way to ensure consistent positioning of large text glyphs across OSs and browsers.

Per default, the intent of the font creator is honoured (if that's really what's currently happening and causing the issues I'm seeing). You'd simply give CSS authors the option to request that their large text doesn't jump to a problematically different y-position on Windows vs MacOS (no matter what caused that jump before the property got applied, and no matter what the font file says).

Side by side:

screenshot
tobireif commented 6 years ago

I think we could solve this

yay

I think we could solve this with a new descriptor inside @font-face that takes a raw number that represents the font ascent (and another one for descent). The raw number would be a multiplier on the used font-size. If present, the browser would use this number instead of whatever is in the font file.

If that would completely solve the issue shown above using the various test-pages and in the various screenshots (eg https://tobireif.com/non_site_stuff/test_case_for_font_position_report_yet_another_font/ incl. the screenshots linked from that page) then I'd be happy, and I (and everyone else who's affected by the issue) could stop applying hacks.

I think I'd prefer a simpler solution where no calculation or measurements are necessary on the part of the CSS user, eg position-of-glyphs: consistent-across-platforms, but to be frank I'll take any solution that's a complete and reliable cross-OS and cross-browser solution - and which will get implemented by all browsers 😀

A detail: With the solution you describe there's a risk that authors choose eg an ascent value that fits an "A" - but wouldn't fit an "Ä". With a simple property such as position-of-glyphs: consistent-across-platforms there'd be no such risk - the browser would ensure consistent glyph positioning across OSs and would be knowledgeable enough to not clip any glyphs.

tobireif commented 6 years ago

Just as a tiny signal from a browser vendor:

https://bugs.chromium.org/p/chromium/issues/detail?id=800693 :

Comment 7 by e...@chromium.org, Jan 12 Cc: dro...@chromium.org koj...@chromium.org e...@chromium.org beh...@chromium.org Labels: -Type-Bug OS-Android OS-Chrome Type-Feature Status: Available

Browsers today by and large try to match the native text rendering of the underlying operating system which often results in differences across platforms.

For webfonts though it is not unre[a]sonable to expect similar metrics across platforms.

Thanks for the report and the detailed test case.

kojiishi commented 6 years ago

Does this font have different metrics on different OSes?

Yes, see dauwhe's comment on Feb 16.

a new descriptor inside @font-face that takes a raw number that represents the font ascent...

That sounds like a good solution to me.

Just as a tiny signal from a browser vendor

Yes, we are working together to find a good solution. It just takes several discussions until we can reach there from multiple point of views, and this is one of such discussions. I hope you understand that.

tobireif commented 6 years ago

@kojiishi wrote:

Does this font have different metrics on different OSes?

Yes, see dauwhe's comment on Feb 16.

I can't find "mac" or "MacOS" in that comment, just two instances of "win".

Anyways, if the new property would allow CSS authors to override such per-OS metrics / if it would allow CSS authors to ensure the same effective glyph position across OSs and browsers no matter what the font says, then all's good 😀(and it would be opt-in, so it'd be safe regarding existing content)

That sounds like a good solution to me.

Wow, so both you and me (if it fixes all demonstrated issues and cases) would be OK with the solution that Myles proposed - that is indeed a first milestone!

Yes, we are working together to find a good solution. It just takes several discussions until we can reach there from multiple point of views, and this is one of such discussions. I hope you understand that.

Sure! (But the above para is a bit vague, so if you want me to do anything specific you'd have to elaborate.)

Thanks for all your input!

tobireif commented 6 years ago

This is the test-page where the y-position difference on MacOS vs Windows is most drastic:

https://tobireif.com/non_site_stuff/test_case_for_font_position_report_yet_another_font/ (Compare the screenshots linked from that page.)

Here's an SVG version of that test-page:

https://tobireif.com/non_site_stuff/test_case_for_font_position_report_yet_another_font_svg_version/

I can't spot any relevant y-position difference in Chrome on Mac vs Chrome on Windows.

screenshot

Thus it is feasible to render the glyphs at the same y-position, even with that specific problematic font file, and especially without requiring the web developer to take font measurements or to calculate and provide any metrics.

I need that same consistent cross-OS glyph positioning for HTML text. In order to not break existing HTML content it should be opt-in via a new property. That property should be simple and quick to write, eg position-of-glyphs: consistent-across-platforms. (Perhaps the respective implementation could mimic its SVG text font rendering or even use that same text-rendering implementation code? Just a thought - browser codebase internals sure are up to you 😀)

SelenIT commented 6 years ago

I agree that the problem is mostly in the fonts themselves, probably because font designers don't pay enough attention to the fact that different platforms use different vertical metrics for displaying fonts (I hope that such a discrepancy is created accidentally rather than intentionally most of the time). The following link provides some details about this: https://glyphsapp.com/tutorials/vertical-metrics.

Currently, the most practical approach to fix this for Web Fonts seems to be to edit the font data and synchronize these different platform-specific *ascent and *descent metrics. E.g. the FontSquirrel's web font generator has the "Auto-Adjust Vertical Metrics" option in the Expert mode, and you can always adjust them manually with a font-editing tool like FontForge as a last resort.

I also have mixed feelings about adding the possibility to override the font metrics in CSS. While there clearly can be valid use cases for this, especially for decorative fonts and icon fonts, it still seems to be kind of a hack, and overusing this hack can have too unpredictable consequences. Especially in the situation where only some browsers support it correctly, which, unfortunately, is so typical for most new CSS features...

tobireif commented 6 years ago

There are many current options:

a) Compensating for the cross-OS differences: eg

if (navigator.platform.startsWith("Win")) {
  var h1 = document.querySelector("h1");
  h1.style.marginTop = "-0.25em";
  h1.style.marginBottom = "0.15em";
}

A hack.

b) Replacing each respective text with SVG:

A hack. (And some might fear that it might impact eg search engine visibility, and it might also impact accessibility, see https://www.google.com/search?q=svg+text+screen+readers .)

c) Fixing each font:

Currently, the most practical approach to fix this seems to be to edit the font data and synchronize these different platform-specific ascent and descent metrics (e.g. the FontSquirrel's web font generator has the "Auto-Adjust Vertical Metrics" option in the Expert mode, and you can always adjust them manually with a font-editing tool like FontForge as a last resort).

Not efficient. A client pays me to do web dev, not for fixing each font I use 😀 Also, have you looked at the license of commercial web fonts? If I remember correctly, some do not allow any modifications. Oh, and many web developers (unfortunately) insist on having their web fonts hosted eg by Google - in that setup they couldn't fix the fonts either.

Given all of the above we need a solution.

In Chrome's SVG implementation for example there is no difference regarding the vertical positioning of the large-text glyphs across the main OSs. This shows it's completely feasible for browsers to not mess up large-text based layouts. That's all I want. Fixing this for medium/large text in all browsers would break existing websites, thus it must be opt-in → a new property / keyword.

I also have a mixed feelings about adding the possibility to override the font metrics in CSS.

You don't have to think of it as telling the browser to "override the font metrics in CSS" - it could just as well be viewed as "don't break my large-text based layout, instead simply do what you do with SVG text".

The browser can do it for SVG text (even when the most problematic fonts are used), it sure can do it for HTML text as well.

While there clearly can be valid use cases for this, especially for decorative fonts and icon fonts

No, the issue occurs quite often in my experience, and the solution would apply for all medium/large text (by far not just decoration glyphs or icon glyphs) because in most/many cases, medium/large HTML text gets positioned differently across OSs. Please see the thread above, it includes various test-pages and screenshots, andI often have to apply hacks, and @jonjohnjohnson lists a hack, and anyone who uses large text in their layouts can run into the issue.

it still seems to be kind of a hack

The reality is ugly: Many fonts seem to be messed up, and browsers often mess up large-text based layouts across OSs. Currently we need to apply hacks. Fixing each font is not feasible. So we do need a solution. I don't see why browsers shouldn't be able to ensure consistent cross-OS glyph positioning if they can do it for SVG. (The cleaner option would be for browsers to fix their HTML text rendering to match their SVG text rendering, but that would break content, thus a new opt-in property/keyword is required.)

overusing this hack can have too unpredictable consequences

Luckily, the opposite would be the case: Test on one OS, then predictably get the same consistent glyph-positioning on all other platforms.

Especially in the situation where only some browsers support it correctly, which, unfortunately, is so typical for most new CSS features...

Yes sure, a new feature must get implemented widely before we can use it 😀That's the case for every other new property/keyword/feature as well. And look at eg Grid - it's a whole new layout spec and it got implemented in an incredibly concerted way. Inside a pretty small timeframe every single modern browser announced support for Grid. Implementing one new property could be much faster.

tobireif commented 6 years ago

Here's a screenshot of the test page https://tobireif.com/non_site_stuff/test_case_for_font_position_report_yet_another_font/ in Firefox on MacOS vs Firefox on Windows:

screenshot_firefox_macos_vs_firefox_windows

tobireif commented 6 years ago

A great solution would be for browsers to start rendering HTML text as cross-OS-consistent as they render SVG text (see the SVG test page and screenshot from April 12 under "SVG version of that test-page").

But that would break a lot of existing HTML text content / large-text based HTML layouts.

So there needs to be a way to opt in.

What do you suggest?

kojiishi commented 6 years ago

SVG provides glyph-bounding-based layout, while CSS provides font-metrics-based layout by default today. Each has its own advantages and disadvantages.

If you want glyph-bounding-based layout, SVG is one good option.

tobireif commented 6 years ago

Thanks for the info!

Replacing each respective text with SVG has major drawbacks: Some might fear that it might impact eg search engine visibility. Imagine a newspaper considering to use SVG for its headlines while search engines are known to handle h1/h2/etc well - they probably wouldn't take that risk. And it might also impact accessibility, see https://www.google.com/search?q=svg+text+screen+readers . It's a potential issue as far as I can see (eg in a given specific screen reader), while HTML text can be expected to just work. Also, SVG is meant for graphics (which might contain text or not) - a pure text page (eg an article) coded in HTML shouldn't have to use SVG just to get consistent cross-OS text-layout (for its large text instances).

Thus it would be great if consistent cross-OS text-layout would be available in HTML as well (not just in SVG).

Perhaps CSS could offer that same glyph-bounding-box-based layout (which browsers already have implemented for SVG) as option for (typically large) HTML text?

eg h1 {text-layout: glyph-bounding-box} (the exact name could be different)

That would solve the issue completely.

jonjohnjohnson commented 6 years ago

I have a feeling that if/when Rhythmic Sizing is rounded out and implemented we may be able to solve these types of issues using line-height-step in combination with step properties and line-height?

@kojiishi If this spec wouldn't offer a solution for these "strangely baselined" per system fonts, I'd imagine the feature will fall short once in the wild?

https://drafts.csswg.org/css-rhythm-1/#line-height-step

kojiishi commented 6 years ago

The line-height-step is about vertical rhythms, other baseline features such as this one, or the consistent body pitch from @dbaron, should be in a separate bucket, probably CSS Inline Level 4 or a new spec. We chatted about both requests with CSS Inline Level 4 in mind but it'll still take time until we reach there...

tobireif commented 6 years ago

I hope that position-of-glyphs: consistent-across-platforms or eg text-layout: glyph-bounding-box (for getting the text-layout that browsers use for SVG) will be discussed by the WG as well.