Skip to content
SiteEmail

Since version 3.0, Gameface exposes a new flex layout mode named WebStandardMode. This mode is configured on the View through ViewSettings::LayoutAlgorithm.

WebStandardMode introduces three main categories of changes:

  1. Correct defaults aligned with the CSS specification.
  2. True static positioning instead of the previously simulated behavior.
  3. Bug fixes that bring the flex layout implementation closer to web standards.

Each of these changes can affect existing UIs and components. To ease the transition, we provide a compatibility mode that preserves legacy behavior (including bugs that have since been fixed), because existing UIs may depend on these quirks in non-obvious ways. This guide explains these differences and details how to migrate your layouts to use the new web defaults.

Previously, our flex layout used incorrect defaults for flex-shrink and box-sizing. To preserve your existing layouts’ default behaviors, add the following global rule to your CSS:

* {
box-sizing: border-box;
flex-shrink: 0;
}

To more closely match browser behavior in most cases when using WebStandardMode, the following rules are still needed.

* {
/* min-width and min-height are auto by default, but they are not supported */
min-width: 0;
min-height: 0;
/* Gameface works with flex layout, so we need to use flex */
display: flex;
}
head, style, script {
display: none;
}
html {
width: 100vw;
height: 100vh;
}

The default position for most elements is position: static. Previously, static positioning was not supported and was simulated by forcing position: relative with left, right, top, and bottom set to auto, regardless of the values resolved for the element.

To approximate the old behavior, you can add:

* {
position: relative;
}

This will help in most cases, but won’t be a complete solution:

  • If an element had an explicit inset, for example <div style="left: 10px"></div>, that inset must also be removed to match the old behavior.

  • Every place that explicitly used position: static (not as a default style) will need to be changed to position: relative with left: auto; right: auto; top: auto; bottom: auto.

There have been numerous bug fixes. Unfortunately, many existing UIs likely rely on buggy behavior to work (for example, by including adjustments to compensate for layout bugs). Releasing all fixes at once can require too much migration time, so compatibility mode includes paths that preserve those bugs while WebStandardMode fixes them. Since simply enabling WebStandardMode and inspecting the new layout might not immediately show what needs to change, the full list of fixes is compiled below.

Alignment with no insets defined

When positioning absolute children with no insets defined:

Previously align-items: center centered the absolute child’s content box inside the parent’s margin box. Now correctly centers the child’s margin box inside the parent’s content box.

  • Example issue: “Some absolute element stopped being centered.”
  • Possible explanation: The parent had different front and back padding, margin, or border.

Previously align-items: flex-start and align-items: stretch started at the border box. Now starts at the padding box.

  • Example issue: “Some absolute element moved to the right.”
  • Possible explanation: The element had align-items: stretch (the default), but now the front padding of the parent plays a role.

Previously align-items: flex-end aligned the child’s border box to the parent’s margin box, which visually stuck the absolute element’s border to its parent’s outermost edge. Now aligns the child’s border box to the parent’s content box.

  • Example issue: “Some absolute element moved to the left.”

  • Possible explanation: The element was aligned as flex-end, but the parent has padding or the element has margin at the back edge.

  • For justify-content, the same cases apply as in the three items above, but in the other flex direction.

Percentage values resolved against the wrong box

Absolute elements using percentage values previously resolved against their parent’s (or containing-block-creating ancestor’s) content box instead of the padding box.

  • Example issue: “Some element with position: absolute has wrong size or position.”
  • Possible explanation: The element uses a percent for some property and the parent has padding.
  • Suggested fix: Reduce the percentage used to make up for it.

Percentage values resolved against own borders and paddings

Absolute elements would sometimes compute their percent values against the size of their own borders and paddings instead of against the size of the containing block.

  • Example issue: “Absolute positioned element changed size (most likely became bigger).”
  • Possible explanation: The absolutely positioned element used percent for sizing.
  • Suggested fix: Consider more explicit sizing, or adjust the percent so that it works as a percent of the containing block rather than of border + padding.

Margins ignored when combined with insets

When positioning absolute elements, their margin would sometimes be ignored when combined with insets.

  • Example issue: “Some element with position: absolute moved.”
  • Possible explanation: The element had a margin and an inset in one of the invalid cases (for example, a right inset and a left margin in a flex-direction: row parent).

wrap-reverse not reversing alignment

