Safari 27 introduces full CSS customization of the HTML <select> element via appearance: base-select, along with new pseudo-elements like ::picker, ::checkmark, and ::picker-icon, enabling fully branded drop-down controls with automatic accessibility support. Developers can now inject arbitrary HTML (images, subtext) into <option> elements and style the picker menu with CSS Grid or Flexbox.
β’ Eliminates the long-standing need for JavaScript-heavy custom select widgets β real <select> semantics and accessibility come for free
β’ New pseudo-elements (::picker, ::checkmark, ::picker-icon) give fine-grained CSS control over every visual part of the control
β’ Rich content inside <option> (images, subtext) is now standard HTML, reducing third-party dependency bloat in forms
Loads a WKWebView containing a fully styled HTML select element using appearance: base-select, custom pseudo-elements, and rich option content including emoji icons and subtext, demonstrating the new Safari 27 Customizable Select feature.
import SwiftUI
import WebKit
struct CustomizableSelectView: UIViewRepresentable {
func makeUIView(context: Context) -> WKWebView {
let config = WKWebViewConfiguration()
let webView = WKWebView(frame: .zero, configuration: config)
webView.loadHTMLString(htmlContent, baseURL: nil)
return webView
}
func updateUIView(_ uiView: WKWebView, context: Context) {}
private var htmlContent: String {
"""
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body { font-family: -apple-system, sans-serif; padding: 32px; background: #f2f2f7; }
select {
appearance: base-select;
font-family: inherit;
font-size: 17px;
color: #1c1c1e;
background: #ffffff;
border: 1.5px solid #c7c7cc;
border-radius: 12px;
padding: 10px 14px;
width: 100%;
}
select::picker(select) {
appearance: base-select;
background: #ffffff;
border: 1px solid #e5e5ea;
border-radius: 16px;
padding: 8px 0;
box-shadow: 0 8px 32px rgba(0,0,0,0.12);
}
option {
display: flex;
align-items: center;
gap: 12px;
padding: 12px 16px;
font-size: 16px;
}
option:hover { background: #f2f2f7; }
.option-icon { font-size: 24px; }
.option-label { font-weight: 600; }
.option-sub { font-size: 13px; color: #8e8e93; }
</style>
</head>
<body>
<label for="fruit">Choose a fruit</label><br><br>
<select id="fruit" name="fruit">
<option value="apple">
<span class="option-icon">π</span>
<span>
<span class="option-label">Apple</span><br>
<span class="option-sub">Crisp and sweet</span>
</span>
</option>
<option value="banana">
<span class="option-icon">π</span>
<span>
<span class="option-label">Banana</span><br>
<span class="option-sub">Tropical and smooth</span>
</span>
</option>
<option value="grape">
<span class="option-icon">π</span>
<span>
<span class="option-label">Grape</span><br>
<span class="option-sub">Small but mighty</span>
</span>
</option>
</select>
</body>
</html>
"""
}
}
struct ContentView: View {
var body: some View {
CustomizableSelectView()
.ignoresSafeArea()
}
}
β’ appearance: base-select must be applied to both the <select> and the ::picker pseudo-element separately to fully unlock styling β’ Rich HTML inside <option> is ignored by browsers that don't support Customizable Select β always test fallback rendering β’ The feature is web-platform (CSS/HTML), so Swift code is needed only when serving/injecting the HTML via WKWebView; pure web projects use no Swift at all
Requires Safari 27 or Safari Technology Preview; not available in older WebKit-based WKWebView rendering on earlier OS versions
More iOS 27 APIs land every week.
Get notified when new capabilities are published β no noise, just signal.