Fix flex-basis incompatibilities with the browsers #427

Open
opened 2017-02-22 04:09:02 -08:00 by emilsjolander · 2 comments
emilsjolander commented 2017-02-22 04:09:02 -08:00 (Migrated from github.com)

I went through a bunch of edge cases with flex-basis and identified where Yoga does not match the behavior of chrome and other browsers. Bellow are the gentest fixtures which I found were generating failing tests.

To test these add them to YGFlexTest.html and run ruby rubygentest/gentest.rb to generate the tests. The run the test suite and see these tests fail. Most failures seem to be due to us expecting width/height and flexbasis to behave identically. This is not the case. The most obvious case is a container with a set flexbasis can grow to accommodate children of larger size but a container with a set width/height cannot.

<div id="flex_basis_unconstraint_row" style="flex-direction: row;">
  <div style="flex-basis: 50px; height: 100px"></div>
</div>

<div id="flex_basis_unconstraint_column" >
  <div style="flex-basis: 50px; width: 100px"></div>
</div>

<div id="flex_basis_smaller_than_content_row" style="flex-direction: row; width: 100px;">
  <div style="flex-basis: 50px;">
    <div style="width: 100px; height: 100px;"></div>
  </div>
</div>

<div id="flex_basis_larger_than_content_row" style="flex-direction: row; width: 100px;">
  <div style="flex-basis: 50px;">
    <div style="width: 10px; height: 100px;"></div>
  </div>
</div>

<div id="flex_basis_smaller_than_content_column" style="height: 100px;">
  <div style="flex-basis: 50px;">
    <div style="width: 100px; height: 100px;"></div>
  </div>
</div>

<div id="flex_basis_larger_than_content_column" style="height: 100px;">
  <div style="flex-basis: 50px;">
    <div style="width: 100px; height: 10px;"></div>
  </div>
</div>

<div id="flex_basis_smaller_then_content_with_flex_grow_large_size" style="flex-direction: row; width: 100px;">
  <div style="flex-basis: 0px; flex-grow: 1;">
    <div style="width: 70px; height: 100px;"></div>
  </div>
  <div style="flex-basis: 0px; flex-grow: 1;">
    <div style="width: 20px; height: 100px;"></div>
  </div>
</div>

<div id="flex_basis_slightly_smaller_then_content_with_flex_grow_large_size" style="flex-direction: row; width: 100px;">
  <div style="flex-basis: 60px; flex-grow: 1;">
    <div style="width: 70px; height: 100px;"></div>
  </div>
  <div style="flex-basis: 0px; flex-grow: 1;">
    <div style="width: 20px; height: 100px;"></div>
  </div>
</div>

<div id="flex_basis_smaller_then_content_with_flex_grow_very_large_size" style="flex-direction: row; width: 200px;">
  <div style="flex-basis: 0px; flex-grow: 1;">
    <div style="width: 70px; height: 100px;"></div>
  </div>
  <div style="flex-basis: 0px; flex-grow: 1;">
    <div style="width: 20px; height: 100px;"></div>
  </div>
</div>

<div id="flex_basis_smaller_then_content_with_flex_grow_small_size" style="flex-direction: row; width: 10px;">
  <div style="flex-basis: 0px; flex-grow: 1;">
    <div style="width: 70px; height: 100px;"></div>
  </div>
  <div style="flex-basis: 0px; flex-grow: 1;">
    <div style="width: 20px; height: 100px;"></div>
  </div>
</div>

<div id="flex_basis_smaller_then_content_with_flex_grow_unconstraint_size" style="flex-direction: row;">
  <div style="flex-basis: 0px; flex-grow: 1;">
    <div style="width: 70px; height: 100px;"></div>
  </div>
  <div style="flex-basis: 0px; flex-grow: 1;">
    <div style="width: 20px; height: 100px;"></div>
  </div>
</div>

<div id="width_smaller_then_content_with_flex_grow_large_size" style="flex-direction: row; width: 100px;">
  <div style="width: 0px; flex-grow: 1;">
    <div style="width: 70px; height: 100px;"></div>
  </div>
  <div style="width: 0px; flex-grow: 1;">
    <div style="width: 20px; height: 100px;"></div>
  </div>
</div>

