1

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 );
        }
    }
}
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154

2 Answers2

2

➥ 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

Jouni
  • 2,830
  • 15
  • 12
1

Caption on field distorts the layout

The problem in your example is the caption on the TextField.

The Answer by Jouni explains this is a bug.

Workaround

As a workaround, delete the caption from your TextField widget.

In your example code, simply change this:

TextField field = new TextField( "field" );

…to this:

TextField field = new TextField();

Now the layout is sensible, behaving as you expected.

screenshot of proper layout without the caption on <code>TextField</code>

This is an annoying little bug, where ironically the least important element (field caption) hijacks the layout algorithm. But at least we have a workaround until a fix arrives: Avoid using caption on fields.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • This should not be required. The CSS has been carefully crafted to align the input field with button, checkboxes, text, etc. The label or error message should not affect it. I’ll take a look at what might be the the issue. – Jouni Dec 17 '18 at 08:56
  • At least with a simple client-side-only test case everything works: https://conscious-seeker.glitch.me (code: https://glitch.com/edit/#!/conscious-seeker) – Jouni Dec 17 '18 at 08:57
  • The “odd choice of behavior” comes directly from CSS. The first textual element inside a block/flex container sets the baseline. Therefore it’s the label of the TextField component. But we “fix” (hack really) that by using a ``::before` pseudo element with a space character to set the baseline on the same line as the input field content. This also fixes the case if you don’t have a label but have a prefix icon, which would wreck the baseline as well. – Jouni Dec 17 '18 at 08:59