选择菜单与复选框
设置原生选择下拉框和复选框的样式,并使用 @tailwindcss/forms 插件统一不同浏览器中的表单样式。
选择菜单与复选框 是 CoddyKit 上的免费 Tailwind CSS Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Tailwind CSS Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Tailwind CSS Academy 课程共包含 4 节课。
本课时的部分内容尚未翻译,以英文显示。
The Challenge With Native Form Controls
Native <select>, <checkbox>, and <radio> elements are notoriously difficult to style consistently across browsers. By default, they inherit the operating system's appearance using the appearance CSS property, which Tailwind resets with the appearance-none utility.
After removing the native appearance, you regain full control over styling. The @tailwindcss/forms plugin automates this reset for all form elements, giving you a clean cross-browser baseline without manually adding appearance-none everywhere.
<!-- Without plugin: manual appearance reset needed -->
<select class="appearance-none w-full px-3 py-2 border border-gray-300 rounded-lg">
<option>Option A</option>
</select>
<!-- With @tailwindcss/forms plugin: already normalized -->
<select class="w-full px-3 py-2 border border-gray-300 rounded-lg">
<option>Option A</option>
</select>Styling a Select Dropdown
A styled select uses the same base classes as a text input: w-full px-3 py-2 text-sm border border-gray-300 rounded-lg bg-white. Add a custom dropdown arrow by positioning a background SVG image or overlaying an absolutely positioned SVG icon.
The focus state uses the familiar focus:outline-none focus:ring-2 focus:ring-blue-500. Add cursor-pointer so the mouse cursor communicates that clicking opens a menu.
<div class="relative">
<select
class="w-full appearance-none px-3 py-2 text-sm text-gray-900 bg-white
border border-gray-300 rounded-lg cursor-pointer
focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent">
<option value="">Select a country</option>
<option value="us">United States</option>
<option value="uk">United Kingdom</option>
<option value="de">Germany</option>
</select>
<!-- Custom dropdown arrow -->
<div class="pointer-events-none absolute inset-y-0 right-3 flex items-center">
<svg class="w-4 h-4 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
</svg>
</div>
</div>Installing the Forms Plugin
The @tailwindcss/forms plugin provides an opinionated reset for all native form elements. Install it with npm install -D @tailwindcss/forms and add it to the plugins array in tailwind.config.js.
Once installed, all inputs, selects, textareas, checkboxes, and radio buttons receive a consistent base style. You can then layer Tailwind utilities on top without fighting browser defaults. Use require('@tailwindcss/forms')({ strategy: 'class' }) if you prefer the plugin to only apply when you add a specific class.
// tailwind.config.js
module.exports = {
content: ['./src/**/*.{html,js}'],
theme: {
extend: {},
},
plugins: [
require('@tailwindcss/forms'),
// Or with class strategy:
// require('@tailwindcss/forms')({ strategy: 'class' }),
],
}Styling Checkboxes
With the forms plugin, checkboxes are already normalized. You can then customize their size, color, and rounding with utilities. Use w-4 h-4 rounded text-blue-600 border-gray-300 — the text-blue-600 on a checkbox sets the fill color of the checkmark.
Pair the checkbox with a label using flex items-center gap-2 to keep them horizontally aligned. The label text uses text-sm font-medium text-gray-700.
<div class="flex items-center gap-2">
<input
id="terms"
type="checkbox"
class="w-4 h-4 rounded text-blue-600 border-gray-300
focus:ring-blue-500 focus:ring-2 cursor-pointer"
/>
<label for="terms" class="text-sm font-medium text-gray-700 cursor-pointer">
I agree to the <a href="/terms" class="text-blue-600 hover:underline">Terms of Service</a>
</label>
</div>Checkbox List for Multi-Select
A checkbox list allows users to select multiple options. Stack multiple checkbox items with space-y-3 on the container. Group them inside a <fieldset> with a <legend> for accessibility.
The legend identifies the entire group for screen readers, while individual labels are associated with their specific checkboxes via for/id attributes.
<fieldset>
<legend class="text-sm font-semibold text-gray-900 mb-3">Notification preferences</legend>
<div class="space-y-3">
<div class="flex items-center gap-2">
<input id="email-notif" type="checkbox" checked class="w-4 h-4 rounded text-blue-600 border-gray-300 focus:ring-blue-500" />
<label for="email-notif" class="text-sm text-gray-700">Email notifications</label>
</div>
<div class="flex items-center gap-2">
<input id="push-notif" type="checkbox" class="w-4 h-4 rounded text-blue-600 border-gray-300 focus:ring-blue-500" />
<label for="push-notif" class="text-sm text-gray-700">Push notifications</label>
</div>
<div class="flex items-center gap-2">
<input id="sms-notif" type="checkbox" class="w-4 h-4 rounded text-blue-600 border-gray-300 focus:ring-blue-500" />
<label for="sms-notif" class="text-sm text-gray-700">SMS notifications</label>
</div>
</div>
</fieldset>Styling Radio Buttons
Radio buttons are styled identically to checkboxes but use rounded-full instead of rounded to keep the circular appearance that users associate with single-selection. The text-blue-600 trick applies here too for the fill color.
All radio buttons in the same group must share the same name attribute so the browser enforces the single-selection constraint.
<fieldset>
<legend class="text-sm font-semibold text-gray-900 mb-3">Plan</legend>
<div class="space-y-2">
<div class="flex items-center gap-2">
<input id="plan-starter" type="radio" name="plan" value="starter"
class="w-4 h-4 text-blue-600 border-gray-300 focus:ring-blue-500" />
<label for="plan-starter" class="text-sm text-gray-700">Starter — Free</label>
</div>
<div class="flex items-center gap-2">
<input id="plan-pro" type="radio" name="plan" value="pro" checked
class="w-4 h-4 text-blue-600 border-gray-300 focus:ring-blue-500" />
<label for="plan-pro" class="text-sm text-gray-700">Pro — $29/mo</label>
</div>
<div class="flex items-center gap-2">
<input id="plan-enterprise" type="radio" name="plan" value="enterprise"
class="w-4 h-4 text-blue-600 border-gray-300 focus:ring-blue-500" />
<label for="plan-enterprise" class="text-sm text-gray-700">Enterprise — Custom</label>
</div>
</div>
</fieldset>Card-Style Radio Group
A card-style radio group wraps each option in a clickable card rather than showing a bare radio button. Hide the radio input visually but keep it accessible, and use the peer utility to style the card based on the input's checked state.
peer-checked:border-blue-600 peer-checked:ring-2 peer-checked:ring-blue-600 on the sibling label card creates a highlighted selection state with no JavaScript required.
<div class="grid grid-cols-3 gap-3">
<label class="cursor-pointer">
<input type="radio" name="tier" value="starter" class="sr-only peer" />
<div class="border-2 border-gray-200 rounded-lg p-4 text-center
peer-checked:border-blue-600 peer-checked:ring-2 peer-checked:ring-blue-600
hover:border-gray-300 transition-colors">
<p class="font-semibold text-gray-900">Starter</p>
<p class="text-sm text-gray-500">Free</p>
</div>
</label>
<label class="cursor-pointer">
<input type="radio" name="tier" value="pro" class="sr-only peer" checked />
<div class="border-2 border-gray-200 rounded-lg p-4 text-center
peer-checked:border-blue-600 peer-checked:ring-2 peer-checked:ring-blue-600
hover:border-gray-300 transition-colors">
<p class="font-semibold text-gray-900">Pro</p>
<p class="text-sm text-gray-500">$29/mo</p>
</div>
</label>
</div>Toggle Switch Component
A toggle switch is a styled checkbox that looks like a sliding on/off switch. Build it using an <input type='checkbox'> with sr-only and a sibling <div> that uses peer-checked utilities to animate.
The track uses w-11 h-6 bg-gray-200 rounded-full, and the knob uses an absolutely positioned w-4 h-4 bg-white rounded-full shadow. The peer-checked:translate-x-5 utility slides the knob right when checked.
<label class="flex items-center gap-3 cursor-pointer">
<div class="relative">
<input type="checkbox" class="sr-only peer" />
<div class="w-11 h-6 bg-gray-200 rounded-full transition-colors duration-200
peer-checked:bg-blue-600"></div>
<div class="absolute top-1 left-1 w-4 h-4 bg-white rounded-full shadow
transition-transform duration-200 peer-checked:translate-x-5"></div>
</div>
<span class="text-sm font-medium text-gray-700">Enable notifications</span>
</label>Custom Select With Search
The native <select> does not support searching. For searchable dropdowns, use a custom combination of an input + list. Show a text input where the user types, and filter a visible <ul> below it with JavaScript.
Style the dropdown list with absolute top-full left-0 right-0 mt-1 bg-white border border-gray-200 rounded-lg shadow-lg max-h-48 overflow-y-auto z-10 to position it correctly below the input.
<div class="relative">
<input
type="text"
placeholder="Search country..."
class="w-full px-3 py-2 text-sm border border-gray-300 rounded-lg
focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
<ul class="absolute top-full left-0 right-0 mt-1 bg-white border border-gray-200
rounded-lg shadow-lg max-h-48 overflow-y-auto z-10">
<li class="px-3 py-2 text-sm text-gray-700 hover:bg-blue-50 cursor-pointer">Germany</li>
<li class="px-3 py-2 text-sm text-gray-700 hover:bg-blue-50 cursor-pointer">France</li>
<li class="px-3 py-2 text-sm text-blue-600 font-medium bg-blue-50 cursor-pointer">United Kingdom</li>
<li class="px-3 py-2 text-sm text-gray-700 hover:bg-blue-50 cursor-pointer">United States</li>
</ul>
</div>Disabled Checkbox and Select
Disabled checkboxes and selects use the disabled: variant. For checkboxes: disabled:opacity-50 disabled:cursor-not-allowed dims the element. For selects: combine these with disabled:bg-gray-50 to match the text input disabled pattern.
Always add the HTML disabled attribute — Tailwind's disabled: variants only activate when this attribute is present on the element.
<!-- Disabled checkbox -->
<div class="flex items-center gap-2">
<input
type="checkbox"
disabled
class="w-4 h-4 rounded border-gray-300 disabled:opacity-50 disabled:cursor-not-allowed"
/>
<label class="text-sm text-gray-400">Unavailable option</label>
</div>
<!-- Disabled select -->
<select
disabled
class="w-full px-3 py-2 text-sm border border-gray-300 rounded-lg
disabled:bg-gray-50 disabled:text-gray-400 disabled:cursor-not-allowed">
<option>Disabled option</option>
</select>Range Input Styling
The <input type='range'> element creates a slider. With the forms plugin, you can style the track and thumb using accent-blue-600 — a CSS property that sets the color of native controls like range sliders, progress bars, and checkboxes with a single utility.
accent-blue-600 is the simplest way to brand native sliders without completely replacing them with custom components.
<div class="flex flex-col gap-1">
<label for="volume" class="text-sm font-medium text-gray-700">Volume: <span id="vol">50</span>%</label>
<input
id="volume"
type="range"
min="0"
max="100"
value="50"
oninput="document.getElementById('vol').textContent = this.value"
class="w-full h-2 accent-blue-600 cursor-pointer"
/>
</div>Quick Check
Test your understanding of Tailwind CSS Mastery concepts from this lesson.
Lesson Recap
In this lesson you learned: @tailwindcss/forms plugin normalizes native form elements across browsers giving a clean styling baseline; checkboxes and radios use text-blue-600 to set the fill color and focus:ring-blue-500 for focus rings; and the peer utility enables card-style radio groups and toggle switches that react to checked state without any JavaScript. Next up we design form layout patterns.
常见问题解答
「选择菜单与复选框」课时是免费的吗?
是的 — 「选择菜单与复选框」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Tailwind CSS Academy 课程的其余内容,请升级到 CoddyKit PRO。 Tailwind CSS Academy 课程共包含 4 节课。
「选择菜单与复选框」这节课中我会学到什么?
设置原生选择下拉框和复选框的样式,并使用 @tailwindcss/forms 插件统一不同浏览器中的表单样式。 你通过在浏览器中直接运行的动手代码来练习 Tailwind CSS Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Tailwind CSS Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Tailwind CSS Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「选择菜单与复选框」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Tailwind CSS Academy 课中编写并运行代码吗?
能。每节 Tailwind CSS Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 设置文本输入框与文本区域样式
- 选择菜单与复选框
- 表单布局模式
- 验证与错误状态