The Goldilocks customizable <select> height

jaffathecake1 pts0 comments

The Goldilocks customizable select height - JakeArchibald.comThe Goldilocks customizable select height<br>Posted 29 June 2026 I recently gave a talk on customizable (as in fully-stylable) , and as I was building demos I realised there's a sizing 'pattern' that's almost always the-one-you-want, but it took me a long time to figure out how to do it in CSS.

Well, I say I figured it out. I actually failed, and asked a bunch of people for help, who (thankfully, for my ego) also struggled. Eventually, Ian Kilpatrick pointed me at the feature I was missing…

TL;DR: If you just want the solution, skip to the end.

Default sizing

Here's a mock-up of a custom select:

Markup Languages

HTML

CSS

XML

SVG

Markdown

Scripting Languages

JavaScript

Python

Ruby

PHP

Perl

Lua

Shell

PowerShell

Transpiled Languages

TypeScript

CoffeeScript

Babel

Elm

ReasonML

ReScript

Haxe

Dart

Compiled Systems Languages

C++

C#

Rust

Go

Zig

Vala

JVM Languages

Java

Scala

Kotlin

Clojure

Groovy

Functional Languages

Haskell

OCaml

F#

Elixir

PureScript

Prolog

Web Frameworks & Libraries

React

Vue

Svelte

Template Languages

EJS

Jade/Pug

Haml

Liquid

Mustache

Nunjucks

Twig

Slim

Smarty

Jinja

CSS Preprocessors

Sass/SCSS

Less

Stylus

Config Files

JSON

YAML

TOML

CSV

TSConfig

Vite

Webpack

Rollup

Grunt

Gulp

Gradle

Maven

SBT

Bazel

ESLint

Stylelint

Bower

NPM

Yarn

Docker

Karma

Database & Query

SQL

GraphQL

Prisma

Other Languages

Julia

Crystal

Nim

Swift

WebAssembly

LaTeX

The best Languages

HTML

CSS

SVG

Unfortunately you're using Safari 26.5 or lower, which has a buggy implementation of anchor positioning, so these demos won't work for you. They work in Safari Technology Preview, so the techniques in this article should work by the time Safari ships custom select.<br>It isn't actually a custom select. Firefox and Safari are actively working on custom select, but haven't released it yet, so to make the demos work in more browsers, and to make it easier for you to inspect with DevTools, I've built the demos from popovers, and CSS anchor positioning, which are the same primitives custom select uses under the hood.

You can drag it around and see how it reacts to being in other parts of the viewport, and how it reacts to scrolling. If you can't be bothered with all that, here's a video:

Here are the default UA styles that impact the picker's position and height:

::picker(select) { margin: 0; inset: auto; min-inline-size: anchor-size(self-inline); max-block-size: stretch; position-area: self-block-end span-self-inline-end; position-try-order: most-block-size; position-try-fallbacks: self-block-start span-self-inline-end, self-block-end span-self-inline-start, self-block-start span-self-inline-start; /* Not part of the spec, but it's something Chrome does, so I've included it */ min-block-size: 1lh;}<br>As a result:

min-inline-size means the picker will always be at least as wide as the button (or toggle button in this case).

max-block-size means the picker will not overflow the viewport. Its stretch size is the full anchor positioning cell (the area from the edge of the button to the edge of the viewport).

position-area defines the default anchor positioning cell to use, which is below the button, and from its left edge to the right edge of the viewport.

position-try-fallbacks defines fallbacks for the anchor positioning cell, so it can appear above the button, and/or clamp to the button's right edge.

position-try-order means the picker will initially appear in the anchor positioning cell that offers it the most-block-size, which means vertical space in this writing-mode. This doesn't currently work in Firefox (ticket) or Safari (ticket), as it wasn't clear in the spec.

This is a reasonable set of defaults, but I think there are a number of things we can do to improve the UX.

Prevent the picker from hitting the viewport edge

Right now the picker extends to the edge of the viewport, making it hard to tell if it's actually stopping there, or if it's overflowing the viewport. The only visual clue is the small border & rounded corners.

Instead, I'll add a small margin:

.custom-select::picker(select) { margin-block-end: 1em;}<br>Try it out:

This isn't quite right, because:

In Firefox, it simply isn't working.

In Chrome & Safari, the margin is on the bottom, which looks bad when the picker flips above the button.

Fixing Firefox

Remember when I said pickers have max-block-size: stretch? Well, Firefox doesn't support that, so I threw in max-block-size: 100% as a fallback. However, with percent heights, margins don't take away from the height, so the picker still hits the viewport edge, and the margin is outside it.

We can work around it:

.custom-select::picker(select) { --viewport-margin: 1em; max-block-size: calc(100% - var(--viewport-margin)); @supports (max-block-size: stretch) { max-block-size: stretch; margin-block-end: var(--viewport-margin); }}<br>Now, for Firefox, we're...

block size select viewport picker languages

Related Articles