A Tailwind CSS plugin that provides comprehensive form element styling and normalization with base styles and utility classes
npx @tessl/cli install tessl/npm-tailwindcss--forms@0.5.0A Tailwind CSS plugin that provides comprehensive form element styling and normalization. It offers two strategies for applying styles: 'base' for global form element styling and 'class' for explicit utility classes, with support for all standard HTML form input types.
npm install -D @tailwindcss/formsconst forms = require('@tailwindcss/forms');For ES modules:
import forms from '@tailwindcss/forms';Add the plugin to your tailwind.config.js file:
// tailwind.config.js
module.exports = {
theme: {
// ...
},
plugins: [
require('@tailwindcss/forms'),
// ...
],
}With configuration options:
// tailwind.config.js
module.exports = {
plugins: [
require('@tailwindcss/forms')({
strategy: 'base', // only generate global styles
}),
// or
require('@tailwindcss/forms')({
strategy: 'class', // only generate classes
}),
],
}The @tailwindcss/forms plugin is built around the following design:
strategy optionMain plugin function that configures form styling behavior.
/**
* Tailwind CSS forms plugin created using plugin.withOptions()
* @param options - Configuration options for the plugin
* @returns Tailwind CSS plugin instance
*/
const forms = plugin.withOptions(function (options = { strategy: undefined }) {
// Plugin implementation
});
interface FormPluginOptions {
/** Strategy for applying form styles */
strategy?: 'base' | 'class';
}Configuration Details:
strategy: 'base' - Applies styles globally to form elements (default when combined with 'class')strategy: 'class' - Generates utility classes only (form-input, form-select, etc.)strategy: undefined - Applies both base styles and generates utility classes (default behavior)The plugin provides styling for all standard HTML form input types through two approaches:
When using base strategy, the following selectors receive automatic styling:
/* Text input types */
[type='text']
input:where(:not([type])) /* inputs without type attribute */
[type='email']
[type='url']
[type='password']
[type='number']
[type='date']
[type='datetime-local']
[type='month']
[type='search']
[type='tel']
[type='time']
[type='week']
/* Other form elements */
textarea
select
[multiple] /* multi-select elements */
[type='checkbox']
[type='radio']
[type='file'] /* minimal reset only */When using class strategy, the following utility classes are generated:
.form-input /* For text, email, password, number, date, etc. inputs */
.form-textarea /* For textarea elements */
.form-select /* For single select elements */
.form-multiselect /* For multiple select elements */
.form-checkbox /* For checkbox inputs */
.form-radio /* For radio inputs */All text-type inputs receive consistent styling with:
Select elements receive:
Checkbox and radio inputs feature:
File inputs receive minimal reset styling to preserve browser functionality while maintaining consistency.
The plugin provides comprehensive support for all HTML form input types:
type="text" - Standard text inputtype="email" - Email address inputtype="url" - URL inputtype="password" - Password inputtype="number" - Numeric inputtype="search" - Search inputtype="tel" - Telephone number inputtype="date" - Date pickertype="datetime-local" - Local date and timetype="month" - Month pickertype="time" - Time pickertype="week" - Week pickertype="checkbox" - Checkbox inputtype="radio" - Radio button inputtype="file" - File upload inputtextarea - Multi-line text inputselect - Single selection dropdownselect[multiple] - Multi-selection list<!-- Using base strategy (automatic styling) -->
<form>
<input type="text" placeholder="Full name" />
<input type="email" placeholder="Email address" />
<select>
<option>Choose option</option>
<option>Option 1</option>
<option>Option 2</option>
</select>
<textarea placeholder="Message"></textarea>
<input type="checkbox" id="agree" />
<label for="agree">I agree to terms</label>
</form><!-- Using class strategy (explicit classes) -->
<form>
<input type="text" class="form-input rounded-lg" placeholder="Full name" />
<input type="email" class="form-input rounded-lg" placeholder="Email" />
<select class="form-select rounded-lg">
<option>Choose option</option>
</select>
<textarea class="form-textarea rounded-lg" placeholder="Message"></textarea>
<input type="checkbox" class="form-checkbox text-blue-600" id="agree" />
</form><!-- Combining with Tailwind utilities -->
<input type="email" class="form-input px-4 py-3 rounded-full border-2 border-blue-300 focus:border-blue-500" />
<select class="form-select bg-gray-50 text-lg rounded-xl">
<option>Large rounded select</option>
</select>
<input type="checkbox" class="form-checkbox h-6 w-6 text-green-600 rounded-lg" />The plugin has minimal dependencies:
// External dependency for SVG data URI conversion
const svgToDataUri = require('mini-svg-data-uri');
// Tailwind CSS plugin utilities
const plugin = require('tailwindcss/plugin');
const defaultTheme = require('tailwindcss/defaultTheme');
const colors = require('tailwindcss/colors');
// Destructured defaults from Tailwind's default theme
const [baseFontSize, { lineHeight: baseLineHeight }] = defaultTheme.fontSize.base;
const { spacing, borderWidth, borderRadius } = defaultTheme;
/**
* Utility function to resolve color values with alpha-value placeholder support
* @param color - Color value that may contain '<alpha-value>' placeholder
* @param opacityVariableName - CSS custom property name for opacity
* @returns Resolved color value with proper opacity variable
*/
function resolveColor(color, opacityVariableName) {
return color.replace('<alpha-value>', `var(${opacityVariableName}, 1)`);
}
/**
* Internal utility to resolve chevron colors for select dropdown arrows
* @param color - Theme color path
* @param fallback - Fallback color value
* @returns Resolved color without CSS variables
*/
function resolveChevronColor(color, fallback) {
let resolved = theme(color);
if (!resolved || resolved.includes('var(')) {
return fallback;
}
return resolved.replace('<alpha-value>', '1');
}The plugin includes specific handling for browser compatibility issues:
The plugin includes TypeScript definitions:
declare const forms: {
(options?: Partial<{ strategy: 'base' | 'class' }>): {
handler: (tailwindApi: { addBase: Function; addComponents: Function; theme: Function }) => void;
};
__isOptionsFunction: true;
};
export = forms;