It can be a tricky one using vanilla CSS too but there is a workaround. If it's a required field, you can add the required attribute to your select element and use the :invalid pseudo class to style it as a placeholder. The idea is that if the first option is used as a placeholder, it's selected and disabled by default, that form field is invalid so you can style it a such.
In the snippet below I only add a required attribute and style the :invalid class directly, which is not really Tailwind-y, but it works:
@import url("https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css");
:invalid {
color: rgba(156, 163, 175, 1);
}
<select
type="text"
id="carType"
class="my-2 px-4 py-3 border rounded-lg text-black-primary focus:outline-none text-sm"
name="carType"
required
v-model="carType"
>
<option value="" disabled selected>Select your option</option>
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="mercedes">Mercedes</option>
<option value="audi">Audi</option>
</select>
Custom Tailwind variants
Although Tailwind has utilities like hover:, focus:, disabled:, etc, unfortunately it doesn't have an invalid: one. If you want to use the invalid:text-gray-400 variant, you need to create a plugin. Luckily, the docs has a nice example which can be used as a base for ours:
// tailwind.config.js
const plugin = require('tailwindcss/plugin');
module.exports = {
variants: {
textColor: ({ after }) => after(['invalid']),
},
plugins: [
plugin(function ({ addVariant, e }) {
addVariant('invalid', ({ modifySelectors, separator }) => {
modifySelectors(({ className }) => {
return `.${e(`invalid${separator}${className}`)}:invalid`;
});
});
}),
],
};
Now you can use the class as invalid:text-gray-400 in your select element, and get rid of the custom CSS style:
<select
type="text"
id="carType"
class="my-2 px-4 py-3 border rounded-lg text-black-primary invalid:text-gray-400 focus:outline-none text-sm"
name="carType"
required
v-model="carType"
>
<option value="" disabled selected>Select your option</option>
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="mercedes">Mercedes</option>
<option value="audi">Audi</option>
</select>
Vue conditional classes
As you're using Vue, a third option would be to use conditional classes. Just toggle between the two classes, text-gray-400 and text-black-primary based on the value of carType.