Oliver Joseph Ash

Full-stack web developer

Vertical select menu with writing modes

What if you have a select menu that you want to be displayed vertically? The CSS writing-mode property allows you to specify the flow direction of content, but unfortunately there is a bug in Chrome and Safari whereby select menus don’t honour vertical writing modes. (It works in Firefox.)

I wanted to achieve this effect without magic numbers, keeping the select menu in the layout and flow of the document. This way, the element’s positioning and dimensions will continue to respond to its contents and surrounding elements.

The way I achieved this was using the infamous padding-bottom trick. Percentage values provided to padding-bottom are proportional to the container element’s width. This rule has little to no intuition (at least to me), but that’s just the way the box model works—and it opens doors to hacks such as this (also, aspect ratios).

By placing the select menu and a placeholder element inside an inline-block container, I can use padding-bottom: 100% on the placeholder element to reserve whitespace with a height equal to the width of the parent, which is derived from its contents (the select menu). If the select menu changes in width, our placeholder changes in height to match.

See the Pen vgyRpr by Oliver Joseph Ash (@OliverJAsh) on CodePen.

Next we can use transforms to rotate our element so it appears in the space reserved by our placeholder element.

See the Pen YNpaaL by Oliver Joseph Ash (@OliverJAsh) on CodePen.

Finally, we need to nudge the select menu up to negate its original place in the document flow before we used transforms to rotate it. This requires one magic number which, fortunately, is easy to calculate up front: the height of the select menu=font size * line height. We can use this value as a negative margin top on the select menu.

See the Pen wgommZ by Oliver Joseph Ash (@OliverJAsh) on CodePen.

Final result:

See the Pen oBYqdE by Oliver Joseph Ash (@OliverJAsh) on CodePen.

This technique should work for any element which doesn’t honour writing modes, although at the time of writing I’m not quite sure what that could be.