How to build custom form controls using HTML?

Custom form controls allow developers to create unique, styled form elements that match their website's design and provide enhanced user experiences. While HTML provides standard form elements like checkboxes, radio buttons, and input fields, building custom controls gives you complete control over appearance and behavior.

Syntax

Following is the basic syntax for creating custom form controls

<label class="custom-control">
   <input type="checkbox" class="visually-hidden">
   <span class="control-indicator"></span>
   Control Label
</label>

The pattern uses a label wrapper, hidden input element, custom visual indicator, and descriptive text. CSS provides the styling and pseudo-elements handle state changes.

Custom Form Control Using HTML and CSS

Pure CSS custom controls use the :checked pseudo-class and ::after pseudo-elements to create interactive visual feedback. This approach requires no JavaScript and works entirely through CSS selectors and state changes.

Example Custom Checkbox

<!DOCTYPE html>
<html>
<head>
   <title>Custom Checkbox Control</title>
   <style>
      body {
         font-family: Arial, sans-serif;
         padding: 20px;
      }
      .custom-checkbox {
         position: relative;
         display: inline-block;
         cursor: pointer;
         padding-left: 35px;
         line-height: 25px;
         margin: 10px;
      }
      .custom-checkbox input[type="checkbox"] {
         position: absolute;
         opacity: 0;
         cursor: pointer;
         height: 0;
         width: 0;
      }
      .checkmark {
         position: absolute;
         top: 0;
         left: 0;
         height: 25px;
         width: 25px;
         background-color: #f0f0f0;
         border: 2px solid #ddd;
         border-radius: 4px;
         transition: all 0.3s;
      }
      .custom-checkbox:hover input ~ .checkmark {
         background-color: #e6e6e6;
      }
      .custom-checkbox input:checked ~ .checkmark {
         background-color: #4CAF50;
         border-color: #4CAF50;
      }
      .checkmark:after {
         content: "";
         position: absolute;
         display: none;
         left: 8px;
         top: 4px;
         width: 6px;
         height: 12px;
         border: solid white;
         border-width: 0 3px 3px 0;
         transform: rotate(45deg);
      }
      .custom-checkbox input:checked ~ .checkmark:after {
         display: block;
      }
   </style>
</head>
<body>
   <h2>Custom Checkbox Controls</h2>
   <label class="custom-checkbox">
      Option 1
      <input type="checkbox">
      <span class="checkmark"></span>
   </label>
   <br>
   <label class="custom-checkbox">
      Option 2
      <input type="checkbox">
      <span class="checkmark"></span>
   </label>
</body>
</html>

The output shows custom-styled checkboxes with hover effects and smooth transitions

Custom Checkbox Controls

? Option 1
? Option 2

(Custom styled checkboxes with green background when checked and white checkmark)

Custom Radio Button Control

Radio buttons follow a similar pattern but use circular indicators and different visual styling to represent single-choice selections.

Example

<!DOCTYPE html>
<html>
<head>
   <title>Custom Radio Buttons</title>
   <style>
      body {
         font-family: Arial, sans-serif;
         padding: 20px;
      }
      .custom-radio {
         position: relative;
         display: block;
         cursor: pointer;
         padding-left: 35px;
         margin-bottom: 15px;
         line-height: 25px;
      }
      .custom-radio input[type="radio"] {
         position: absolute;
         opacity: 0;
         cursor: pointer;
      }
      .radio-mark {
         position: absolute;
         top: 0;
         left: 0;
         height: 25px;
         width: 25px;
         background-color: #f0f0f0;
         border: 2px solid #ddd;
         border-radius: 50%;
         transition: all 0.3s;
      }
      .custom-radio:hover input ~ .radio-mark {
         background-color: #e6e6e6;
      }
      .custom-radio input:checked ~ .radio-mark {
         background-color: #2196F3;
         border-color: #2196F3;
      }
      .radio-mark:after {
         content: "";
         position: absolute;
         display: none;
         top: 6px;
         left: 6px;
         width: 13px;
         height: 13px;
         border-radius: 50%;
         background: white;
      }
      .custom-radio input:checked ~ .radio-mark:after {
         display: block;
      }
   </style>
</head>
<body>
   <h2>Select Your Favorite Language</h2>
   <label class="custom-radio">
      JavaScript
      <input type="radio" name="language" value="javascript">
      <span class="radio-mark"></span>
   </label>
   <label class="custom-radio">
      Python
      <input type="radio" name="language" value="python">
      <span class="radio-mark"></span>
   </label>
   <label class="custom-radio">
      Java
      <input type="radio" name="language" value="java">
      <span class="radio-mark"></span>
   </label>
</body>
</html>

The output displays custom radio buttons with circular indicators and blue styling when selected

Select Your Favorite Language

? JavaScript
? Python  
? Java

(Custom styled radio buttons with blue background and white inner circle when selected)

Custom Form Control Using HTML, CSS, and JavaScript

JavaScript enables advanced interactivity, form validation, and dynamic behavior. You can handle events, update multiple elements, and create complex form interactions that pure CSS cannot achieve.

