Alexis King Alexis King - 17 days ago 6
CSS Question

Flexbox align-self: baseline does not align elements’ baselines while align-items: baseline does

I seem to be observing some confusing behavior with flexbox, specifically when attempting to use

align-self: baseline
. The basic issue is that it simply doesn’t work; the following snippet demonstrates the problem:



.flex-form {
display: flex;
}

.flex-form label {
align-self: baseline;
}

input[type=text] {
border: 1px solid black;
font-size: 16px;
margin: 0 10px;
padding: 5px;
}

button {
background-color: white;
border: 1px solid black;
margin: 0;
}

<form class="flex-form">
<label>Label: </label>
<input type="text" placeholder=" " />
<button type="submit">Submit</button>
</form>





Here’s a screenshot of what the output looks like:





As you can see, the label’s baseline is not aligned with the other form elements, despite having
align-self: baseline
set. If I use
align-items: baseline
on the parent container, however, I get a different result:



.flex-form {
display: flex;
align-items: baseline;
}

input[type=text] {
border: 1px solid black;
font-size: 16px;
margin: 0 10px;
padding: 5px;
}

button {
align-self: stretch;
background-color: white;
border: 1px solid black;
margin: 0;
}

<form class="flex-form">
<label>Label: </label>
<input type="text" placeholder=" " />
<button type="submit">Submit</button>
</form>









Is this correct behavior according to the spec, or is it a bug? If so, why? Is there a workaround? For reference, I’ve tested on Chrome 54, Safari 9.1.2, and Firefox 50 on macOS 10.11.6, and they all seem to exhibit the same results.

Answer

An initial setting of a flex container is align-items: stretch.

This means that all flex items will expand to cover the full cross-axis length of the container.

That's what's happening in your layout. EXCEPT, you've overridden align-items: stretch on one flex item (label), by applying align-self: baseline.

While the other flex items stretch, the label element has a baseline instruction but no reference point.

From the spec:

8.3. Cross-axis Alignment: the align-items and align-self properties

baseline

If the flex item’s inline axis is the same as the cross axis, this value is identical to flex-start.

Otherwise, it participates in baseline alignment: all participating flex items on the line are aligned such that their baselines align, and the item with the largest distance between its baseline and its cross-start margin edge is placed flush against the cross-start edge of the line.

Okay, let's break this down:

  • This first line doesn't apply. In this case, the flex item's inline axis is the same as the main axis (horizontal), not the cross axis (vertical). Hence, baseline doesn't automatically resolve to flex-start.

  • "...all participating flex items on the line are aligned such that their baselines align..." Well, there's only one item with baseline alignment, so it has no other baseline for reference.

  • The rest of the spec language is covered in detail in this related post: What's the difference between flex-start and baseline?

If you want baseline alignment for all items, apply align-self: baseline to all or, more simply, set align-items: baseline on the container.