A (limited) CSS-only approach for styling placeholders, along with a way to work around the limitations with a custom JS-based solution.
I’ve been working through my first freelance website in years and totally forgot that it’s the little things that can sometimes take up so much time. Although there were many of those throughout this project, one pesky issue that I ran into was in styling a placeholder for a <select>
form field to look and behave like inputs and textareas.
Before I get into the solutions, I should specify that I have two caveats here:
After a lot of searching, I found a CSS-only solution. It looks like this:
<select required>
<option value="" disabled selected>Placeholder value ...</option>
<option value="A">Option A</option>
<option value="B">Option B</option>
</select>
<style>
select:required:invalid {
color: #888;
}
select {
color: #000;
}
</style>
Here it is in action:
See the Pen Native Default Placeholder by @seancdavis on CodePen .
The output looks okay at first glance, but I found some issues with it:
Eventually, I decided to ditch the native CSS route and sprinkle in a bit of JavaScript. Here’s where I ended up:
<div class="wrapper">
<select required onchange="selectChanged(this)">
<option value=""></option>
<option value="A">Option A</option>
<option value="B">Option B</option>
</select>
<div class="placeholder">Placeholder value ...</div>
</div>
<style>
.wrapper {
position: relative;
}
select {
padding: 16px;
min-width: 200px;
border-color: #666;
position: relative;
z-index: 1;
background-color: transparent;
}
.placeholder {
position: absolute;
top: 0;
left: 0;
padding: 16px;
color: #999;
z-index: 0;
}
</style>
<script>
function selectChanged(select) {
const placeholder = document.getElementsByClassName("placeholder")[0];
if (select.value && select.value.length > 0) {
placeholder.style.display = "none";
} else {
placeholder.style.display = "block";
}
}
</script>
What I’m doing here is placing an absolutely-positioned element behind the select and using a transparent background on the select element.
When an option is chosen (when the select element has a value), the placeholder is hidden (using JS). Otherwise, it’s shown through the transparent select element.
Although it felt clever to put this together, there are some risks:
Here it is in action:
See the Pen Faking a Select Placeholder by @seancdavis on CodePen .