Centering Content on an Arbitrary Point

There is a recurring layout pattern where a set of items must be centered around a single element, which I call the “pivot.” The pivot element might not be at the exact midpoint of the container — it simply sits between what comes before it and what comes after it, and everything must line up around it.

A real-world version of this is a word-puzzle menu where a vertical word is the pivot and all horizontal words must have one of their letters centered on that pivot's letter. You can solve this with explicit offsets on each word, but that means adding an offset for every new item and maintaining redundant rules. With a small set of CSS properties, we can solve this generically without adding markup.

Breaking the Problem Into Two Halves

Look at how the layout behaves before any styling:

If we visually remove every element before the pivot (using display: none), the pivots are already perfectly aligned:

That means the real problem is positioning the hidden, earlier letters without disturbing the pivot alignment. When we bring those letters back, they push the entire word toward the right. A mirrored issue appears if we hide the trailing letters instead:

The two halves of the problem are symmetric. In a logical right-to-left (RTL) reading scheme the roles swap, but the core issue is the same. We need a solution that handles both the elements before the pivot (“the head”) and the pivot with what comes after it (“the tail”) simultaneously — a classic divide-and-conquer breakdown.

Aligning the Head and the Tail

Position the head:

Then position the tail:

Flexbox is a good fit here because it lets us manage these two groups with a single axis. The first trick is to use the order property, which controls the visual sequence of flex items. Because a smaller order places an item first in the flow, we give the tail a smaller order value than the head. This swaps their visual arrangement, keeping the head and the tail usable as independently positioned items.

Without adding extra wrapper elements, we can target the head and tail using the cascade. By default, we apply “head” styles to every letter, then use the subsequent-sibling combinator .pivot ~ .letter to override the pivot and every element after it with the “tail” styles.

With the head and tail now flush against each other, we need to move the head outward. Applying margin: auto to the right side of the last element in the tail pushes the entire head group to the right edge of the flex container:

From here, it is simply a matter of placing both groups back in the correct spots. Applying position: relative to every letter, we shift the tail group to the right with left: 50% and shift the head group to the left with right: 50%:

This complete solution is short enough to keep in one's head:

.container {
  display: flex;
}
.item:last-child {
  margin-right: auto;
}
.item {
  order: 2;
  position: relative;
  right: 50%;
}
.pivot, .pivot ~ .item {
  order: 1;
  left: 50%;
}

Generalizing and Considering Other Layouts

Using the flex-direction property with a value of column works for vertical display, but the core approach can achieve the same result with explicit wrapper elements. However, doing so adds both markup and verbose CSS, and it becomes unwieldy when a dynamic back end produces an ungrouped list of elements with class names we don't control.

Because we are not reordering the document, only shifting groups via relative positioning, the final reading and tab order matches the original markup. This makes the approach also work well with assistive technologies.

Screen readers preserve the element ordering as per the original markup.

While centered layout often means finding a midpoint, the “balance point” of a layout doesn't have to be mathematically centered. This technique keeps arbitrary, off-center pivot elements as the focal point of an alignment with limited, durable CSS.