<div id="width_smaller_then_content_with_flex_grow_very_large_size" style="flex-direction: row; width: 200px;">
  <div style="width: 0px; flex-grow: 1;">
    <div style="width: 70px; height: 100px;"></div>
  </div>
  <div style="width: 0px; flex-grow: 1;">
    <div style="width: 20px; height: 100px;"></div>
  </div>
</div>

<div id="width_smaller_then_content_with_flex_grow_small_size" style="flex-direction: row; width: 10px;">
  <div style="width: 0px; flex-grow: 1;">
    <div style="width: 70px; height: 100px;"></div>
  </div>
  <div style="width: 0px; flex-grow: 1;">
    <div style="width: 20px; height: 100px;"></div>
  </div>
</div>

<div id="width_smaller_then_content_with_flex_grow_unconstraint_size" style="flex-direction: row;">
  <div style="width: 0px; flex-grow: 1;">
    <div style="width: 70px; height: 100px;"></div>
  </div>
  <div style="width: 0px; flex-grow: 1;">
    <div style="width: 20px; height: 100px;"></div>
  </div>
</div>

<div id="flex_basis_smaller_than_main_dimen_row" style="flex-direction: row; width: 100px;">
  <div style="flex-basis: 10px; width: 50px; height: 50px;"></div>
</div>

<div id="flex_basis_smaller_than_main_dimen_column" style="height: 100px;">
  <div style="flex-basis: 10px; width: 50px; height: 50px;"></div>
</div>

<div id="flex_basis_and_main_dimen_set_when_flexing" style="flex-direction: row; width: 100px;">
  <div style="flex-basis: 10px; width: 50px; height: 50px; flex-grow: 1;"></div>
  <div style="flex-basis: 10px; width: 0px; height: 50px; flex-grow: 1;"></div>
</div>
I went through a bunch of edge cases with flex-basis and identified where Yoga does not match the behavior of chrome and other browsers. Bellow are the gentest fixtures which I found were generating failing tests. To test these add them to `YGFlexTest.html` and run `ruby rubygentest/gentest.rb` to generate the tests. The run the test suite and see these tests fail. Most failures seem to be due to us expecting width/height and flexbasis to behave identically. This is not the case. The most obvious case is a container with a set flexbasis can grow to accommodate children of larger size but a container with a set width/height cannot. ``` <div id="flex_basis_unconstraint_row" style="flex-direction: row;"> <div style="flex-basis: 50px; height: 100px"></div> </div> <div id="flex_basis_unconstraint_column" > <div style="flex-basis: 50px; width: 100px"></div> </div> <div id="flex_basis_smaller_than_content_row" style="flex-direction: row; width: 100px;"> <div style="flex-basis: 50px;"> <div style="width: 100px; height: 100px;"></div> </div> </div> <div id="flex_basis_larger_than_content_row" style="flex-direction: row; width: 100px;"> <div style="flex-basis: 50px;"> <div style="width: 10px; height: 100px;"></div> </div> </div> <div id="flex_basis_smaller_than_content_column" style="height: 100px;"> <div style="flex-basis: 50px;"> <div style="width: 100px; height: 100px;"></div> </div> </div> <div id="flex_basis_larger_than_content_column" style="height: 100px;"> <div style="flex-basis: 50px;"> <div style="width: 100px; height: 10px;"></div> </div> </div> <div id="flex_basis_smaller_then_content_with_flex_grow_large_size" style="flex-direction: row; width: 100px;"> <div style="flex-basis: 0px; flex-grow: 1;"> <div style="width: 70px; height: 100px;"></div> </div> <div style="flex-basis: 0px; flex-grow: 1;"> <div style="width: 20px; height: 100px;"></div> </div> </div> <div id="flex_basis_slightly_smaller_then_content_with_flex_grow_large_size" style="flex-direction: row; width: 100px;"> <div style="flex-basis: 60px; flex-grow: 1;"> <div style="width: 70px; height: 100px;"></div> </div> <div style="flex-basis: 0px; flex-grow: 1;"> <div style="width: 20px; height: 100px;"></div> </div> </div> <div id="flex_basis_smaller_then_content_with_flex_grow_very_large_size" style="flex-direction: row; width: 200px;"> <div style="flex-basis: 0px; flex-grow: 1;"> <div style="width: 70px; height: 100px;"></div> </div> <div style="flex-basis: 0px; flex-grow: 1;"> <div style="width: 20px; height: 100px;"></div> </div> </div> <div id="flex_basis_smaller_then_content_with_flex_grow_small_size" style="flex-direction: row; width: 10px;"> <div style="flex-basis: 0px; flex-grow: 1;"> <div style="width: 70px; height: 100px;"></div> </div> <div style="flex-basis: 0px; flex-grow: 1;"> <div style="width: 20px; height: 100px;"></div> </div> </div> <div id="flex_basis_smaller_then_content_with_flex_grow_unconstraint_size" style="flex-direction: row;"> <div style="flex-basis: 0px; flex-grow: 1;"> <div style="width: 70px; height: 100px;"></div> </div> <div style="flex-basis: 0px; flex-grow: 1;"> <div style="width: 20px; height: 100px;"></div> </div> </div> <div id="width_smaller_then_content_with_flex_grow_large_size" style="flex-direction: row; width: 100px;"> <div style="width: 0px; flex-grow: 1;"> <div style="width: 70px; height: 100px;"></div> </div> <div style="width: 0px; flex-grow: 1;"> <div style="width: 20px; height: 100px;"></div> </div> </div> <div id="width_smaller_then_content_with_flex_grow_very_large_size" style="flex-direction: row; width: 200px;"> <div style="width: 0px; flex-grow: 1;"> <div style="width: 70px; height: 100px;"></div> </div> <div style="width: 0px; flex-grow: 1;"> <div style="width: 20px; height: 100px;"></div> </div> </div> <div id="width_smaller_then_content_with_flex_grow_small_size" style="flex-direction: row; width: 10px;"> <div style="width: 0px; flex-grow: 1;"> <div style="width: 70px; height: 100px;"></div> </div> <div style="width: 0px; flex-grow: 1;"> <div style="width: 20px; height: 100px;"></div> </div> </div> <div id="width_smaller_then_content_with_flex_grow_unconstraint_size" style="flex-direction: row;"> <div style="width: 0px; flex-grow: 1;"> <div style="width: 70px; height: 100px;"></div> </div> <div style="width: 0px; flex-grow: 1;"> <div style="width: 20px; height: 100px;"></div> </div> </div> <div id="flex_basis_smaller_than_main_dimen_row" style="flex-direction: row; width: 100px;"> <div style="flex-basis: 10px; width: 50px; height: 50px;"></div> </div> <div id="flex_basis_smaller_than_main_dimen_column" style="height: 100px;"> <div style="flex-basis: 10px; width: 50px; height: 50px;"></div> </div> <div id="flex_basis_and_main_dimen_set_when_flexing" style="flex-direction: row; width: 100px;"> <div style="flex-basis: 10px; width: 50px; height: 50px; flex-grow: 1;"></div> <div style="flex-basis: 10px; width: 0px; height: 50px; flex-grow: 1;"></div> </div> ```
woehrl01 commented 2017-02-22 15:22:13 -08:00 (Migrated from github.com)

just had a look at some of these tests. These are super strange.

e.g: flex_basis_unconstraint_row

Chrome calculates root_child0.width = 50 but the root itself is root.width = 0.

I found the required change to make root_child0 with a width of 50, but it fails on root.width (because this is 50, then too)

just had a look at some of these tests. These are super strange. e.g: ```flex_basis_unconstraint_row``` Chrome calculates ```root_child0.width = 50``` but the root itself is ```root.width = 0```. I found the required change to make ```root_child0``` with a width of 50, but it fails on ```root.width``` (because this is 50, then too)
emilsjolander commented 2017-02-23 01:00:09 -08:00 (Migrated from github.com)

@woehrl01 Yeah this is all pretty strange. I don't expect there to be any quick fix for this and it might require re-architecting core parts of the algorithm due to early assumptions made on how browsers handle flex-basis.

This is high impact to fix but I suggest only working on this if you have a lot of time to spend :P I have been trying to find a quicker solution from time to time but failed. Open sourced this issue for transparency more than hope that someone else will tackle it. Thanks for having a look though!

@woehrl01 Yeah this is all pretty strange. I don't expect there to be any quick fix for this and it might require re-architecting core parts of the algorithm due to early assumptions made on how browsers handle flex-basis. This is high impact to fix but I suggest only working on this if you have a lot of time to spend :P I have been trying to find a quicker solution from time to time but failed. Open sourced this issue for transparency more than hope that someone else will tackle it. Thanks for having a look though!
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: DaddyFrosty/yoga#427
No description provided.