349 karma · joined August 31, 2012
Browser engineers have an extremely difficult job. The codebase is incredibly complex (they aren't just copying data from one system to another - it takes years to get up to speed in just a small area of the codebase) - any change (even improvements/fixes) risks breaking websites.
You might think you are complaining to a faceless organization, but in reality your really just talking to 1-2 people. Be kind. Each time an engineers gets dumped on you risk them throwing in the towel for good (engineer burnout is real), your bug will very much not be fixed then.
Engineers like fs@ are one of a kind and experts in their area. (fs@ implemented SVG favicons to Chromium for example - https://bugs.chromium.org/p/chromium/issues/detail?id=294179 ). As the web platform is so expansive there are really only a few people in the world at one time who understand various problems deeply enough to make progress on a fix.
What does help? In this particular case - if you are affected by this bug starring it helps. If you can kindly describe how this affects you - that also helps. The Chromium project actively tracks highly starred bugs. (Keep in mind the project also takes into account "gaming" the count so getting 100 people to star the bug mindlessly wont help).
(I'm an engineer on Blink's layout engine).
We've recently finished re-architecting Blink's layout engine, part of the reason why we did this investment was we were concerned that we couldn't fix WebKit era bugs (e.g. too many sites would depend on them due to our shared heritage). This makes other engines jobs (e.g. Gecko) super difficult as they'd need to encode even more quirks than they have time for.
I think we've broadly mitigated a large part of that risk. There are still large parts of CSS which are underspecified, e.g. tables/block/float layout. But its slowly getting better.
.target {
anchor-name: --myname;
}
.tooltip {
left: anchor(--myname left);
bottom: calc(anchor(--myname top) - 20px);
}
https://jsfiddle.net/3rasnhyp/ .BlueSquare {
width: 100px;
height: 100px;
top: 0px;
left: 0px;
anchor-name: --BlueSquare;
}
.RedSquare {
width: 100px;
height: 100px;
top: calc(anchor(--BlueSquare bottom) + 10px);
left: calc(anchor(--BlueSquare right) + 10px);
}
https://jsfiddle.net/kbqua1te/The next largest part was writing all the tests for this work, e.g. making sure that margin/border/padding worked consistently between all the MathML elements[3].
Arguably the implementation in Chromium was the "smallest" part of the work required here.
Congrats to Fred/Igalia/MathML-CG and all those involved. :)
[1] https://www.w3.org/TR/MathML3/chapter2.html#fund.renderingmo... [2] https://www.w3.org/TR/mathml-core [3] https://wpt.fyi/results/mathml/relations/css-styling/padding...
Some fonts have the space character in the kerning table, and possibly (although super rare) in the "ligature" table (gsub). (https://www.sansbullshitsans.com/ is an example of a font with a space in gsub, "paradigm shift" maps to a single glyph).
If you want to go really deep on how complex some scripts are take a look at: https://r12a.github.io/scripts/arabic/arb.html#shaping
width(A) + width(B) != width(A+B)
...which some basic text layout engines assume. The post touches on this, and is one reason why line-breaking is so difficult.
If you add some text to a line, the width of the line may be longer or shorter(!) than if you measured (shaped) the parts separately.This occurs for many reasons, the post mentions splitting a ligature, can also happen with kerning (spaces can have kerning applied for example).
E.g. many text layout engines will incrementally "add" to a line. However to do this correctly for all cases you need to re-shape (measure) the entire line (or from a known "safe to break" point in the shape result see: https://github.com/harfbuzz/harfbuzz/issues/224 ). This is typically fine for latin cases, but begins to become slow for more complex scripts (Thai).
Chromium kinda works backwards. It tries to fit everything in the paragraph on a single line, shapes (measures), then finds a line-break opportunity within the (potentially large) shape result which would "fit" on the line without re-shaping. Then given that line-break will reshape the entire line (using the "safe to break" API), (and remaining content for the next line), see if it will fit and repeats the process[1].
By always "removing" content from the line you end up with a correct implementation which works for all the crazy things which can happen with text rendering.
[1] The content in the line may become bigger after taking a line-break, hence this needs to happen in a loop until there is one "unbreakable" piece of content in the line. This loop typically only goes through one iteration.
div {
width:100px; height:100px;
aspect-ratio: 3 / 2;
}
This is all well specified and doesn't "break" the box-model in anyway. Anytime there is a definite width/height specified the box well respect that width/height. The aspect-ratio is lowest on the constraint priority list if you like.Internally in browser engines there was already an aspect-ratio for replaced elements, and these elements already had to (in a slightly different way) deal with width/height/min-width/min-height/etc. aspect-ratio was exposing and slightly generalizing what engines had already.
The example you give with allowing the width() function for margin, raises a lot of questions. E.g. you could have something like:
div {
width: auto;
margin: width(10%);
}
This gets into "difficult" territory very quickly (even more complex with calc/min/max/clamp/etc) as you'd need to try and solve a multi-variable equation. (Width depends on the size of the margins, and margins depends on the width).We expect it'll be ready for testing in a few months. However we expect that it'll be a bumpy rolling this out as table layout has a long history, and isn't exactly well defined :).
- Ian
(preview link might be more useful).
People also might be (1% prob.) placed into a "holdback" experiment group which has the old behaviour in M77.
- Chrome's implementation won't actually perform a raster at this stage, instead we'll raster later on a background thread. toDataUrl, etc will raster.
- We'll only invoke the paint method for things which we actually need to paint. E.g. if you have a long list, we won't invoke the method for things that are outside the paint window (things off-screen).
- We'll have the ability to add a bunch of caching later on. From memory the servo folks in their experimental implementation actually speculatively generated a bunch of images ahead of time.
- We are actively investigating moving this to a background thread. So even if your main thread is janked, an animation which triggers a paint worklet, will still run at 60fps.
edit - formatting.
The primary reason we did this is to ensure there wasn't a performance cliff if you did read-back pixels. With the current API surface you can record all of the canvas commands, and play them back when you need to raster. Additionally it doesn't leak how many pixels we are actually rastering to.
(hope this helps).
Edge put together a really great visualization of the API surface of all the browsers. - https://developer.microsoft.com/en-us/microsoft-edge/platfor... The API surface (and bug surface) is actually pretty different these days.
Internally Blink and WebKit are also diverging reasonably rapidly. As a specific example here is the project to re-architect how blink does it's painting: https://www.chromium.org/blink/slimming-paint
EDIT: spelling
Where you will see performance improvements is when developers create more expressive layouts/paints/etc. For example you can implement a grid layout with a bunch of nested flexboxes. You could also do it with the CSS Layout API. Because by using the CSS Layout API requires fewer divs, and maybe no N^2 layout passes, chances are it'll be faster.
But this really gets at the point of Houdini is to inform browsers/specs what is important. If a grid/masonary polyfill becomes widely used, then it will help inform CSS work.
It uses a serviceworker in the background to transpile es6-js requests into es5 transparently.
There is an endless array of divs which is absolutely positioned, ie:
<div id="container" style="top: -2920px"> <!-- endless array of divs --> </div>
The actual scrolling is performed by a 'dummy' div, has the same overflow. Some javascript will be listening to scroll events on this div, and updating the position of the above div.
This is typically done as scrolling 'floating' images on most browsers isn't smooth, & to 'jump' the scroll the correct amount to achieve the effect.