Hacker News new | past | comments | ask | show | jobs | submit login
Yoga: A cross-platform layout engine (facebook.com)
438 points by emilsjolander on Dec 7, 2016 | hide | past | web | favorite | 158 comments



One thing I've thought about recently is Facebook's Patent grants, and it's one thing that makes me uneasy about using any open source technology from Facebook like React (I currently do but am thinking to move to Preact because of the nicer MIT license and that it's analogous to React in many ways) because they're generally given a patent grant. I'm not a lawyer so I don't know if the grant would hold up in court since it's not actually in the license itself, only referenced in the readme but if I had a patent and Facebook infringed on it my license is terminated if I assert my patent rights against Facebook even if it is valid and doesn't pertain to specific React technologies. This has been discussed heavily in the past but suffice it to say it's pretty scary and bears thought.

This library looks very useful for those who use React Native or want a layout engine in C# or Java for their mobile app, but as someone who works in an industry (bio/chem engineering) who develops applications around tools in that industry and thinking that Facebook may one day enter that field, or even if we create a software patent for some idea we create while developing the tools, it makes me uneasy whenever a new Facebook open source project, especially one with the potential to become popular in a specific area of software development, is introduced.

Also, another thing to keep in mind is not every big company does this with their open source tech. For example, Angular and Visual Studio Code are both under MIT license.


