Search code examples
alignmentvaadinvertical-alignmentbaselinevaadin-flow

Align widgets along baseline of field in Vaadin Flow 12


I am trying vertical alignment within a HorizontalLayout in Vaadin 12.

In most apps I can imagine, it makes sense to line up widgets along the baseline of the text fields, as text fields tend to drive the layout of most apps, and specifically of business apps.

So I was glad to find FlexComponent.Alignment.BASELINE offered for HorizontalLayout. But when I tried it in a Vaadin 12.0.2 app, the baseline seems to be everything except the text field.

screenshot of several <code>HorizontalLayout</code> bars, one for each value in the <code>FlexComponent.Alignment</code> enum

Here is an example app. I downloaded the generated base starter and touched nothing but the content of the MainView constructor.

The app consists of a VerticalLayout composed of six HorizontalLayout objects. Each horizontal bar is a Label, TextField, Button, and Button. The label and the first button have their vertical alignment set explicitly.

Use the edge of another window over the window you are viewing now, using its top edge like a ruler. Notice how the “BASELINE” row appears to line up the explicitly set widgets (label and first button) with the baseline of the field’s caption rather than the field itself, and with the baseline of the last button’s text.

So, the BASELINE alignment lines up the baseline of everything but the text field. This is exactly the opposite of what I expect and need.

➥ Is this a feature or a bug?

➥ Am I doing something wrong?

➥ Is there some way to get the widgets to align to the baseline of the TextField?

As a minor side issue, STRETCH seems to have no effect. What should it be doing?

Code

package work.basil.example.bugsy;

import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.server.PWA;

/**
 * The main view contains a button and a click listener.
 */
@Route ( "" )
@PWA ( name = "Project Base for Vaadin Flow",
    shortName = "Project Base" )
public class MainView extends VerticalLayout {

    public MainView () {
        this.setSpacing( true );
        this.setMargin( true );

        for ( FlexComponent.Alignment a : FlexComponent.Alignment.values() ) {
            Label label = new Label( a.name() );
            TextField field = new TextField( "field" );
            Button alignedButton = new Button( "aligned" );
            Button unalignedButton = new Button( "unaligned" );

            HorizontalLayout horizontalLayout = new HorizontalLayout();
            horizontalLayout.add( label , field , alignedButton , unalignedButton );
            // Set vertial alignment of the label and the first button.
            horizontalLayout.setVerticalComponentAlignment( a , label );
            horizontalLayout.setVerticalComponentAlignment( a , alignedButton );

            this.add( horizontalLayout );
        }
    }
}

Solution

  • ➥ Is this a feature or a bug?

    That’s a bug.

    ➥ Am I doing something wrong?

    Don’t think so. I’ll set up a Flow project to test this.

    ➥ Is there some way to get the widgets to align to the baseline of the TextField?

    Not sure if there’s a difference that you seem to be setting the alignment on the components individually vs setting it “globally” for the whole layout (align-self vs align-items in CSS).

    As a minor side issue, STRETCH seems to have no effect. What should it be doing?

    Stretch should make the component grow vertically to match the tallest item on the row.


    Here’s a client-side-only test case, which at least works as expected:

    https://conscious-seeker.glitch.me

    https://glitch.com/edit/#!/conscious-seeker