JavaScript/CSS/HTML || sliderRadioButton.js – Simple Animated Slider Radio Button Using Vanilla JavaScript
Radio buttons let a user select only one of a limited number of choices. Radio buttons are normally presented in radio groups (a collection of radio buttons describing a set of related options). Only one radio button in a group can be selected at the same time.
Using JavaScript, the following is sample code which demonstrates how to display a simple animated slider radio button group to the page.
This animated slider radio button comes with a few basic features. When a selection is chosen, a sliding animation appears. The speed of the animation can be modified via CSS transitions. The look and orientation can also be modified via CSS, with the button group direction being either vertical or horizontal.
Contents
1. Basic Usage
2. Slider HTML - Default
3. Slider HTML - Column
4. sliderRadioButton.js & CSS Source
5. More Examples
1. Basic Usage
Syntax is very straightforward. The following demonstrates the JavaScript used to setup the radio buttons decorated with the ‘slider’ CSS class.
1 2 3 4 5 6 7 8 |
// Initialize slider. <script> document.addEventListener("DOMContentLoaded", function(eventLoaded) { // Initialize slider Slider.init(); }); </script> |
2. Slider HTML – Default
The following is an example of the HTML used to display the slider. By default, the options are displayed inline.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<!-- // HTML --> <!-- Radio Group --> <div class="slider-radio-group"> <!-- Option 1 --> <input type="radio" class="slider-radio-button" id="rdoSole" value="Solé" name="rdoGroupName"> <label class="slider-option-label" for="rdoSole">Solé</label> <!-- Option 2 --> <input type="radio" class="slider-radio-button" id="rdoLynn" value="Lynn" name="rdoGroupName"> <label class="slider-option-label" for="rdoLynn">Lynn</label> <!-- Option 3 --> <input type="radio" class="slider-radio-button" id="rdoJennifer" value="Jennifer" name="rdoGroupName"> <label class="slider-option-label" for="rdoJennifer">Jennifer</label> <!-- Option 4 --> <input type="radio" class="slider-radio-button" id="rdoKenneth" value="Kenneth" name="rdoGroupName"> <label class="slider-option-label" for="rdoKenneth">Kenneth</label> </div> |
3. Slider HTML – Column
The following is an example of the HTML used to display the slider as a column.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<!-- // HTML --> <!-- Radio Group --> <div class="slider-radio-group column"> <!-- Option 1 --> <input type="radio" class="slider-radio-button" id="rdoRed" value="Red" name="rdoGroupColor"> <label class="slider-option-label" for="rdoRed">Red</label> <!-- Option 2 --> <input type="radio" class="slider-radio-button" id="rdoBlue" value="Blue" name="rdoGroupColor"> <label class="slider-option-label" for="rdoBlue">Blue</label> <!-- Option 3 --> <input type="radio" class="slider-radio-button" id="rdoBlack" value="Black" name="rdoGroupColor"> <label class="slider-option-label" for="rdoBlack">Black</label> <!-- Option 4 --> <input type="radio" class="slider-radio-button" id="rdoYellow" value="Yellow" name="rdoGroupColor"> <label class="slider-option-label" for="rdoYellow">Yellow</label> <!-- Option 5 --> <input type="radio" class="slider-radio-button" id="rdoPurple" value="Purple" name="rdoGroupColor"> <label class="slider-option-label" for="rdoPurple">Purple</label> </div> |
4. sliderRadioButton.js & CSS Source
The following is the sliderRadioButton.js Namespace & CSS Source. Include this in your project to start using!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 |
// ============================================================================ // Author: Kenneth Perkins // Date: Jun 12, 2020 // Taken From: http://programmingnotes.org/ // File: sliderRadioButton.js // Description: Javascript that handles the animation for a slider radio // button. // ============================================================================ /** * NAMESPACE: Slider * USE: Handles the sliding animation for the Slider Radio Button. */ var Slider = Slider || {}; (function(namespace) { 'use strict'; // -- Public data -- // Property to hold public variables and functions let exposed = namespace; // Set class names and other shared data const settings = { classNameRadioGroup: '.slider-radio-group', classNameRadioButton: '.slider-radio-button', classNameRadioButtonLabel: 'slider-option-label', classNameSelectedItem: '.slider-selected-item', classNameRadioColumn: '.column', classNameLabelContent: '.slider-option-label-content', clean: (str) => { return str ? str.trim().replace('.', '') : ''; } }; exposed.settings = settings; /** * FUNCTION: init * USE: Initializes the slider radio groups and button clicks. * @param element: JavaScript element to search for radio groups * @return: N/A. */ exposed.init = (element = document) => { exposed.prepareRadioGroups(element); addClickEvents(element); } /** * FUNCTION: animate * USE: Handles the sliding animation of a radio button. * @param radioButton: JavaScript element (radio button) that the * slider animation should be applied to. * @return: N/A. */ exposed.animate = (radioButton) => { if (!radioButton) { throw new Error('Radio button does not exist!'); } // Get the radio group for this button and make sure it exists let radioGroup = exposed.getGroupForButton(radioButton); if (!radioGroup) { throw new Error('Unable to find radio group!'); } // Get the radio button label and make sure it exists let radioButtonLabel = exposed.getLabelForButton(radioButton, radioGroup); if (!radioButtonLabel) { throw new Error('Unable to find radio option label!'); } // Get the "selected item" slider div that marks the // label as selected and make sure it exists let selectedItem = exposed.getSelectedItem(radioGroup); if (!selectedItem) { throw new Error('Unable to find selected item slider animation element!'); } // Mark the option label as selected markAsSelected(radioButtonLabel, selectedItem); } /** * FUNCTION: prepareRadioGroups * USE: Makes sure radio groups contain the "selected item" slider div * and makes sure radio column groups are set up properly * @param element: JavaScript element to search for radio groups * @return: N/A. */ exposed.prepareRadioGroups = (element = document) => { // Get radio groups and make sure it exists let radioGroups = exposed.getRadioGroups(element); if (!radioGroups) { throw new Error('Unable to find a radio group!'); } // Go through radio groups and make sure they are setup properly for (const radioGroup of radioGroups) { // Make sure the "selected item" slider div exists. Add it in if it does not let selectedItemElement = exposed.getSelectedItem(radioGroup); if (!selectedItemElement) { selectedItemElement = document.createElement('div'); selectedItemElement.classList.add(settings.clean(settings.classNameSelectedItem)); radioGroup.appendChild(selectedItemElement); } // Get radio buttons for this group and make sure it exists let radioButtons = exposed.getRadioButtons(radioGroup); if (!radioButtons) { continue; } let classRadioColumn = settings.clean(settings.classNameRadioColumn); for (const radioButton of radioButtons) { // Check to see if this radio group is marked as a "column". If it is, // also add the associated class to its linked radio button elements if (radioGroup.classList.contains(classRadioColumn) && !radioButton.classList.contains(classRadioColumn)) { radioButton.classList.add(classRadioColumn); } let radioButtonLabel = exposed.getLabelForButton(radioButton, radioGroup); if (!radioButtonLabel) { continue; } let container = document.createElement('div'); container.classList.add(settings.clean(settings.classNameLabelContent)); while (radioButtonLabel.hasChildNodes()) { container.appendChild(radioButtonLabel.firstChild); } radioButtonLabel.appendChild(container); } } } /** * FUNCTION: getRadioGroups * USE: Returns the radio groups that are descendants of the object on * which this method was called. * @param element: JavaScript element to search for radio groups * @return: Radio group descendants found in the given element. */ exposed.getRadioGroups = (element = document) => { return element.querySelectorAll(settings.classNameRadioGroup); } /** * FUNCTION: getRadioButtons * USE: Returns the radio buttons that are descendants of the object on * which this method was called. * @param element: JavaScript element to search for radio buttons * @return: Radio button descendants found in the given element. */ exposed.getRadioButtons = (element = document) => { return element.querySelectorAll(settings.classNameRadioButton); } /** * FUNCTION: getGroupForButton * USE: Returns the radio group that is a parent of * the object on which this method was called. * @param radioButton: JavaScript element representing the radio button * @return: Radio button label descendant found in the given element. */ exposed.getGroupForButton = (radioButton) => { return radioButton.closest(settings.classNameRadioGroup); } /** * FUNCTION: getLabelForButton * USE: Returns the radio button label that is a descendant of * the object on which this method was called. * @param radioButton: JavaScript element representing the radio button * @param element: JavaScript parent element of the radio button * @return: Radio button label descendant found in the given element. */ exposed.getLabelForButton = (radioButton, element = document) => { return element.querySelector('label[for="' + radioButton.id + '"]'); } /** * FUNCTION: getSelectedItem * USE: Returns the "selected item" div for the object on which this * method was called. * @param element: JavaScript element to search for the "selected item" * @return: The "selected item" div found in the given element. */ exposed.getSelectedItem = (element = document) => { return element.querySelector(settings.classNameSelectedItem); } /** * FUNCTION: getSelectedRadioButton * USE: Returns the selected (checked) radio button that is * descendant of the object on which this method was called. * @param element: JavaScript element to search for radio buttons * @return: Selected radio button descendant found in the given element. */ exposed.getSelectedRadioButton = (element = document) => { let selectedButton = null; let buttons = exposed.getRadioButtons(element); for (const button of buttons) { if (button.checked) { selectedButton = button; break; } } return selectedButton; } // -- Private data -- /** * FUNCTION: addClickEvents * USE: Adds slider animation button click events for the radio buttons. * @param element: JavaScript element to search for radio groups * @return: N/A. */ let addClickEvents = (element = document) => { // Go through each radio button to initialize any that are selected/set button clicks exposed.getRadioButtons(element).forEach((radioButton, index) => { // If the radio button is checked, animate the selection if (radioButton.checked) { exposed.animate(radioButton); } // Add click events to update the selected radio button radioButton.addEventListener('click', (eventClick) => { exposed.animate(radioButton); }); }); } /** * FUNCTION: markAsSelected * USE: Marks the radio button label as "selected" and performs * the slider animation by moving the "selected item" div to * the location of the radio button label. * @param radioButtonLabel: JavaScript element (label) linked to the selected radio button * @param selectedItem: JavaScript element (div) for "selected item" * @return: N/A. */ let markAsSelected = (radioButtonLabel, selectedItem) => { let radioButtonLabelCoords = getElementCoords(radioButtonLabel, true); moveElement(selectedItem, radioButtonLabelCoords); selectedItem.style.display = 'block'; } /** * FUNCTION: moveElement * USE: Moves an element to a specific location and resizes it * to a specific size. * @param element: JavaScript element to move * @param coords: Coordinates to move & resize the element to * @return: N/A. */ let moveElement = (element, coords) => { element.style.left = coords.x + 'px'; element.style.top = coords.y + 'px'; element.style.width = coords.width + 'px'; element.style.height = coords.height + 'px'; } /** * FUNCTION: getElementCoords * USE: Gets the coordinates & size of an element. * @param element: JavaScript element in question * @param roundUp: Determines if element coordinates should * be rounded up or not * @return: The coordinates of the element in question. */ let getElementCoords = (element, roundUp = true) => { const boundingRect = element.getBoundingClientRect(); let coords = { x: element.offsetLeft, y: element.offsetTop, width: boundingRect.width, height: boundingRect.height } if (roundUp) { for (const prop in coords) { let item = coords[prop]; if (isNumber(item)) { coords[prop] = Math.ceil(item); } } } return coords; } let isNumber = (n) => { return !isNaN(parseFloat(n)) && !isNaN(n - 0) } (function (factory) { if (typeof define === 'function' && define.amd) { define([], factory); } else if (typeof exports === 'object') { module.exports = factory(); } }(function() { return namespace; })); }(Slider)); // http://programmingnotes.org/ |
The following is sliderRadioButton.css.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
/* // ============================================================================ // Author: Kenneth Perkins // Date: Jun 12, 2020 // Taken From: http://programmingnotes.org/ // File: sliderRadioButton.css // Description: CSS that handles the animation for a slider radio // button. // ============================================================================ */ @import url('https://fonts.googleapis.com/css?family=Roboto'); .slider-radio-group { border: solid 1px #bdbdbd; margin: 5px; border-radius: 10px; overflow: hidden; width: 420px; position: relative; font-family: roboto; display: flex; justify-content: center; align-items: center; } .slider-radio-group.column { width: 100px; flex-direction: column; } .slider-radio-button { visibility: hidden; display: none; } .slider-radio-button.column { } input[type=radio][class*="slider-radio-button" i]:checked + label { background-color: rgba(117, 190, 218, .3); } input[type=radio][class*="slider-radio-button" i]:not(:first-child) + label { border-left: solid 1px lightgrey; } input[type=radio][class*="slider-radio-button column" i]:not(:first-child) + label { border-top: solid 1px lightgrey; } .slider-option-label { display: inline-block; cursor: pointer; padding: 5px; width: 110px; text-align:center; background-color: #f3f4f4; overflow: hidden; box-sizing: border-box; } .slider-option-label:hover { background-color: #eef6fa; } .slider-option-label-content { position: relative; z-index: 1; } .slider-selected-item { cursor: pointer; position: absolute; transition: all 400ms ease-in-out; background-color: rgba(117, 190, 218, .25); display:none; } /* // http://programmingnotes.org/ */ |
5. More Examples
Below are more examples demonstrating the use of ‘sliderRadioButton.js‘. Don’t forget to include the module when running the examples!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
<!-- // ============================================================================ // Author: Kenneth Perkins // Date: Jun 12, 2020 // Taken From: http://programmingnotes.org/ // File: sliderRadioButtonDemo.html // Description: Demonstrates how to display a simple animated // slider radio button to the page. // ============================================================================ --> <!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title>My Programming Notes Simple Animated Slider Radio Button Demo</title> <style> .button { padding: 8px; background-color: #d2d2d2; height:100%; text-align:center; text-decoration:none; color:black; display: flex; justify-content: center; align-items: center; flex-direction: column; border-radius: 15px; cursor: pointer; } .button.medium { height:18px; width:80px; } .section-header { margin-top: 20px; text-align:center; font-size: 15px; font-weight: bold; font-style: italic; font-family: Tahoma,helvetica,arial,sans-serif; } .inline { display:inline-block; } .main { text-align:center; margin-left:auto; margin-right:auto; } .emoji { font-size:13px } </style> <!-- // Include module --> <link type="text/css" rel="stylesheet" href="./sliderRadioButton.css"> <script type="text/javascript" src="./sliderRadioButton.js"></script> </head> <body> <div class="main"> <div class="inline" style="margin: 5px;"> <div> <div class="section-header"> Rate Our Service </div> <!-- Radio Group 1 --> <div class="slider-radio-group"> <!-- Option 1 --> <input type="radio" class="slider-radio-button" id="rdoOneStar" value="1" name="rdoGroupRatings"> <label class="slider-option-label" for="rdoOneStar"><span class="emoji">⭐</span></label> <!-- Option 2 --> <input type="radio" class="slider-radio-button" id="rdoTwoStar" value="2" name="rdoGroupRatings"> <label class="slider-option-label" for="rdoTwoStar"><span class="emoji">⭐⭐</span></label> <!-- Option 3 --> <input type="radio" class="slider-radio-button" id="rdoThreeStar" value="3" name="rdoGroupRatings"> <label class="slider-option-label" for="rdoThreeStar"><span class="emoji">⭐⭐⭐</span></label> <!-- Option 4 --> <input type="radio" class="slider-radio-button" id="rdoFourStar" value="4" name="rdoGroupRatings"> <label class="slider-option-label" for="rdoFourStar"><span class="emoji">⭐⭐⭐⭐</span></label> </div> </div> <div> <div class="section-header"> Favorite Name </div> <!-- Radio Group 2 --> <div class="slider-radio-group"> <!-- Option 1 --> <input type="radio" class="slider-radio-button" id="rdoSole" value="Solé" name="rdoGroupName"> <label class="slider-option-label" for="rdoSole">Solé</label> <!-- Option 2 --> <input type="radio" class="slider-radio-button" id="rdoLynn" value="Lynn" name="rdoGroupName"> <label class="slider-option-label" for="rdoLynn">Lynn</label> <!-- Option 3 --> <input type="radio" class="slider-radio-button" id="rdoJennifer" value="Jennifer" name="rdoGroupName"> <label class="slider-option-label" for="rdoJennifer">Jennifer</label> <!-- Option 4 --> <input type="radio" class="slider-radio-button" id="rdoKenneth" value="Kenneth" name="rdoGroupName"> <label class="slider-option-label" for="rdoKenneth">Kenneth</label> </div> </div> <div class="inline"> <div class="section-header"> Favorite Color </div> <!-- Radio Group 3 --> <div class="slider-radio-group column"> <!-- Option 1 --> <input type="radio" class="slider-radio-button" id="rdoRed" value="Red" name="rdoGroupColor"> <label class="slider-option-label" for="rdoRed">Red</label> <!-- Option 2 --> <input type="radio" class="slider-radio-button" id="rdoBlue" value="Blue" name="rdoGroupColor"> <label class="slider-option-label" for="rdoBlue">Blue</label> <!-- Option 3 --> <input type="radio" class="slider-radio-button" id="rdoBlack" value="Black" name="rdoGroupColor"> <label class="slider-option-label" for="rdoBlack">Black</label> <!-- Option 4 --> <input type="radio" class="slider-radio-button" id="rdoYellow" value="Yellow" name="rdoGroupColor"> <label class="slider-option-label" for="rdoYellow">Yellow</label> <!-- Option 5 --> <input type="radio" class="slider-radio-button" id="rdoPurple" value="Purple" name="rdoGroupColor"> <label class="slider-option-label" for="rdoPurple">Purple</label> </div> </div> <div class="button section-header" id="btnSelect"> Select </div> </div> </div> <script> document.addEventListener("DOMContentLoaded", function(eventLoaded) { // Make sure the radio group is setup with the selected option slider div and other options // And add button clicks to animate the radio button slider Slider.init(); // Select button click document.querySelector('#btnSelect').addEventListener('click', function(eventClick) { let radioButtons = Slider.getRadioButtons(); let optionSelected = false; if (radioButtons) { for (const radioButton of radioButtons) { if (radioButton.checked) { alert(radioButton.id + ' is checked. Its value is: ' + radioButton.value); optionSelected = true; } } } if (!optionSelected) { alert('Please select an option!'); } }); }); </script> </body> </html><!-- // http://programmingnotes.org/ --> |
QUICK NOTES:
The highlighted lines are sections of interest to look out for.
The code is heavily commented, so no further insight is necessary. If you have any questions, feel free to leave a comment below.
Leave a Reply