This is one of the reasons companies seek patents, called a defensive patent strategy. The goal is to discourage competitors from suing you for patent violations by making sure you own a patent your competitors are likely to have violated. It creates a kind of "mutually assured destruction" that discourages either party from launching a patent war (this only works against real competitors, not against patent trolls, but it can still be a viable part of a company's IP strategy).

In the case you describe, what it boils down to is yeah, if your business intends to sue Facebook for patent infringement, you probably shouldn't be dependent on any of Facebook's IP or patents for your business. There are lots of things companies do to discourage other companies from suing them. Giving out free software is one of the nicer ways a company can choose to go about it.


Let's say I have a patent for a technology outside of React, and even outside of software, such as some hardware patent. Why should me suing for infringement of that patent preclude me from using React when it (the patent infringement and React) are completely independent?


Because facebook wants to avoid getting sued. React is their bat and ball so they set the rules. If you don't like the rules go and play elsewhere - it is not like there aren't hundreds of other frameworks you can use.


Because facebook said so in their README. Demands don't need to make sense but they need to be observed (whether that means respecting the demands or avoiding the people, the companies and the products that make such demands and thus not being affected in the first place).


Given that the trade seems pretty apparent, at least to me. "You can use our thing here for free but in exchange we might want to use one of your things later also for free", I have to ask why you don't think not agreeing to the latter half of the deal shouldn't preclude you from the former? I mean, that's how deals work.


Because you agreed to use the software facebook architected, developed, tested and publicly made available for you for free, in exchange for letting them use ideas you developed and publicly described for free.


There's a deeper issue here I think (IANAL). If there is anything in Facebook's patent portfolio that is indeed "a patent owned by Facebook that is necessarily infringed by the [React] Software standing alone," then using Preact, which implements the same functionality using similar algorithms, may very well infringe on that patent. And... if a release of your software does not use React itself in favor of Preact, you were never given a license in the first place to that patent, so you'd be even more vulnerable to Facebook enforcing their IP rights!

If you sue a company with competent lawyers, their defensive patent portfolio will be unleashed on you to the greatest extent possible, whether you intentionally infringed or not. If you use technology similar to Angular and sued Google, you'd be in a similar position. Facebook's patent grants simply codify this, and so they've taken the blame for something that was always hanging over every developer's head with any patented software anywhere.

https://en.wikipedia.org/wiki/Software_patents_and_free_soft...


This project is under the BSD license, which is equally silent about patent rights to the MIT license, making it ambiguous whether it applies to patents. The patent license is on top of that; Facebook's approach is basically strictly more permissive, patents-wise, than typical use of the MIT license. (But not as permissive as the Apache 2 license, which contains explicit patent grants with a "don't sue us" condition that only applies to the specific software being licensed.)

Well, there's some argument that including a patent license makes the other license less likely to be construed as implicitly extending to patents, even if it says "additional". But you really shouldn't be depending on either the MIT or BSD license counting as a patent license.

See also: https://writing.kemitchell.com/2016/09/21/MIT-License-Line-b...

Edit: I misremembered the scope of the Apache 2 patent license, sorry.


That's fair, and I respect Facebook's want to have specific patents language in their licenses. But my main fear is that the language is too broad and taken at face value wouldn't allow any kind of patent infringement to be fought against, regardless of its merits. I also wish that the language was in the license itself rather than as a separate grant because it's potentially confusing. I had a friend I was telling this about didn't know about this at all, and said he's happy that his company has lawyers that review this stuff because he would just copy the license without the separate grant and be done with it, which wouldn't suffice.


Maybe I'm misunderstanding the license terms but I feel like this is a bit of a "Maserati Problem", at least, if you are not competing directly with Facebook. If you are worried you might want to sue Facebook for patent infringement some day, you could still use React today and switch to Preact or some other library "just in time".


Just because you are not competing with Facebook today does not mean that Facebook will not be competing with you tomorrow.


I am curious to hear of anyone who has reviewed this license with their lawyers / legal departments and received a positive, non-cautionary response to go ahead and use the software and libraries covered under it.


Google hasn't specifically said they're using React (which uses the same terms on the patent licensing) but they did review and suggest changes originally and have stated that the current license meets their needs.

There are other companies (I would be betraying confidences to list who) that have looked at it and decided not to use it because of the strong retaliation clause. I should elaborate that those companies are not planning to sue FB as far as I know, but they want to preserve the opportunity to do so (i.e. they don't want to de-weaponize their patent portfolio with respect to FB).


I'm not able to name names, but legally speaking, it's no worse than MIT or BSD. Sure, there's a retaliation clause, but that's just affirmation of what companies who publish with the others aren't telling you.

In effect, it's more, not less, permissive and honest. INAL, but that's what I've been told by one.


The React wiki has a non exhaustive list of users[0] which includes some rather large companies (BBC, Airbnb, Automattic, Atlassian, eBay, Netflix, etc.). I presume most of those larger companies had their legal departments approve its use.

[0] https://github.com/facebook/react/wiki/Sites-Using-React


That may be the case, but I personally would be surprised. My impression is that most companies don't do a good job of managing and monitoring dependency licensing.

I have seen tooling that analyzes licenses, but not for node or client-side javascript. Maybe I'm just in the dark.


That may be true in general but the React license has generated a lot of buzz. If you look at pretty much any Facebook project posted on HN, you'll find that one of the top comments is about the license. Also, the decision to use React is impactful enough that I'd expect most tech CTOs to know about it. I grant you that some might not take the license issue seriously enough to discuss it with legal counsel.

To answer your original question, I found this statement by Automattic's legal counsel[0]:

> “Automattic looked at the legal issues with Facebook’s patent license on React,” Sieminski said. “The termination provisions of the patent license aren’t ideal, but are not a blocker to using React as part of Calypso.”

[0] https://wptavern.com/automattic-will-continue-to-use-react-j...


FYI, my React/Redux links list has a section pointing to discussion on the PATENTS license, including Facebook's official FAQ on the topic: https://github.com/markerikson/react-redux-links/blob/master... .


Yes, given two libraries A and B, which are equal in all respects except one is encumbered with vague licensing talk, pick the one without! It's a good engineering practice, and it will ensure that we, as a community, evolve towards zero-licensing libraries.


Except two libraries A and B are never equal in all respects.

A library might have a stronger community or better documentation than the other. They might be equivalent today but evolve differently in the future. Etc.

The choice between two libraries is never that easy.


Both React and hypothetical library B are encombered with possible Facebook patents. Only by using React are you assured that you aren't going to be in patent infringement with Facebook's patents given they provide you a license for React. By using Preact, you have no such patent grant.


What's a hypothetical scenario that would be a problem?

I assume your company is not developing UX patents and the concern is more around developing a suite of products that use a FB library and dealing with unexpected costs or restrictions?

I would hate to avoid using what I thought were the most productive tools in anticipation of a very unlikely event. You'd essentially be paying a productivity penalty now, to try and avoid a productivity penalty in the future if you have to rewrite something.

The odds of a company like yours in a vertical getting sued by Facebook I would guess are vanishingly small.

Now if your core IP competes directly with FB I can see a little more risk because they could plausibly have strategic reasons to make your life difficult as well as a potential damages claim. However this would be a special case for only certain companies to worry about.


"if I had a patent and Facebook infringed on it my license is terminated if I assert my patent rights against Facebook even if it is valid and doesn't pertain to specific React technologies."

Do you have a patent that Facebook might infringe on?


Please do not spread FUD, or at least clearly explain your worries. The patent clause only applies if you sue Facebook for patent infringement in React itself. It's a very clear defensive policy. Despite all the breathless blog posts claiming that you can lose your license for "competing" with Facebook, it is not true.

https://code.facebook.com/pages/850928938376556


I never said that you could lose your license for competing against Facebook, I said that you could lose your license if you have a patent and assert it against Facebook if it infringes. This is the patent grant from React, which is identical to the grant in the post's repo as well. The language in the patent grant is pretty clear and doesn't mention anything about React specifically:

The license granted hereunder will terminate, automatically and without notice, if you (or any of your subsidiaries, corporate affiliates or agents) initiate directly or indirectly, or take a direct financial interest in, any Patent Assertion: (i) against Facebook or any of its subsidiaries or corporate affiliates, (ii) against any party if such Patent Assertion arises in whole or in part from any software, technology, product or service of Facebook or any of its subsidiaries or corporate affiliates, or (iii) against any party relating to the Software. Notwithstanding the foregoing, if Facebook or any of its subsidiaries or corporate affiliates files a lawsuit alleging patent infringement against you in the first instance, and you respond by filing a patent infringement counterclaim in that lawsuit against that party that is unrelated to the Software, the license granted hereunder will not terminate under section (i) of this paragraph due to such counterclaim.

Also, your link doesn't actually dispel any fears I have. It specifically doesn't mention about if I sue Facebook for patent infringement if I have a valid patent that Facebook infringes upon, which is the main basis of my argument and worry.


If you name React in your patent lawsuit against Facebook, your license for React is terminated. Other software licenses remained unaffected.

That seems like a pretty reasonable stance for distributing an open source project.


Both you and grandparent are wrong. I have consulted with lawyers on this (and the language is pretty clear as well). If you initiate a patent lawsuit against FB on any grounds, you lose patent protection for this library (or React, Reactive-Native, etc -- they share the same patent licensing terms).

If you counter-sue FB after they have initiated a patent suit against you, you are ok, as long as your counter-suit does not cover patents you were licensed via using React, Yoga, etc.

This type of patent language is called a "strong patent retaliation clause." What you are describing also exists (Apache uses it) and is called the "weak patent retaliation clause." They are not the same.


It doesn't matter if you use React or not. If you sue Facebook, they can sue you for any patents they hold.


Of course, but having to stop using React as a result would be deadly for a company that built its company on it. :)


It doesn't matter if you use React or not. If you infringe on any of facebook's patents and go after them, they can counter sue.


If I am using React/Yoga/etc, and have a patent on FooTech, and Facebook starts using it tomorrow without license, and I sue them, then I have tripped clause (i).

The license granted hereunder will terminate, automatically and without notice, if you (or any of your subsidiaries, corporate affiliates or agents) initiate directly or indirectly, or take a direct financial interest in, any Patent Assertion: (i) against Facebook or any of its subsidiaries or corporate affiliates

At that point, I am infringing any patents that FB have on all of {React/Yoga/etc}. Thus opening myself up immediately to a counter-patent suit, even I infringe no other FB patents.

tl;dr any patent suit initiated by me (troll or legitimate), revokes all the patent grants for every FB product using this license.


It doesn't matter if you use React or not. If you sue Facebook, they can sue you for any of the patents they hold.


IANAL but isn't the text quoted above also saying that except if initiated by Facebook suing you over a patent first, any patent lawsuit against facebook will terminate your license? It's listing "(i), (ii) or (iii)", not "(i), (ii) and (iii)".


I made a similar library earlier this year. It builds as C or C++ and is only two files (MIT license): https://github.com/randrew/layout

The API is similar to Yoga. I hadn't seen Yoga before, and I'm surprised at how similar it is. It seems like Yoga is about the same age (or older?) than my Layout library.

It's meant to be easily embedded into existing software, such as game engines, OpenGL-based tools, custom GUI libraries, etc. without requiring its own complicated build system. Its API and layout engine seems to work in a way similar to Yoga, but it doesn't have pre-made bindings for any existing GUI toolkits. There is, however, an example binding for the Lua scripting language.

API comparison:

Yoga:

    YGNodeRef root = YGNodeNew();
    YGNodeStyleSetWidth(root, 500);
    YGNodeStyleSetHeight(root, 120);
    YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);

    YGNodeRef image = YGNodeNew();
    YGNodeStyleSetWidth(image, 80);
    YGNodeStyleSetMargin(image, YGEdgeEnd, 20);
    YGNodeInsertChild(root, image, 0);
