BR: FlexBox::AlignItems not behaving as expected

Using the following CSS, I can get the pictures result:

#main {
  width: 200px;
  height: 200px;
  border: 1px solid black; 

  display: flex;
  align-items: flex-end;
}

#main div {
   width:50px;
   height:50px;
}

Screenshot 2021-10-20 at 21.48.58


However, doing the equivalent in JUCE, doesn’t give the expected result:

        juce::FlexBox flex;
        flex.alignItems = juce::FlexBox::AlignItems::flexEnd;

        flex.items = {
            juce::FlexItem{ b1 }.withWidth(50.f).withHeight(50.f),
            juce::FlexItem{ b2 }.withWidth(50.f).withHeight(50.f)
        };

        auto bounds = getLocalBounds().withSizeKeepingCentre(200, 200);
        flex.performLayout(bounds);


Am I missing something, or does juce::FlexBox not implement the align-items property properly?

Full Component to reproduce:

class MainComponent  : public juce::Component
{
public:
    MainComponent()
    {
        addAndMakeVisible(b1);
        addAndMakeVisible(b2);

        setSize (600, 400);
    }

    void paint (juce::Graphics& g) override
    {
        g.fillAll (findColour (juce::ResizableWindow::backgroundColourId));

        auto bounds = getLocalBounds().withSizeKeepingCentre(200, 200);
        g.setColour(juce::Colours::white);
        g.drawRect(bounds);
    }

    void resized() override
    {
        juce::FlexBox flex;
        flex.alignItems = juce::FlexBox::AlignItems::flexEnd;

        flex.items = {
            juce::FlexItem{ b1 }.withWidth(50.f).withHeight(50.f),
            juce::FlexItem{ b2 }.withWidth(50.f).withHeight(50.f)
        };

        auto bounds = getLocalBounds().withSizeKeepingCentre(200, 200);
        flex.performLayout(bounds);
    }

private:
    juce::TextButton b1, b2;

    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainComponent)
};

what exactly is your problem? is it that the boxes dont look aligned correctly? if so, its because of the rectangle stroke. is that the issue?

Using CSS, the boxes are positioned at the bottom of the container as I would expect when using flex-end. However in JUCE, the boxes are positioned at the top.

Well I personally don’t use FlexBox but from the docs I can see you should set a “main axis” and you have not done so.

Direction

You’re trying to set at the end of an axis but you have not told your flexbox where the end is.

I think the specific one you’re looking for is

FlexBox::Direction::column

The default direction is Direction::row, the same as in CSS where the direction will be row if you don’t specify one.

align-items should change the way items are aligned on the cross-axis (so the Y axis, when the direction is row). In the CSS example, the items are positioned at the end of the cross-axis (bottom), whereas in JUCE, changing the alignment doesn’t appear to have any effect

This will work as you need:

    juce::FlexBox flex;
    flex.items = {
        juce::FlexItem { b1 }.withWidth (50.f).withHeight (50.f).withAlignSelf (juce::FlexItem::AlignSelf::flexEnd),
        juce::FlexItem { b2 }.withWidth (50.f).withHeight (50.f).withAlignSelf (juce::FlexItem::AlignSelf::flexEnd)
    };
    
    auto bounds = getLocalBounds().withSizeKeepingCentre(200, 200);
    flex.performLayout(bounds);

But I don’t know if it is correct behaviour.

I don’t really need the behaviour, I’m more concerned about juce::FlexBox using the alignment properly which it doesn’t current seem to.

This looks like a bug. FlexItem::alignSelf is currently defaulting to stretch, whereas I think it should default to autoAlign. When I modify the default value of alignSelf, I see the expected result with the buttons in the bottom left corner of the container.

Ahh yeah, that seems to be it!

Adding withAlignSelf (juce::FlexItem::AlignSelf::autoAlign) to each item aligns them properly at the bottom of the parent.

Seems to have introduced another issue however… Changing the default to autoAlign seems to now ignore any specific height that’s set (using a row direction). I’ll try to find time to put together an example.

Here’s an example showing how a FlexItem's height isn’t taken into account when it has autoAlign and the flex box’s align-items is stretch:

/*******************************************************************************
 The block below describes the properties of this PIP. A PIP is a short snippet
 of code that can be read by the Projucer and used to generate a JUCE project.

 BEGIN_JUCE_PIP_METADATA

  name:             FlexItemHeightBug

  dependencies:     juce_core, juce_data_structures, juce_events, juce_graphics, juce_gui_basics
  exporters:        XCODE_MAC

  moduleFlags:      JUCE_STRICT_REFCOUNTEDPOINTER=1

  type:             Component
  mainClass:        MainComponent

 END_JUCE_PIP_METADATA

*******************************************************************************/

#pragma once

#include <JuceHeader.h>

class MainComponent  : public juce::Component
{
public:
    MainComponent()
    {
        addAndMakeVisible (button);

        setSize (600, 400);
    }

    void paint (juce::Graphics& g) override
    {
        g.fillAll (findColour (juce::ResizableWindow::backgroundColourId));

        g.setColour (juce::Colours::white);
        g.drawRect (getLocalBounds().withSizeKeepingCentre (200, 200));
    }

    void resized() override
    {
        juce::FlexBox flex;
        flex.alignItems = juce::FlexBox::AlignItems::stretch;

        flex.items = {
            juce::FlexItem {button}
                .withAlignSelf (juce::FlexItem::AlignSelf::autoAlign)
                .withWidth (50.f)
                .withHeight (50.f)
        };

        flex.performLayout (getLocalBounds().withSizeKeepingCentre (200, 200));
    }

private:
    juce::TextButton button;

    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainComponent)
};

(This works as expected if the item’s alignSelf is also set to stretch).


Expected result using CSS:

Screenshot 2021-10-27 at 11.47.54

https://jsfiddle.net/nak6obye/

The default value of alignSelf is fixed on develop now:

The newest issue you’ve raised looks a bit more involved to fix, so I’m still working on a solution to that.

1 Like

I’ve just pushed some changes that should hopefully fix the additional alignment issues you were seeing:

Please try this out and let us know if you find any further problems.