
Yoga: A cross-platform layout engine - emilsjolander
https://code.facebook.com/posts/1751945575131606
======
yladiz
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.

~~~
Steeeve
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.

~~~
olalonde
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](https://github.com/facebook/react/wiki/Sites-Using-React)

~~~
Steeeve
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.

~~~
olalonde
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...](https://wptavern.com/automattic-will-continue-to-use-react-js-in-
calypso-despite-patent-clause)

------
tumult
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](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?

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

~~~
tumult
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.

------
BinaryIdiot
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.

~~~
oblio
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 :)

~~~
sixdimensional
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)....](https://msdn.microsoft.com/en-
us/library/z9w7ek2f\(v=vs.110\).aspx)

------
amelius
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.

~~~
emilsjolander
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).

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

~~~
dimillian
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.

------
RubenSandwich
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](http://caniuse.com/flexbox))

~~~
spicyj
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/](https://facebook.github.io/yoga/docs/learn-more/)

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

------
unwind
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?

~~~
fit2rule
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...

------
pcwalton
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...](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.207.1244&rep=rep1&type=pdf)

~~~
aseipp
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.

~~~
pcwalton
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?

------
rsp1984
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?

------
adamnemecek
Why not just embrace Cassowary
([https://en.wikipedia.org/wiki/Cassowary_(software)](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.

~~~
vjeux
(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/](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 :)

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

~~~
jordanlev
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).

------
olalonde
> 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?

~~~
wilonth
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).

------
smaili
Page - [https://facebook.github.io/yoga/](https://facebook.github.io/yoga/)

GitHub - [https://github.com/facebook/yoga](https://github.com/facebook/yoga)

------
phn
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.

------
king_magic
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).

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

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

~~~
emilsjolander
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.

------
jordanlev
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).

~~~
woah
The vast majority of interfaces are nested 1-d layouts

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

~~~
sheraz
I would think that the industry vertical is namespace enough.

Hardware laptop vs software library?

------
mwcampbell
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?

------
bnycum
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#?

------
namuol
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.

------
shurcooL
Is anyone thinking of creating a Go binding for this?

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

~~~
emilsjolander
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...](https://code.facebook.com/posts/531104390396423/components-
for-android-a-declarative-framework-for-efficient-uis/) Talks about how we
make use of this.

------
omouse
I wonder if this competes with Qt or GTK?

~~~
awalton
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.

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

------
mrcheesy
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.

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

------
polskibus
Can i use this in react?

~~~
drcode
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)

------
amelius
What is the footprint of this library in bytes?

And is it light on dependencies?

~~~
emilsjolander
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.

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

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

~~~
amelius
I think the name comes from flex -> yoga.

~~~
emilsjolander
correct :)

------
crudbug
Great work guys.

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

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

------
abledon
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.

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

Or hip, depending on where you are :)

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

It is equivalent of naming a sports team Rednecks.

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

~~~
tn13
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.

~~~
grzm
_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?

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

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