Layout:

    lay_context ctx;
    lay_init_context(&ctx);
    lay_id root = lay_item(&ctx);
    lay_set_size_xy(&ctx, root, 500, 120);
    lay_set_contain(&ctx, root, LAY_ROW);

    lay_id image = lay_item(&ctx);
    lay_set_size_xy(&ctx, image, 80, 0);
    lay_set_margins_ltrb(&ctx, image, 0, 0, 20, 0);
    lay_insert(&ctx, root, image);
The Layout library can handle laying out tens of thousands of items in a few microseconds, so I would expect Yoga to have similar performance. (Layout is meant to work stutter-free and waste-free with layouts that could be animated or changing every frame in a game engine.)

One major difference I noticed, though, is that Yoga seems to allocate for each individual node, whereas Layout uses a single resizable contiguous buffer. This is gives it pretty good CPU cache performance (writes are all in their own separate region of the buffer) and allows you to do complete rebuilds of the layout hierarchy without any heap allocations. It's nice if you have a dynamic layout and want to keep the layout calculations fast/cheap. It might be interesting to do benchmarks of the two libraries in different scenarios.

Are there any other libraries similar to Yoga and Layout?


Hey, this looks really good - I'll give a shot at using this in MOAI! Thanks for that!


Thanks. Leave a message or issue on GitHub if you have any problems and I'll try to fix it. I've only used it in my own software, so there's a chance you will encounter some shortcoming or bug that I haven't.


I like the concept and the C# code is just hands down the best example out of all of them (yet another reason I miss coding in C#).

I'm curious though, will this be eventually ported to JavaScript? Yeah yeah I know "flexbox is already on the web!" but if you could write a layout in this fashion versus using style sheets then you could take it and directly apply it to any of your applications (even if you have to convert between languages the exact same setup is still there it's just a straight up conversion).

Overall cool idea and implementation. Curious to see where it goes from here.


They totally could have done it clean like this for Swift and I struggle to understand why they did it in the old Obj-C way: extension methods with yg_ prefix, static constants instead of enums, unnecessary configuration after instantiation.


I just happen to be more familiar with obj-c :) I agree that a swift API would probably look very cool. Would be fun to see this come from the community.


> will this be eventually ported to JavaScript?

It has been ported already.

https://www.npmjs.com/package/css-layout

Oddly enough there's no git repository. Only the npm package has the pure JS code. And the last release was from last year. Fortunately it looks it was easy to port, if one needs a more recent version.


It's actually the exact opposite flow ;)

css-layout is the original project, it was written in JS and then automatically translated into Java & co. It had some bugs, and Facebook rewrote the thing directly to a native implementation but decided to drop JS as they were not using that variation internally. This is a shame as I love CSS-layout for calculating tween points in layout animations on the web. FB said at this point they have no plans for an official JS port of the new version aka yoga.


Bummer. I was using css-layout to lay out svg elements[0]

[0]: https://kentor.me/posts/creating-diagrams-with-react-svg-and...


I'm not sure how you're supposed to use this from C# in real life, though.

Ok, you have a layout engine. For what widgets? Windows.Forms? WPF? Xamarin Forms? Can those even use a third party layout engine?

I'm slightly confused :)


To be honest, I'm a .NET developer and I'm not entirely sure either. None of the tests they wrote show any integration with existing widget engines.

One thought I had is that one could use this layout engine to do the calculations for the positioning of visual objects on the screen, but you would have to essentially build a fully integrated layout manager that renders to the particular framework you're using. Maybe overridding the hooks for existing layout managers that come with the particular UI framework (for example, WPF has layout managers).

For example, in WinForms, if you build the UI programmatically rather than old fashioned drag-and-drop, you could set X/Y positions, widths/sizes etc. per the constraints generated by this engine. Needs to be observable/reactive so the UI changes are fed back into the engine and then the UI automatically changes - much like existing layout manager tech.

Perhaps doing this work/exercise was left to the open source community/reader. There aren't any examples/tests showing how to integrate this layout manager with any existing .NET UI widget frameworks. It looks like they wrote the integration with .NET in C# (on MacOS as well), and tested the layout engine itself, but that's about it.

EDIT: Possible hooks for old WinForms maybe? https://msdn.microsoft.com/en-us/library/z9w7ek2f(v=vs.110)....


Also Microsoft is using Yoga (previously known as css-layout) in React Native for Windows: https://github.com/ReactWindows/react-native-windows


I agree the C# code is super nice :) There is interest from the community to contribute an emscripten version. If a PR comes my way I will be happy to merge it.


I found it kind of ironic that their tests in .NET for the C# code only run on MacOS currently! :) So hard to remember that finally we are in a world where that is possible.

"We have a script which to launch C# test on macOS, csharp/tests/Facebook.Yoga/test_macos.sh."


I believe the canonical JS implementation is (or will be?) https://github.com/jordwalke/ReLayout - written in Reason and compiled to JS via Bucklescript. Lots of very nice reasons and benefits for this, including readable JS with good performance.


Hi, I'm one of the contributors to ReLayout. I originally worked on ReactJS, and ReactNative which made use of Yoga (then, css-layout), and now I'm working on Reason and ReLayout (which is a port of Yoga to Reason). I definitely wouldn't call ReLayout the canonical way to compile Yoga to JS. While we intend to keep ReLayout up to date with the Yoga implementation, we're ultimately doing this because we'd like to experiment with combining ReactJS's API, the new Fiber architecture, with a deeply integrated Flex Box layout algorithm. Feel free to message us if you're interested in tracking the results of the experiment, but but for now, I'm just excited to see Yoga launch. The Yoga project and team have been incredibly helpful with our experiment and I'm excited to see more apps integrate Yoga going forward. Congrats! I can't go back to not using FlexBox now that I've gotten hooked on it. (edited: Formatting)


Hopefully it does get ported to javascript. In the meantime, if you happen to use react, https://github.com/necolas/react-native-web is a good way to use react-native's styling approach (which uses css-layout under the hood) on the web.


Just curious, when/why would you want to code UI layout in C# vs using a template ?


Hmm good question. The last time I did C# I did a little WPF and mostly Win or Web Forms so I'm not sure what the state of creating GUIs with C# / .Net is. If this technique affords me better cross platform support then it likely makes sense to use it but as far as using it versus a template I'm not really sure.


XAML is the state of the art, which is cross-platform thanks to Xamarin.Forms.


c# is generally for back end logic. UI's are generally done using templates on web/wpf/winforms platforms. Especially on the web it makes little sense to do layouts in c#


I wonder why they didn't use new in C#, maybe they are under realtime constraint with unity on oculus and they use a pool.


> I'm curious though, will this be eventually ported to JavaScript?

Here's a similar but seemingly dead project:

http://gridstylesheets.org/


I'd prefer it the other way around. CSS is already ubiquitous, would it be possible to make an implementation for a cross-platform tool?


You might be able to accomplish this with emscripten, which is pretty capable. You'd need appopriate bindings to have it control the DOM


> will this be eventually ported to JavaScript?

It's already cross-platform; cross-language would probably be a little much to ask :)


> It's already cross-platform; cross-language would probably be a little much to ask :)

I'm not sure I follow; it's supported in multiple languages already. Am I missing something?


Okay, question: can it perform the following task elegantly?

Say, I build a declarative tree describing a layout, and I render it. Now I remove one item from the tree. Can the layout engine efficiently remove the item from the view, and... (now it comes) provide an animation for it? As in, the item slowly losing opacity, then the surrounding items moving closer together? (Or a different animation depending on settings).

Of course, the opposite should also be possible (i.e., inserting an item).

Implement this, and we're a step beyond CSS, because so far this has not been possible (elegantly) in CSS. I.e., remove the element from the DOM tree, and it is gone immediately (without the animation). And no amount of CSS can fix this.


One motivation for reimplementing a layout engine for React Native was to solve this exact problem that CSS doesn't address.

We have LayoutAnimation inside of React Native which lets you do that. It's not very well documented and the delete method is not implemented, but the idea is there :)

https://facebook.github.io/react-native/docs/layoutanimation...


Yoga itself does not handle animation but by using another animation system on top of Yoga it should be very possible. I have not yet tried it myself but by wrapping a layout change in a UIView animation block the above should be doable (on iOS but similar should hold on other platforms).


Interesting. Could it be done efficiently? I.e., without walking the complete tree on every update?


It's platform specific, as I understand Yoga, it's just a nicer way to write UI code as I see it. On iOS for example, you should totally be able to wrap it be able to wrap Yoga code in existing animation engine, like UIView animation, layer animations and UIKit dynamics. So it'll be as efficient as the system its running on implemented its layout and animation engine. In the case of iOS, it would be amazingly efficient.


