Menús de selección y casillas de verificación
Aplique estilos a los menús desplegables select y las casillas de verificación nativos, y utilice el plugin @tailwindcss/forms para normalizar los estilos de formularios entre navegadores.
Menús de selección y casillas de verificación es una lección gratuita de Tailwind CSS Academy en CoddyKit. Esta es la lección 2 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Tailwind CSS Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Tailwind CSS Academy incluye 4 lecciones en total.
Partes de esta lección aún no han sido traducidas y se muestran en inglés.
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.
Aprende HTML con un tutor de IA — gratis
Escribe y ejecuta código real en tu navegador, obtén ayuda instantánea de un tutor de IA disponible 24/7 y continúa donde lo dejaste en la web o en la aplicación.
- Cursos
- 30
- Lecciones
- 120
Preguntas frecuentes
¿La lección «Menús de selección y casillas de verificación» es gratis?
Sí — el texto completo de «Menús de selección y casillas de verificación» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Tailwind CSS Academy, actualiza a CoddyKit PRO. El curso de Tailwind CSS Academy incluye 4 lecciones en total.
¿Qué aprenderé en «Menús de selección y casillas de verificación»?
Aplique estilos a los menús desplegables select y las casillas de verificación nativos, y utilice el plugin @tailwindcss/forms para normalizar los estilos de formularios entre navegadores. Practicas Tailwind CSS Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar Tailwind CSS Academy?
No se requiere experiencia previa. Tailwind CSS Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 2 de 4.
¿Cuánto tiempo toma la lección «Menús de selección y casillas de verificación»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de Tailwind CSS Academy?
Sí. Cada lección de Tailwind CSS Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Estilos para inputs de texto y textareas
- Menús de selección y casillas de verificación
- Patrones de diseño de formularios
- Estados de validación y error