Welcome to Vanilla Breeze
This bell pulls live notifications from /go/notify/messages — the same contract documented at /docs/concepts/service-contracts/. Static articles like this one are the no-JS / no-backend fallback.
This bell pulls live notifications from /go/notify/messages — the same contract documented at /docs/concepts/service-contracts/. Static articles like this one are the no-JS / no-backend fallback.
Displays a clone of the currently selected option's content inside a customizable select's button trigger. Used with appearance: base-select to show rich content (icons, images, descriptions) in the closed select state.
Requirements: Only works when the browser supports appearance: base-select (Chrome 135+). In non-supporting browsers, the select falls back to its standard rendering.
The browser automatically clones the currently selected <option>'s DOM into the <selectedcontent> element using cloneNode(). It updates every time the selection changes via a change event.
The nesting must follow this exact pattern:
<!-- Required structure --><select> <button> <!-- Custom trigger --> <selectedcontent></selectedcontent> <!-- Cloned content appears here --> </button> <option value="a">Option A</option> <!-- Options after the button --> <option value="b">Option B</option></select> <!-- Both opening and closing tags are mandatory --><!-- This will NOT work: <selectedcontent /> -->
<button> must be the first child of <select><selectedcontent> must be inside that <button><option> elements come after the buttonA plain select with a custom trigger. The selected option text is cloned into the button automatically.
<select name="status"> <button> <selectedcontent></selectedcontent> </button> <option value="open">Open</option> <option value="closed">Closed</option> <option value="pending">Pending</option></select>
Options with emoji flags and descriptions. The .detail text is hidden in the closed trigger via CSS to keep it compact.
<select name="language"> <button> <selectedcontent></selectedcontent> </button> <option value="en"> <span aria-hidden="true">🇺🇸</span> English <span class="detail"> — American English</span> </option> <option value="es"> <span aria-hidden="true">🇪🇸</span> Español <span class="detail"> — Spanish</span> </option> <option value="fr"> <span aria-hidden="true">🇫🇷</span> Français <span class="detail"> — French</span> </option></select>
Since <selectedcontent> contains a clone of the selected option's DOM, you can target child elements to control what is visible in the closed state versus the open dropdown.
/* Hide supplementary text in the closed trigger */selectedcontent .detail { display: none;} /* Hide images in the button, show only in dropdown */selectedcontent img { display: none;}
VB applies these styles automatically inside @supports (appearance: base-select):
selectedcontent gets display: flex with align-items: center and gapselectedcontent .detail is hidden by defaultbutton fills the select width as a flex container<selectedcontent> accepts only global HTML attributes (class, id, style, data-*, etc.). There are no element-specific attributes.
<button> inside <select> is inert, so <selectedcontent> and its children cannot be focused or interacted with independentlynone — screen readers treat it as presentationaria-hidden="true" since they are cloned into the trigger as well<select> — no additional keyboard handling needed<selectedcontent> on change events. If you modify the currently selected option's content dynamically (e.g., via a framework), the clone won't refresh automatically<button> and <selectedcontent>, the browser creates an implicit button that cannot be targeted with CSS type selectorsRequires appearance: base-select support (Chrome 135+). VB gates all related styles behind @supports, so non-supporting browsers fall back gracefully to the standard select rendering.
base-select guide