Animation effects like this are more annoying than anything else, anyway.


No it's not, nicely done animations, and I'm not saying over the top animation, can ease context changes for example. It's better to have an object moving to its new place than to have an object disappear and reappear somewhere else on the screen.


Over the top example: Mac mail, when sending email send the window "over the top" of your screen. As mentioned above, it's not the effect, it's the purpose. Better to not animate and be considered "lazy" or "inelegant" than to over animate and annoy.


Yoga's layout API is very similar, if not a direct copy, of the web's Flexbox. Which funny enough means that we might get a chance to use Flexbox on the desktop before we can use it on the web. (I'm looking at you IE and your continuing partial support: http://caniuse.com/flexbox)


Yes, it's directly based on CSS Flexbox. See more info about the similarities and differences here – in particular a few default values are different:

https://facebook.github.io/yoga/docs/learn-more/


Is there a plan to add support for the extensions (especially AspectRatio) in React web? I would greatly welcome them.


The link[0] to GitHub from the hamburger menu on this page results in a 404.

[0]: https://facebook.github.io/yoga/http://github.com/facebook/y...


Thank you for providing these excellent docs from day 1. Can I suggest that you change the background color of the flex item in the jsfiddle example of the default values, https://jsfiddle.net/emilsjolander/jckmwztt/, to something besides white as it took me a moment to realize that I was looking at a flex item as white backgrounds are very common.


I already use it in production. I don't really care about old IE users. I agree that not all devs can afford this, but many can.


Parent was referring to the current version of IE which still has partial support. I wish it were better supported today. It would sure make my life easier.


If you use autoprefixer you can reliably use flexbox, with a few minor exceptions which, IMO, aren't huge dealbreakers.


Fair enough I've just kinda avoided things not supported fully in evergreen browsers when I can. I should probably re-examine that more often.


In my experience it's "good enough". I just shipped a production site with all flexbox layouts and we had to support IE11. I found that the trick was to avoid the shorthand flex attribute and use the explicit flex-* attributes instead.


A lot of real-world usage of flexbox is broken that has nothing to do with IE/Edge. Follow the "Known issues" tab on your caniuse link. Also see Flexbugs [1] for more. I get bitten by #11 and/or #14 on almost every project, which work fine in IE/Edge.

[1] https://github.com/philipwalton/flexbugs


Wow, thanks for the link. I use flexbox for layouts and usually can get away with fiddling with wrappers and such until it looks right, but I can easily see myself losing at least a half a day to each one of the bugs on that list. :)


ReactNative uses Yoga for it's layout. There's an OSX port already in progress, so cross platform Desktop apps using Yoga isn't that far off ;)


I wouldn't hold my breath waiting for IE to fully support it.


Uh, Edge already fully supports it. I don't think they are adding new features to IE anymore.


You bring up a good point, in Windows 10 Edge is already the default browser. My comment is more joke then anything substantial. I think realistically anyone who isn't targeting enterprise could use Flexbox and be fine most of the time.


Cool to see Facebook release code in C! I clicked the "C" tag in the blog post, and this is the only post referencing C. Heh. Anyway, finally code from an Internet Giant in a language I care about enough to go and take a look at.

It seems ... smallish, which was a pleasant surprise. The core Yoga/ folder contains six files which is certainly fewer than I expected.

Didn't have time to do a full read-through, but one thing that I couldn't ignore is the use of a pointer-hiding typedef for the core layout node:

    typedef struct YGNode *YGNodeRef;
I'm really opposed to "hiding the asterisk" in C, since whether or not a thing is a pointer typically matters, and code becomes harder to read when you need to think about this more.

Even stranger, though, is that then most function protypes look like this:

    void YGNodeMarkDirty(const YGNodeRef node);
So, you have a function called "mark" which really sounds like a mutating, modifying, operation. But it's declared to take a constant node reference!

Peeking at the code, what it does boils down to:

    if (!node->isDirty) {
      node->isDirty = true;
      ...
    }
So it really is modifying, there's no trickery involved (like having node be a handle or indirect reference). It then recurses upwards through the chain of parent nodes, like you'd expect.

This works since the "const" here doesn't apply to the pointed-at object (it's distinct from the un-typedef:ed version "const struct YGNode * node"), it applies to the reference.

So the code jumps through these hoops and adds a const to the external interface, which doesn't matter, all it does is say "yeah, this function won't re-assign the reference variable to point at something else". Which, in my opinion, is not very useful information, as opposed to "this function doesn't write to the object you pass in" which you'd get with the non-asterisked version.

Can anyone shed some light on why one would do this?


I'd guess that its because changing the value of the *Pointer would actually be a bug, and const args are used to catch these kinds of bugs...


Why not use parallelism? Parallel layout tends to be a major speed boost in our experience, and we have a parallel implementation of flexbox already. See Meyerovich 2010 [1] for the basic idea; you can adopt it to flexbox relatively easily.

Additionally, I'm a bit skeptical about the use of C here: this stuff tends to end up exposed to the user and security-sensitive.

[1]: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.207...


Parallelization is something that I've wanted to do for a long time and as you mentioned, flexbox is well suited for that :) Would love for someone to try and implement it!


For React Native, at least, I think the threat model is a little different. Browsers have to deal with any hostile webpage, so all input can be considered hostile to something like the layout engine -- but here, you're baking the application along with the engine and shipping it wholesale. But I guess it depends on the details of how Yoga actually integrates and what its surface area actually is.