Example Interactive Toggle Switch

<!DOCTYPE html>
<html>
<head>
   <title>Custom Toggle Switch</title>
   <style>
      body {
         font-family: Arial, sans-serif;
         padding: 20px;
      }
      .toggle-switch {
         position: relative;
         display: inline-block;
         width: 60px;
         height: 30px;
         margin: 10px;
      }
      .toggle-switch input {
         opacity: 0;
         width: 0;
         height: 0;
      }
      .slider {
         position: absolute;
         cursor: pointer;
         top: 0;
         left: 0;
         right: 0;
         bottom: 0;
         background-color: #ccc;
         transition: 0.4s;
         border-radius: 30px;
      }
      .slider:before {
         position: absolute;
         content: "";
         height: 22px;
         width: 22px;
         left: 4px;
         bottom: 4px;
         background-color: white;
         transition: 0.4s;
         border-radius: 50%;
      }
      .toggle-switch input:checked + .slider {
         background-color: #4CAF50;
      }
      .toggle-switch input:checked + .slider:before {
         transform: translateX(30px);
      }
      .status {
         margin-left: 10px;
         font-weight: bold;
         color: #666;
      }
   </style>
</head>
<body>
   <h2>Custom Toggle Switches</h2>
   
   <div>
      Notifications:
      <label class="toggle-switch">
         <input type="checkbox" id="notifications" onchange="updateStatus('notifications')">
         <span class="slider"></span>
      </label>
      <span id="notif-status" class="status">OFF</span>
   </div>
   
   <div>
      Dark Mode:
      <label class="toggle-switch">
         <input type="checkbox" id="darkmode" onchange="updateStatus('darkmode')">
         <span class="slider"></span>
      </label>
      <span id="darkmode-status" class="status">OFF</span>
   </div>

   <script>
      function updateStatus(controlId) {
         const checkbox = document.getElementById(controlId);
         const statusElement = document.getElementById(controlId + '-status');
         
         if (checkbox.checked) {
            statusElement.textContent = 'ON';
            statusElement.style.color = '#4CAF50';
         } else {
            statusElement.textContent = 'OFF';
            statusElement.style.color = '#666';
         }
      }
   </script>
</body>
</html>

The output shows toggle switches that change appearance and update status text when clicked

Custom Toggle Switches

Notifications: [switch] OFF
Dark Mode:     [switch] OFF

(Toggle switches slide left/right with animated transitions and status updates)

Custom Range Slider Control

Range sliders require JavaScript for precise value tracking and real-time updates as users drag the slider handle.

Example

<!DOCTYPE html>
<html>
<head>
   <title>Custom Range Slider</title>
   <style>
      body {
         font-family: Arial, sans-serif;
         padding: 20px;
      }
      .slider-container {
         width: 300px;
         margin: 20px 0;
      }
      .range-slider {
         -webkit-appearance: none;
         width: 100%;
         height: 8px;
         border-radius: 5px;
         background: #ddd;
         outline: none;
         transition: background 0.3s;
      }
      .range-slider::-webkit-slider-thumb {
         -webkit-appearance: none;
         appearance: none;
         width: 20px;
         height: 20px;
         border-radius: 50%;
         background: #4CAF50;
         cursor: pointer;
         transition: background 0.3s;
      }
      .range-slider::-webkit-slider-thumb:hover {
         background: #45a049;
      }
      .range-slider::-moz-range-thumb {
         width: 20px;
         height: 20px;
         border-radius: 50%;
         background: #4CAF50;
         cursor: pointer;
         border: none;
      }
      .value-display {
         text-align: center;
         margin-top: 10px;
         font-weight: bold;
         font-size: 18px;
         color: #333;
      }
   </style>
</head>
<body>
   <h2>Volume Control</h2>
   <div class="slider-container">
      <input type="range" min="0" max="100" value="50" class="range-slider" id="volumeSlider" oninput="updateValue(this.value)">
      <div class="value-display">Volume: <span id="volumeValue">50</span>%</div>
   </div>

   <script>
      function updateValue(val) {
         document.getElementById('volumeValue').textContent = val;
         
         // Change color based on volume level
         const slider = document.getElementById('volumeSlider');
         if (val < 33) {
            slider.style.background = 'linear-gradient(to right, #4CAF50 0%, #4CAF50 ' + val*3 + '%, #ddd ' + val*3 + '%, #ddd 100%)';
         } else if (val < 66) {
            slider.style.background = 'linear-gradient(to right, #ff9800 0%, #ff9800 ' + val*1.5 + '%, #ddd ' + val*1.5 + '%, #ddd 100%)';
         } else {
            slider.style.background = 'linear-gradient(to right, #f44336 0%, #f44336 ' + val + '%, #ddd ' + val + '%, #ddd 100%)';
         }
      }
      
      // Initialize on page load
      updateValue(50);
   </script>
</body>
</html>

The output displays a custom range slider with dynamic color changes and real-time value updates

Volume Control

[??????????] 
Volume: 50%

(Range slider with green/orange/red colors based on volume level)
Updated on: 2026-03-16T21:38:54+05:30

509 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements