📜 ⬆️ ⬇️

Houdini: one of the most impressive CSS projects you've never heard of



Have you ever wanted to use any feature from the CSS standard, but you didn’t, because it is not supported by all browsers ? Or even worse: it is supported by all browsers, but is the support buggy, controversial or even incompatible? Surely you are faced with this, and therefore I recommend you look at Houdini .

This is a new W3C working group that has an ambitious task to solve the problem described above forever. This is planned to be done using a new set of APIs, which for the first time will give developers the opportunity to independently expand CSS, as well as provide tools for connecting to the process of creating a layout and applying styles in the course of the browser engine .
')
But what exactly is behind these promises? Is this even a good idea? And how will all of the above help us, developers, create websites today and tomorrow?

I will try to answer all these questions. But first I will clarify the current problems of today and the need to solve them. And then we will talk about how Houdini can help us with them, and consider some of his most impressive features that are under development. And in conclusion, I will make a number of suggestions on how the developer community can help the project Houdini.

What problems is Houdini trying to solve?


Every time I write an article or create a demo application to popularize some new CSS feature, I will inevitably receive comments like: “This is great! What a pity we won't be able to use it for another ten years. ” Although such comments are non-constructive and very annoying, I can understand the mood of the developers. It so happened that the wide dissemination of innovations takes years. And the main reason for this, as the web history teaches us, is to get new CSS capabilities exclusively through the standardization process.


Stages of the standardization process

I have nothing against standardization, but it takes too much time! For example, flexbox was proposed in 2009, and developers still explain that they still cannot use it due to insufficient browser support. Fortunately, this problem is gradually disappearing, since almost all modern browsers are updated automatically. But even in this case, there is always a delay between the offering of functionality and the general readiness for its use. It is curious that this situation is not observed in all areas of the web. Compare, for example, with JavaScript:


The stages of the introduction of polyfill

In this case, days may pass from the moment an idea arises to its use in work. For example, I already use the async/await functions in production, but this functionality has not yet been implemented in any browser!

Surely you have noticed a huge difference in the moods of both communities. In the JS community, you are reading an article in which someone complains that things are changing too quickly. And in CSS, everyone is moaning about the futility of learning new products, since it will take a lot of time before they can be used.

So why don't we just write more CSS polyfills?


At first glance, this is an obvious solution. Thanks to good polyfills, CSS could be as fast-paced as JavaScript, right? Alas, not so simple. Embedding polyfills in CSS is incredibly difficult, and in many cases this cannot be done without collapsing performance completely.

JavaScript is a dynamic language, so you can create JS polyfills on JS. Its incredible extensibility is due to its dynamic nature. And CSS is rarely used to create your own polyfills. Sometimes at the build stage, you can compile CSS code into CSS code (transpile) (this is what PostCSS does). But if you want to use polyfills for something that depends on the DOM structure, or for the position or layout of the element, then the logic of the polyfill will have to be executed on the client side. Unfortunately, browsers do not make this task easier.

Below is a basic diagram of the browser operation process, from receiving an HTML document to displaying pixels on the screen. Blue highlights the stages in which JavaScript can affect the result:


JavaScript access to browser visualization pipeline

Pretty dark picture. You, as a developer, do not control the process of parsing HTML and CSS, and then turn it into DOM and CSS object model (CSSOM). You do not control the cascade. You do not control the process of choosing the layout of elements in the DOM, do not control their color (paint) when displayed on the screen. Finally, you have no effect on the work of the compositor (composite). Only the DOM is completely under your control. You have some influence on CSSOM, but according to the Houdini website, this stage is “not sufficiently defined, it differs depending on the browser, and is also devoid of a number of critical features.” For example, today CSSOM will not show you the rules from cross-origin style sheets, while it will simply drop them if it does not understand. And this means that if you want to write a polyfill that adds functionality, you will be forced to bypass CSSOM. You will have to find the <style> and / or <link rel="stylesheet"> tags through DOM, then get the CSS yourself, parse it, convert it and then add it back to the DOM.

Of course, a DOM update usually means that the browser will then have to go through all the steps again: the cascade, the template, the coloring, and the layout.


Using JavaScript Polyfills in the Browser Visualization Pipeline

If you think that a complete redrawing of the page doesn’t have a big impact on performance, then remember how often this can happen. If the logic of polyfills has to be executed depending on such events as scrolling, window resizing, mouse movement, keystrokes — that is, with any change — then your site will run much slower, perhaps even indecently slowly. Everything looks even darker if you imagine that all modern CSS polyfills include their own CSS parser and cascade logic. And since these are very complex components, the polyfills turn out to be either very large or too large.

Summing up what has been said: if you want to force the browser to do something for which it, in its opinion, is not intended (including the CSS fed to it by you), you will have to think how to trick it using self-modifying the DOM. You do not have access to other pipeline stages.

But why would I even want to modify the internal browser engine?


In my opinion, this is the most important question of the whole article. So, if you have reached this point, then read on slowly and thoughtfully!

After the previous section, one of you thought: “I don’t need it! I'm just doing regular web pages, and not trying to hack the insides of the browser or do something extremely extravagant, experimental, or super modern. ” If you have been visited by such thoughts, then I insist that you postpone this text for now and carefully study the technologies you have used to create websites in recent years. The desire to access the process of applying styles in the browser is connected not with creating fancy demos, but with giving developers and framework authors the ability to do two things:


If you have ever used jQuery, then immediately got the benefit of using its features! This is one of the main arguments in favor of almost all modern frontend libraries and frameworks. For example, the five most popular JS and DOM repositories on GitHub — AngularJS, D3, jQuery, React, and Ember — are working hard to smooth the differences between browsers so that you and I don't have to think about it. Each of these projects offers a single API that works like a clock.

And now think of CSS and all these cross-browser problems. Even popular frameworks, like Bootstrap and Foundation, claiming their broad compatibility do not really solve the problem of cross-browser bugs - they just avoid them. But all these CSS bugs are not just pieces of the past. Even today, despite the use of new template modules like flexbox , we are constantly confronted with incompatibilities . Imagine how much easier it would be for developers if we could use any CSS properties and were confident that they work the same in every browser. Or remember all the great new items that you read about on blogs or heard at conferences and meetings — for example, grids , anchor points, and sticky positioning . Imagine how you could use them now, as easily as the native CSS features. And for that, you just need to copy a piece of code from GitHub.

All this is the dream of the Houdini development team. This is the future they are trying to create. And even if you do not plan to write CSS polyfills or develop experimental functionalities, you probably want others to do this. After all, if there are such polyfills, then everyone will benefit from it.

What functionality is Houdini currently in development?


I mentioned above that we have very few entry points to the browser page pipeline. In essence, this is just a DOM and, with a stretch, CSSOM. The Houdini development team introduced several new specifications that, for the first time, will provide developers with access to the other stages of the pipeline. These specifications are reflected in the diagram (the planned ones, but not yet implemented) are highlighted in gray.


New Houdini specifications for working with the visualization pipeline

In the following sections, we will briefly review each of these new specifications, analyze the possibilities they provide. A number of specifications in this article are not mentioned; you can find a complete list in the project repository .

CSS Parsing API


This specification has not yet been implemented, so everything mentioned below may change. The basic idea is to allow developers to extend the CSS parser and inform it about new designs. For example, about new media rules, new pseudo-classes, nesting, @extends , @apply , etc. As soon as the parser finds out about them, it will be able to place them in the right place in the CSSOM, and not drop it.

CSS properties and values ​​API


CSS already has custom properties, and I really like the features they provide. The new API takes this functionality to a higher level by adding types. This gives many advantages, the most important of which is that with the help of types, developers will be able to implement color transition and animation of custom properties (it is not possible to do this today).

See an example:

 body { --primary-theme-color: tomato; transition: --primary-theme-color 1s ease-in-out; } body.night-theme { --primary-theme-color: darkred; } 

The night-theme class is added to the <body> element, and now the color of all the individual elements on the page that refer to the value of the property --primary-theme-color will slowly move from tomato to darkred . So far, for this, you have to manually register the color transition for each element, since you cannot describe the transition for the property itself.

Another promising feature of this API is to register hooks (apply hook), which allows developers to modify the final value of the custom property of an element after the end of the cascading step. This is very useful in terms of using polyfills.

CSS typed OM


This functionality can be considered as the second version of the current CSSOM. It is designed to solve numerous problems associated with the current model, and includes features added by the new parsing API and the properties and values ​​API. Also typed OM is designed to improve performance. Converting CSSOM string values ​​to typed JS representations can lead to significant performance failures.

CSS Layout API


This API allows developers to write their own layout modules. And by the “mockup module” I mean everything that can be transferred to the display property. This will allow you to create a layout as quickly as with native modules, like display : flex and display : table . An example is the Masonry library. Developers have to resort to such tools if they want to create complex layouts that cannot be implemented by means of CSS alone. And although all these layouts look very impressive, their performance leaves much to be desired, especially not on the most powerful devices.

The layout API provides the registerLayout method, which gets the layout name (later used in CSS) and the JS class, which includes all the layout logic. Here is a simple example of how you can define masonry via registerLayout :

 registerLayout('masonry', class { static get inputProperties() { return ['width', 'height'] } static get childrenInputProperties() { return ['x', 'y', 'position'] } layout(children, constraintSpace, styleMap, breakToken) { // Layout logic goes here. } } 

If here everything looks incomprehensible to you, do not worry. The main thing is to look at the code for the following example. After downloading the masonry.js file and adding it to the site, you can write CSS in a similar style, and everything will work.

 body { display: layout('masonry'); } 

CSS Painting API


This API is very similar to the previous one. It provides a registerPaint method that works in the same way as registerLayout . After that, you can use the paint() function in CSS wherever the parser needs the expected image, passing the registered name.

A simple example of drawing a colored circle:

 registerPaint('circle', class { static get inputProperties() { return ['--circle-color']; } paint(ctx, geom, properties) { // Change the fill color. const color = properties.get('--circle-color'); ctx.fillStyle = color; // Determine the center point and radius. const x = geom.width / 2; const y = geom.height / 2; const radius = Math.min(x, y); // Draw the circle \o/ ctx.beginPath(); ctx.arc(x, y, radius, 0, 2 * Math.PI, false); ctx.fill(); } }); 

And in CSS you can use it like this:

 .bubble { --circle-color: blue; background-image: paint('circle'); } 

Now the element .bubble will be displayed on the background of the blue circle. This circle will be centered on the element and adjusted to its size, no matter what happens.

Worklets


For many of the specifications described, sample code is provided (for example, registerLayout and registerPaint ). This code will need to be placed in scripts - worklet 's. These are analogs of “web workers” (web workers), which allow you to import script files and execute JS code that can be executed at different stages of the visualization pipeline independently of the main stream.

Permissible types of operations in worksets will be tightly restricted for the sake of maintaining high performance.

Composited Scrolling and Animation


Although the official specification does not yet exist, but this is already one of the most well-known and expected features of Houdini. Probably, these APIs will allow the logic to be executed in the linker vorklet, outside the main thread, with support for modifying a limited set of properties of the DOM element. This set will include only those properties that can be read or changed without having to force the engine to recalculate the layout or styles (for example, transformation, transparency, scroll shift). All this will allow to implement very fast animation, based on scrolling or user input, like sticking when scrolling headers and parallax effect. You can read more about how to use these APIs on GitHub.

Despite the lack of official specifications, the Chrome development team has already begun to experiment. Using the primitives provided by these APIs, they implemented CSS anchor points and sticky positioning . This means that the Houdini APIs work fast enough to create new functionality in Chrome based on them. This fact should finally dispel your possible doubts about the performance of Houdini in comparison with the native tools.

You can watch a video made using the internal assembly of Chrome. It shows the header behavior when scrolling, similar to that implemented in the native Twitter mobile application. Also available source code .

What can be done now?


As I said, it seems to me that Houdini will be of interest to anyone involved in web development. This project is capable of making our life much easier in the future. Even if you never begin to directly use these specifications, you will certainly use tools built on their basis. And although tomorrow a bright future will not come, yet it is closer than many of you think. Representatives of all the major browser developers this year met to meet with the Houdini team in Sydney, and among them there was almost no disagreement on what or how to implement. As far as I know, the question is only in the timing of the completion of the work on Houdini.

Like all software developers, browser creators should pay particular attention to the new features of their products. And such priorities often depend on the degree of demand for new functions. So if you care about the extensibility of website styles and layouts, if you want to live in a world where you can take advantage of new CSS features without many years of waiting for standardization, inform those who are associated with the development teams of the browsers you use.

You can also help the cause by sharing with the community the possible ways of applying new products. Tell us what you would like to do with styles and layouts that today is difficult or impossible to do. For some drafts on GitHub , use-case descriptions are available, but you can, of course, create a pull request by sharing your ideas. If there is no suitable document, you can create a new one.

The Houdini development team (and the W3C as a whole) is really important to get an informative response from the web development community. Many of those involved in the specification process are engineers working on browsers. Often they are not professional web developers and do not always know about our immediate needs and difficulties.

Give them your opinion.

useful links


Source: https://habr.com/ru/post/282027/


All Articles