That said, I think the more likely conclusion for security vulnerabilities is the one you allude to, where people will probably end up reusing this component elsewhere and exposing the engine to potentially hostile input somewhere along the line, and it might not end well.


Right, it's not an issue with React Native. My concern is that people will end up using this in browser-like settings with untrusted content. Do they adequately guard against stack overflow with deeply nested layouts, for example?


Why not just embrace Cassowary (https://en.wikipedia.org/wiki/Cassowary_(software)) aka the algorithm behind Cocoa's Auto Layout? Auto Layout isn't perfect but I think that it's fundamentally the API/UI that you are working with, the concepts are definitely at the right level of abstraction. Some sort of DSL could really solve this.

Flexbox could be implemented as a framework on top of this.


Pete Hunt, one of the original developers of React at Facebook, began work on a Cassowary-like layout engine at one point and came to the conclusion (whether rightly or wrongly) that arbitrary constraint-based layout is too user hostile to pursue further.

I too like constraint-based layout, but I have to admit flexbox is nice in that it has very predictable behavior. The main hangup I have with flexbox is that it doesn't allow for layout based on aspect ratios, but Yoga has extensions that resolve this issue.


> Pete Hunt, one of the original developers of React at Facebook, began work on a Cassowary-like layout engine at one point and came to the conclusion (whether rightly or wrongly) that arbitrary constraint-based layout is too user hostile to pursue further.

I think that pg's point #2 from this post applies

http://paulgraham.com/javacover.html


Off topic but I read #2 and I can't for the life of me think of why he would consider Cobol a bad language, perhaps he has no personal experience with it.


There are some mentions here

http://paulgraham.com/popular.html

"It is a mistake to try to baby the user with long-winded expressions that are meant to resemble English. Cobol is notorious for this flaw. A hacker would consider being asked to write."


(Original author of css-layout here)

I've spend a few months playing with Cassowary before working on css-layout and had long chats with its creator Greg Badros and the people behind https://gridstylesheets.org/.

Cassowary underlying abstraction is a linear inequation solver. So you give it a bunch of constraints of the form ax + by + cz + d < 0 and it's going to give you values for x, y and z.

## There are two innovations in Cassowary:

1) There's a concept of strength (required, strong, medium, weak) which allows you to define which rules should be dropped in case of conflicts. This is a very different way to think about building UI and was a really fun exercise.

That said, I had to build a dedicated tool to show me which rules where overridden or why otherwise it was very hard to understand what happened when the layout didn't work as I expected.

2) Cassowary is an iterative solver, this means that it's not going to recompute the entire simplex from scratch on every tiny update.

## The biggest issue with Cassowary is that you cannot express everything with a linear system of equations:

The most annoying instance is line breaking. You cannot encode how lines are going to break as a set of linear inequations. In practice, what happens is that you're going to "fake it" by iterating outside of the simplex by first giving it a rough size and then do another pass with the real one. It usually works but you are not guaranteed for it to converge nor to have the optimal layout.

## In practice

It's extremely painful to write all the inequations yourself. If you want to have a container with an item of height 100px with 5px of padding it looks like.

    obj.left = parent.left + 5
    obj.top = parent.top + 5
    obj.right = parent.right - 5
    obj.height = 100
    parent.height = obj + 5
For every single object you need to define 4 inequations to "define": top, left, width and height which is very verbose.

So I started writing abstractions for containers, padding... At some point, I realized that I was just reimplementing flexbox. But it was a worst implementation of flexbox because it didn't properly work with text and was way slower.

The other difficulty is that you need references to all those elements. In order to tell where an element is, you need a reference to your parent. This model doesn't work well with React components where you only shouldn't know about your parent.

## Where it shines

The places where constraint solver shines is when you have a wysiwyg element builder. You have a reference to all the elements as they are visible on-screen so it's very easy to link them and you can show 4 inputs for each constraint.

This is very useful for xcode interface builder and would be a good fit for designer tools like photoshop.

Hopefully this gives some light around why we didn't proceed with cassowary :)


Hey vjeux! I'm sure everyone here on HN would really love the story of how you first implemented css-layout.

You had a really inspiring use of fuzz testing and TDD. You used a hilarious technique to implement it in several languages at once. And I heard a rumor you did it all over your paternity leave?!


HN Comments are ephemeral... this would make a nice blog post!


They may be harder to find, but HN comments are probably less ephemeral that most blogs (that is, HN comments are more long-lasting and at the same "permalink"... seems that plenty of blogs fall off the internet after a few years).


> There's a concept of strength (required, strong, medium, weak) which allows you to define which rules should be dropped in case of conflicts. [...] That said, I had to build a dedicated tool to show me which rules where overridden or why otherwise it was very hard to understand what happened when the layout didn't work as I expected.

That sounds like "strength" was probably the wrong approach. Why not require the developer to simply resolve conflicts? Your set of inequalities are a basic type system and you tried to resolve your type errors by layering some secondary weird "overriding" type system over top. Better to just resolve the errors from the get-go, and when it compiles, you know it will run correctly.

> The most annoying instance is line breaking. You cannot encode how lines are going to break as a set of linear inequations.

Is this discussed anywhere in more detail? It doesn't sound right to me, unless I'm misunderstanding what you mean here.


For 1), those are not bugs but to simulate if then else. If the width is < 800, then do that, else do that. Then problem is that if then else is not linear so you can't express this. What they do is to put bigger weights than anything so the minimization function is going to pick them instead. Because it's using different orders of magnitude, you can only have a few of those categories (4 in this case), afterwards you run into numerical precision issues.

2) The height of a text is not a linear function based on the width of the container. You can't say, the height of the text is 10px * number of characters * width of the container.

Instead, if you add a single more character that makes it go to the next line it's going to add a single lineheight.

So, you can't encode this inside of the simplex and you need to do it as a separate pass.


> Then problem is that if then else is not linear so you can't express this.

It sounds like a limited set of discontinuous functions are needed, like how media queries are used in CSS. The constraints to satisfy are defined by a set of top-level discontinuous functions on environmental parameters, but the set is always fixed so it's pretty simple to detect when you need to switch to a different set of constraints. Wouldn't that suffice?

> The height of a text is not a linear function based on the width of the container. You can't say, the height of the text is 10px * number of characters * width of the container.

For simplicity, let's take the easiest case of a fixed width font and we'll hard wrap at X characters, regardless of whitespace positions. The number of lines L and the height of the text H in px is then given by:

    L = char_px_width * char_count / container_px_per_line
    H = L * char_px_height
Agreed? If so, then that case isn't difficult, but difficulties arise when you want better wrapping behaviour based on whitespace with a non-fixed width font. I agree that doing it precisely with linear equations doesn't seem feasible, but it seems like we can closely approximate it to minimize the reflows needed to converge on the final result.

Suppose we set char_px_height=the widest character of the typeface (ditto for char_px_height) so we overestimate the dimensions needed. A quick google search suggests that the average word length for ordinary English is around 5 characters. So with avg_word_length=5, the above equation changes to something like:

    L = char_px_width * avg_word_length * ceiling(char_count / avg_word_length) / container_px_per_line
This should miss the actual number of lines needed at most by 1, except when dealing with highly irregular text. Then again, the avg_word_length can be constantly adjusted on the fly based on the reflows you have to do, so this should quickly converge too. Does this sound right?

Edit: sorry, that last calculation is obviously wrong, I was rushing out the door. The idea is to estimate number of lines from the average nnumber of words that would fit per line.


Android has started embracing it with ConstraintLayout. It implements a Cassowary solver in order to resolve the constraint imputed by the dev.

I have been using it for some time and it is an huge step in the right direction.

A downside of Yoga seems to be its tooling, ConstraintLayout is very well integrated with Android Studio. Actually they created it hand in hand with a rewrite of its layout editor.


I think you're thinking of RelativeLayout? I don't have ConstraintLayout in my IDE right now, but RelativeLayout sounds like what you're talking about.


Nope, I am refering to ConstraintLayout. RelativeLayout does not use Cassowary (even though for an API consumer, this is just an implementation detail).

Actually, CL one of the reasons behind the creation of RL is to improve on RL : - remove the need to nest for complex layouts. Nesting has some intrinsic measure/layout overhead. CL solves this by allowing way more types of relative constraint. The only remaining reasons for manual ViewGroups are performances (still faster than any generalistic approach) or really deep customization.

- solve some of RL qwirks. There are a couple of behaviors which are surprising. CL streamline these corner cases.

- deeper layouting possibilities

- integrated with a better layout editor. By better, I mean something you might choose to use, unlike the previous layout editor.

CL is in beta right now, you can add it as an external lib (that way the android team can update it anytime they want). The layout itself is already useable in production, the layout editor is where there are still some potential bugs.


This is incredible! is this going to be paired with a wysiwyg tool... because i have a feeling that writing the constraints is going to get frustrating very quickly.


It is already : https://developer.android.com/studio/write/layout-editor.htm...

The previous layout editor was pretty much unusable. Even though XML is ugly it is still efficient to work with (especially since the IDE auto completes all the cruft), so almost nobody was using the old layout editor.

The new one is still in beta and has some rough edges but it sounds like this will actually be useable and maybe even faster than editing the XML in some cases.


AutoLayout basically directly exposes that algorithm and all of its complexity to the developer. That makes it the most powerful, but also the hardest to learn. Flexbox is a nice middle ground where you can express most things in a sane manner, but it's not the single layout engine to rule them all.


Speaking as someone coming from the web, auto-layout is really awful. You're way better off making UI easy to reason about for web developers transitioning to mobile, because that's where most of the talent comes from. By DSL, do you mean something like HTML/CSS? React Native basically has this with JSX and style properties which use Yoga under the hood.


I have a web background myself, but I always found auto layout a pleasure to work with. I use it with http://snapkit.io/docs/ (a DSL built on top of the iOS APIs) and with programmatically written UIs. I find it so much easier to reason about than CSS.


Is it just me or does anyone else also feel a bit left behind by this?

They say it has bindings for Android and yea, I can generate these Yoga objects in Java but how exactly would I integrate this with my Android view hierarchy? Do I need to use React for that? The documentation says exactly nothing about this.

What's the piece of information that I'm missing?


> Yoga also does not support styling properties that have no impact on layout, such as color or background properties.

Does that mean that Yoga is too low level to be used directly by application developers? Who's the intended audience?


Yoga is a Layout engine, not a UI or graphics engine. It's output is basically just the size and position of those objects put into it. So you'd need a bridge to use it for existing UI systems or build a new UI system on top of it (just like what React Native did).



I'm especially happy to see the C in CSS go away.

Flexbox and the explicit inheritance used in react native makes styling so much nicer.


Very, very interesting - curious about whether the C# bit supports Xamarin on iOS and Android, or if the C# piece is just Windows-only (not super clear from the documentation).


I'm not very familiar with Xamarin but I think it should work. If it doesn't please file an issue on the repo.