Previously, wrap-reverse failed to reverse alignment in absolutely positioned children.

  • Example issue: “Some absolutely positioned child moved to the opposite side of its container.”
  • Possible explanation: The parent had wrap-reverse and align-items: flex-start or align-items: flex-end.
  • Suggested fix: Change the child’s align-self to flex-end or flex-start respectively.

Changes to elements in wrapping flex containers

Section titled “Changes to elements in wrapping flex containers”

Wrong cross size when wrapping due to main axis margins

Previously, a wrapped flex line could have an incorrect cross size when it wrapped due to main-axis margins. In other words, if elements could have fit on one line were it not for margins between them, wrapping would still occur, but the cross size would be incorrect—often larger than it should be and not constrained by the line size.

  • Example issue: “Some wrapped elements inside a flex-direction: row container became shorter.”
  • Possible explanation: There were large horizontal margins, or the line barely wrapped.

align-content in single line containers

Previously, align-content had no effect in a single-line container, even if flex-wrap: wrap was applied.

  • Example issue: A line of child elements moved to the center or the end in the cross axis of its container.
  • Possible explanation: There is flex-wrap: wrap and align-content applied to the parent, which can move the line even without wrapping involved.
  • Suggested fix: Remove either the flex-wrap or the align-content from the parent to get the old behavior.

align-content: stretch in row containers

Previously, align-content: stretch when used in a flex-direction: row container would remove vertical margins (instead of horizontal margins) from the space the elements can stretch in.

  • Example issue: “Some wrapped elements in a row container became a different width.”
  • Possible explanation: The element is in a container with align-content: stretch and flex-direction: row, and has different vertical and horizontal margins.

align-content in auto-sized containers

Previously, align-content in auto-sized containers used the size of the container’s parent to align the container’s children. This caused elements to be positioned outside their parent or to grow when they should not.

  • Example issue: “Some wrapping elements now position closer to each other or become smaller in the cross dimension.”
  • Possible explanation: The wrapping container had an auto size.
  • Suggested fix: To restore previous behavior, consider using 100% instead of auto in this case.

Relatively positioned elements and cross insets

Relatively positioned elements in wrapping flex containers with align-items: flex-start were not affected by their inset in the cross direction.

  • Example issue: “Some relatively positioned element moved downwards.”
  • Possible explanation: There was top applied to the element in a flex-direction: row wrapping container.

flex-grow factors summing to less than 1

Previously, when flex-grow factors summed to less than 1, all extra space on the line was still given to elements. Now, flex lines whose flex-grow factors sum to less than 1 may leave free space.

  • Example issue: “Some elements in a container shrank, leaving free space.”
  • Possible explanation: flex-grow was applied to at least one element in the container, and the total flex-grow value in the container is less than one.
  • Suggested fix: Multiply the flex-grow factors by a value that makes them sum to more than 1 to restore the old behavior.

Auto-width sibling after wrapping text

When a flex container had multiple children and one of them had auto width with wrapping text, the box used to size itself based on where the text wrapped instead of taking the full width of the container.

  • Example issue: “I had an element after some wrapping text that sat to the right of the text, and now it moved below the text.”
  • Possible explanation: The box of the element containing the text got bigger, since it no longer stops at the wrap point, but takes all the available space, moving the other children on the next line.
  • Suggested fix: Give a non-auto width to the box containing the text.

min and max binding skipped when distributing flex sizes

Binding with min and max was sometimes skipped when distributing flex sizes, which in rare cases produced inaccurate results.

  • Example issue: “An element that used flex-grow or flex-shrink to determine its main size is now sized differently.”
  • Possible explanation: Non-zero min or max constraints on the main axis were used on an element that shrinks or grows.

justify-content: space-between growing the container

In rare cases, justify-content: space-between could grow the container by the computed space-between size.

  • Example issue: “Container with space-between had its final ‘gap’ removed, reducing it in size.”
  • Possible explanation: justify-content: space-between is used in a container that does not have specified main size, but has minimum main size.

Missing fallback alignment for justify-content

There was no fallback alignment for justify-content. When a container does not have enough space on its main axis for all its children, justify-content: space-between or justify-content: space-around should fall back to flex-start. Without this fallback, space-around could, for example, create negative spacing between elements and cause them to overlap.

  • Example issue: “Some elements in a container too small for them grew in size.”
  • Possible explanation: justify-content: space-between or justify-content: space-around was used in a container too small to fit its children.