How do you see it being used? I'm especially interested in the C# widget toolkit you used this with, if any.


I haven't worked much with the c# bindings myself. It should be able to integrate into most widget toolkits fairly seamlessly I would think.


Curious how using this for a complete page layout "feels" to someone who's familiar with designing websites. Since flexbox is intended for 1-dimensional layout only (as opposed to the old-school display:table or the forthcoming Grid spec, which are intended for 2-dimensional layout), I wonder what they do to make it work well for the full page / screen layout (in terms of ease of coding, not the display algorithm itself).


The vast majority of interfaces are nested 1-d layouts


Yoga is also the new Lenovo laptop. Human languages need better support for namespaces.


I would think that the industry vertical is namespace enough.

Hardware laptop vs software library?


I wonder why the new C implementation is faster on Android than the old Java implementation, even though the former comes with some overhead for JNI and the inability for the ART ahead-of-time compiler to do any cross-module optimziation between Java and native code. Is it because C has structs, which java still doesn't have?


Looks like a nice library, but maybe I'm missing one thing in the examples. In the examples they define an image and text views, but only in the iOS Obj-C example are they a native image or text view. How do you define the YogaNode to say be a TextBox in C#?


I'd love to see this defined as a formal spec so it might be implemented in JS. Having access to raw layout calculations in React applications would solve the need to peek at the DOM all the time in so many cases.


Is anyone thinking of creating a Go binding for this?


I like Facebook creating platforms but it is unclear, at least to me, what the problem is they are trying to solve here.


There are a couple of things which we set out to solve with Yoga. These are two things.

- One layout concept across different platforms. This allows developers to more easily collaborate and jump between platforms and re-use knowledge.

- Decouple layout from rendering. A lot of UI frameworks couple layout tightly with rendering which often ties the layout to be run on the main thread. By decoupling layout we are able to run it asynchronously. https://code.facebook.com/posts/531104390396423/components-f... Talks about how we make use of this.


"Please implement this user interface for Android, iOS, and Windows Phone."


I wonder if this competes with Qt or GTK?


No it does not. But, with some hand wringing you could probably write a Gtk+ GtkLayout-based widget that used this engine to do layout rather than box packing or ebassi's constraint stuff that's going into Gtk+ 3.89.x/4.x.

...I'm not sure that you'd actually want to, but that's a different issue.


I wish they had chosen a different name, Yoga is too popular a name to be chosen for something like this.


Static layouts are hardly "complex." The complexity comes from animating between different layout states, animating elements in a list, animating elements relative to other elements (e.g., parallax), animating element size changes, etc.

It seems confusing to me to have "layout" as a separate component rather than having it be tightly integrated with the rest of the UI framework.


Is there a designer online to easily build these layouts? (not counting generic flex box tools)


Can i use this in react?


Not yet (other than react native)

Which is a shame, since the lack of aspect ratio support is one of Flexbox's failings (and apparently resolved with Yoga)


What is the footprint of this library in bytes?

And is it light on dependencies?


If you are using purely the C library it is very small and has no dependencies. I can't remember the exact size as it was a while ago I looked but check it out.


Is this a more general-purpose, polyglot version of Vaadin?


Looks nice but the naming is wrong. We shouldn't expropriate well known names for tech solutions


I think the name comes from flex -> yoga.


correct :)


I think it's nice. It describes its function perfectly and "facebook yoga" will soon return this project in the first result.


Could be a big part behind companies re-purposing common words? If you give it a unique word, it becomes it's own thing. But if it's something like "Yoga", then you will always have to refer to it as "Facebook Yoga" which is very good for the Facebook brand.


I agree with you wholeheartedly about the naming.

This is becoming a serious issue with many different things. Try to search for info about the visual studio "Code" editor for example.

Facts and common sense are not fashionable in this age though unfortunately as evidenced by your (current) low vote on your comment.


vscode.

Also:

It's not a "fact" that such names are a bad choice. It's an opinion. Personally I prefer evocative names, and that requires – almost by definition – to reuse words already in use.

It's also not "fashionable" or "trendy". To quote Aristoteles: "The young people today are rotten to the core, or they would have never named this software 'R'".

The alternative is the pharmaceutical naming system which includes a review to ensure that names are not just unique, but unlikely to confuse even with bad handwriting. The result is an endless stream of forgettable, but pronounceable, UUIDs with too many 'Z's.

(... and "Plan B", which is probably my favorite example of evocative naming).


Great work guys.

I think now we can start on CSS => Compiled Style Sheets. :)


Why not use something like XAML instead? Much more readable and powerful.


I really dislike how software is able to hijack meaning of nouns in our regular lives. To call a software 'Yoga' is so tasteless lol.


> To call a software 'Yoga' is so tasteless lol.

Or hip, depending on where you are :)


Using the name "Yoga" for your software is cultural appropriation. Facebook should not do it.

It is equivalent of naming a sports team Rednecks.


Is Yoga a derogatory term? I've never heard it used in such a way, so I think that's quite the false equivalence.


Does not matter. It is not a good idea to use other people's cultural heritage to name "things". In fact the downvotes here suggest how deeply prejudiced and racist people are on HN.


In fact the downvotes here suggest how deeply prejudiced and racist people are on HN.

Is it fair to generalize like this across all the members of HN? You might argue that this is the case for those that down-voted, but everyone?


If a comment has down-votes it is fair to say people who did not upvote despite reading supported the action of the downvoters.


Okay, I can understand that point of view. Even that only includes those who saw the discussion, right?




Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: