Custom Multi-Select Dropdown (CSS + Vanilla JavaScript)
Snippet Description
Upgrade default checkbox fields into a modern, searchable, and fully interactive multi-select dropdown using pure CSS and vanilla JavaScript.
This snippet is designed for WordPress users, works seamlessly with form builders, and integrates perfectly via WPCode Snippets.
Key Features
- Custom Dropdown Trigger
Replaces standard checkbox groups with a clean button showing selected count
- Live Search Filtering
Instantly filter options as users type
- Select All / Clear All Controls
Improve usability for large option lists
- Selected Item Tags (Chips)
Visual tags with individual remove buttons - Hover Tooltips
Automatically display full labels for truncated text - Keyboard Navigation & Accessibility
- Arrow keys
- Enter / Space
- Escape to close
- Smooth Animations & Transitions
Polished UI interactions throughout - Click-Outside & Done Button Handling
Explicit and intuitive close behavior
What’s Included in This Snippet
🎨 CSS
- Gradient backgrounds & borders
- Custom checkbox styling
- Responsive grid layout
- Tooltips using ::before and ::after
- Scrollbar customization
- Hover, focus, and animation effects
- Proper z-index layering
/* Hide original labels and checkboxes */ .jet-form-builder-row:has(.custom-dropdown-wrapper) > .jet-form-builder__label { display: none !important; } label[for="location_characteristics"], label[for="property_features"], label[for="outdoor_features"], label[for="interior_features"], label[for="community_amenities"], label[for="smart_home_features"] { display: none !important; } /* Dropdown Wrapper */ .custom-dropdown-wrapper { position: relative; width: 100%; font-family: inherit; } /* Trigger Button */ .custom-dropdown-trigger { width: 100%; padding: 14px 50px 14px 18px; background: linear-gradient(135deg, #1a472a 0%, #2d5a3d 100%); border: 2px solid #c9a227; border-radius: 10px; color: #fff; font-size: 15px; font-weight: 500; text-align: left; cursor: pointer; position: relative; transition: all 0.3s ease; box-shadow: 0 2px 8px rgba(0,0,0,0.15); } .custom-dropdown-trigger:hover { background: linear-gradient(135deg, #1e5233 0%, #357347 100%); box-shadow: 0 4px 12px rgba(0,0,0,0.2); } .custom-dropdown-trigger.open { border-radius: 10px 10px 0 0; border-bottom-color: transparent; } .custom-dropdown-trigger .trigger-arrow { position: absolute; right: 18px; top: 50%; transform: translateY(-50%); transition: transform 0.3s ease; font-size: 12px; } .custom-dropdown-trigger.open .trigger-arrow { transform: translateY(-50%) rotate(180deg); } .custom-dropdown-trigger .selection-count { position: absolute; right: 45px; top: 50%; transform: translateY(-50%); background: #c9a227; color: #1a472a; font-size: 12px; font-weight: 700; min-width: 24px; height: 24px; border-radius: 12px; display: inline-flex; align-items: center; justify-content: center; padding: 0 6px; } /* Tags Container */ .custom-dropdown-tags { display: flex; flex-wrap: wrap; gap: 8px; padding: 12px 0; min-height: 40px; } .tags-placeholder { color: #888; font-size: 13px; font-style: italic; } .selection-tag { display: inline-flex; align-items: center; gap: 6px; background: linear-gradient(135deg, #1a472a 0%, #2d5a3d 100%); color: #fff; padding: 6px 10px; border-radius: 20px; font-size: 13px; border: 1px solid #c9a227; transition: all 0.2s ease; } .selection-tag:hover { background: linear-gradient(135deg, #1e5233 0%, #357347 100%); } .selection-tag .tag-text { max-width: 150px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .selection-tag .tag-remove { cursor: pointer; font-size: 16px; font-weight: bold; line-height: 1; opacity: 0.7; transition: opacity 0.2s; color: #c9a227; } .selection-tag .tag-remove:hover { opacity: 1; } /* Dropdown Panel */ .custom-dropdown-panel { position: absolute; top: 100%; left: 0; right: 0; background: #fff; border: 2px solid #c9a227; border-top: none; border-radius: 0 0 10px 10px; box-shadow: 0 8px 24px rgba(0,0,0,0.15); z-index: 9999; display: none; animation: slideDown 0.25s ease; } .custom-dropdown-panel.open { display: block; } @keyframes slideDown { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: translateY(0); } } /* Search Input */ .custom-dropdown-search-wrapper { padding: 12px; border-bottom: 1px solid #e5e5e5; position: relative; } .custom-dropdown-search-wrapper::before { content: '🔍'; position: absolute; left: 22px; top: 50%; transform: translateY(-50%); font-size: 14px; opacity: 0.5; } .custom-dropdown-search { width: 100%; padding: 10px 12px 10px 36px; border: 1px solid #ddd; border-radius: 6px; font-size: 14px; transition: all 0.2s ease; } .custom-dropdown-search:focus { outline: none; border-color: #1a472a; box-shadow: 0 0 0 3px rgba(26, 71, 42, 0.1); } /* Action Buttons */ .custom-dropdown-actions { display: flex; gap: 10px; padding: 10px 12px; border-bottom: 1px solid #e5e5e5; background: #f8f9fa; } .btn-select-all, .btn-clear-all { flex: 1; padding: 8px 12px; border-radius: 6px; font-size: 13px; font-weight: 500; cursor: pointer; transition: all 0.2s ease; } .btn-select-all { background: #fff; border: 1px solid #1a472a; color: #1a472a; } .btn-select-all:hover { background: #1a472a; color: #fff; } .btn-clear-all { background: #fff; border: 1px solid #ddd; color: #666; } .btn-clear-all:hover { background: #dc3545; border-color: #dc3545; color: #fff; } /* Checkbox Grid */ .custom-dropdown-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; padding: 12px; max-height: 280px; overflow-y: auto; } @media (max-width: 768px) { .custom-dropdown-grid { grid-template-columns: repeat(2, 1fr); } } @media (max-width: 480px) { .custom-dropdown-grid { grid-template-columns: 1fr; } } /* Checkbox Items */ .custom-checkbox-item { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-radius: 6px; cursor: pointer; transition: all 0.15s ease; border: 1px solid transparent; position: relative; } .custom-checkbox-item:hover { background: #f0f7f2; border-color: #1a472a; } .custom-checkbox-item.selected { background: #e8f5e9; border-color: #1a472a; } .custom-checkbox-item.keyboard-focused { background: #f0f7f2; border-color: #c9a227; box-shadow: 0 0 0 2px rgba(201, 162, 39, 0.3); } /* Tooltip for long labels */ .custom-checkbox-item.has-tooltip::after { content: attr(data-tooltip); position: absolute; bottom: calc(100% + 8px); left: 50%; transform: translateX(-50%); background: #1a472a; color: #fff; padding: 8px 12px; border-radius: 6px; font-size: 12px; white-space: nowrap; max-width: 250px; overflow: hidden; text-overflow: ellipsis; z-index: 10000; opacity: 0; visibility: hidden; transition: opacity 0.2s ease, visibility 0.2s ease; pointer-events: none; box-shadow: 0 2px 8px rgba(0,0,0,0.2); } .custom-checkbox-item.has-tooltip::before { content: ''; position: absolute; bottom: calc(100% + 2px); left: 50%; transform: translateX(-50%); border: 6px solid transparent; border-top-color: #1a472a; opacity: 0; visibility: hidden; transition: opacity 0.2s ease, visibility 0.2s ease; pointer-events: none; } .custom-checkbox-item.has-tooltip:hover::after, .custom-checkbox-item.has-tooltip:hover::before { opacity: 1; visibility: visible; transition-delay: 0.3s; } /* Custom Checkbox */ .custom-checkbox { width: 20px; height: 20px; min-width: 20px; border: 2px solid #ccc; border-radius: 4px; display: flex; align-items: center; justify-content: center; transition: all 0.15s ease; background: #fff; } .custom-checkbox.checked { background: #1a472a; border-color: #1a472a; } .custom-checkbox.checked::after { content: '✓'; color: #c9a227; font-size: 14px; font-weight: bold; } /* Checkbox Label */ .custom-checkbox-label { font-size: 14px; color: #333; line-height: 1.3; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } /* No Results */ .custom-dropdown-no-results { grid-column: 1 / -1; text-align: center; padding: 20px; color: #888; font-style: italic; } /* Done Button */ .custom-dropdown-done-wrapper { padding: 12px; border-top: 1px solid #e5e5e5; background: #f8f9fa; } .btn-done { width: 100%; padding: 12px; background: linear-gradient(135deg, #1a472a 0%, #2d5a3d 100%); border: 2px solid #c9a227; border-radius: 8px; color: #fff; font-size: 15px; font-weight: 600; cursor: pointer; transition: all 0.2s ease; } .btn-done:hover { background: linear-gradient(135deg, #1e5233 0%, #357347 100%); box-shadow: 0 4px 12px rgba(0,0,0,0.2); transform: translateY(-1px); } /* Custom Scrollbar */ .custom-dropdown-grid::-webkit-scrollbar { width: 8px; } .custom-dropdown-grid::-webkit-scrollbar-track { background: #f1f1f1; border-radius: 4px; } .custom-dropdown-grid::-webkit-scrollbar-thumb { background: #1a472a; border-radius: 4px; } .custom-dropdown-grid::-webkit-scrollbar-thumb:hover { background: #2d5a3d; }
⚡ JavaScript
- Dynamic DOM manipulation
- Event handling & delegation
- Checkbox state management
- Real-time search logic
- Keyboard focus management
- Click-outside detection
- Reusable component structure
(function() {
'use strict';
const dropdownConfigs = [
{ fieldName: 'location_characteristics', label: 'Location Characteristics' },
{ fieldName: 'property_features', label: 'Property Features' },
{ fieldName: 'outdoor_features', label: 'Outdoor Features' },
{ fieldName: 'interior_features', label: 'Interior Features' },
{ fieldName: 'community_amenities', label: 'Community Amenities' },
{ fieldName: 'smart_home_features', label: 'Smart Home Features' },
{ fieldName: 'exterior_features', label: 'Exterior Features' },
{ fieldName: 'heating_cooling', label: 'Heating & Cooling' },
{ fieldName: 'estate_community_amenities', label: 'Estate / Community Amenities'},
{ fieldName: 'services_utilities', label: 'Services & Utilities'}
];
function createCustomDropdown(fieldName, label) {
const container = document.querySelector('[name="' + fieldName + '[]"]')?.closest('.jet-form-builder-row');
if (!container) {
console.log('Container not found for:', fieldName);
return;
}
const checkboxGroup = container.querySelector('.jet-form-builder__fields-group');
if (!checkboxGroup) {
console.log('Checkbox group not found for:', fieldName);
return;
}
const checkboxes = checkboxGroup.querySelectorAll('input[type="checkbox"]');
if (checkboxes.length === 0) {
console.log('No checkboxes found for:', fieldName);
return;
}
// Hide original checkbox group
checkboxGroup.style.display = 'none';
// Create wrapper
const wrapper = document.createElement('div');
wrapper.className = 'custom-dropdown-wrapper';
wrapper.setAttribute('data-field', fieldName);
// Create trigger button
const trigger = document.createElement('button');
trigger.type = 'button';
trigger.className = 'custom-dropdown-trigger';
trigger.innerHTML = '<span class="trigger-label">Select ' + label + '</span><span class="trigger-arrow">▼</span><span class="selection-count" style="display: none;">0</span>';
// Create tags container
const tagsContainer = document.createElement('div');
tagsContainer.className = 'custom-dropdown-tags';
tagsContainer.innerHTML = '<span class="tags-placeholder">No selections</span>';
// Create dropdown panel
const panel = document.createElement('div');
panel.className = 'custom-dropdown-panel';
// Search input
const searchWrapper = document.createElement('div');
searchWrapper.className = 'custom-dropdown-search-wrapper';
const searchInput = document.createElement('input');
searchInput.type = 'text';
searchInput.className = 'custom-dropdown-search';
searchInput.placeholder = 'Search options...';
searchWrapper.appendChild(searchInput);
// Action buttons
const actionsDiv = document.createElement('div');
actionsDiv.className = 'custom-dropdown-actions';
const selectAllBtn = document.createElement('button');
selectAllBtn.type = 'button';
selectAllBtn.className = 'btn-select-all';
selectAllBtn.textContent = 'Select All';
const clearAllBtn = document.createElement('button');
clearAllBtn.type = 'button';
clearAllBtn.className = 'btn-clear-all';
clearAllBtn.textContent = 'Clear All';
actionsDiv.appendChild(selectAllBtn);
actionsDiv.appendChild(clearAllBtn);
// Checkbox grid
const grid = document.createElement('div');
grid.className = 'custom-dropdown-grid';
// Create custom checkboxes
checkboxes.forEach(function(originalCheckbox, index) {
const labelText = originalCheckbox.nextElementSibling?.textContent ||
originalCheckbox.parentElement?.textContent?.trim() ||
originalCheckbox.value;
const item = document.createElement('div');
item.className = 'custom-checkbox-item';
item.setAttribute('data-label', labelText.toLowerCase());
item.setAttribute('data-index', index);
item.setAttribute('tabindex', '0');
item.setAttribute('role', 'option');
item.setAttribute('aria-selected', originalCheckbox.checked ? 'true' : 'false');
const checkbox = document.createElement('span');
checkbox.className = 'custom-checkbox' + (originalCheckbox.checked ? ' checked' : '');
const labelSpan = document.createElement('span');
labelSpan.className = 'custom-checkbox-label';
labelSpan.textContent = labelText;
// Add tooltip for long labels
if (labelText.length > 25) {
item.setAttribute('data-tooltip', labelText);
item.classList.add('has-tooltip');
}
item.appendChild(checkbox);
item.appendChild(labelSpan);
grid.appendChild(item);
if (originalCheckbox.checked) {
item.classList.add('selected');
}
// Click handler
item.addEventListener('mousedown', function(e) {
e.preventDefault();
e.stopPropagation();
const isChecked = !originalCheckbox.checked;
originalCheckbox.checked = isChecked;
checkbox.classList.toggle('checked', isChecked);
item.classList.toggle('selected', isChecked);
item.setAttribute('aria-selected', isChecked ? 'true' : 'false');
originalCheckbox.dispatchEvent(new Event('change', { bubbles: true }));
updateSelectionCount();
updateTags();
});
// Keyboard handler for individual items
item.addEventListener('keydown', function(e) {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
item.dispatchEvent(new MouseEvent('mousedown', { bubbles: true }));
}
});
});
// No results message
const noResults = document.createElement('div');
noResults.className = 'custom-dropdown-no-results';
noResults.textContent = 'No matching options';
noResults.style.display = 'none';
grid.appendChild(noResults);
// Done button
const doneWrapper = document.createElement('div');
doneWrapper.className = 'custom-dropdown-done-wrapper';
const doneBtn = document.createElement('button');
doneBtn.type = 'button';
doneBtn.className = 'btn-done';
doneBtn.innerHTML = '✓ Done';
doneWrapper.appendChild(doneBtn);
// Assemble panel
panel.appendChild(searchWrapper);
panel.appendChild(actionsDiv);
panel.appendChild(grid);
panel.appendChild(doneWrapper);
// Assemble wrapper
wrapper.appendChild(trigger);
wrapper.appendChild(tagsContainer);
wrapper.appendChild(panel);
// Insert after checkbox group
checkboxGroup.parentNode.insertBefore(wrapper, checkboxGroup.nextSibling);
// Update selection count
function updateSelectionCount() {
const count = Array.from(checkboxes).filter(cb => cb.checked).length;
const countSpan = trigger.querySelector('.selection-count');
if (count > 0) {
countSpan.textContent = count;
countSpan.style.display = 'inline-flex';
} else {
countSpan.style.display = 'none';
}
}
// Update tags display
function updateTags() {
const selectedItems = [];
checkboxes.forEach(function(cb) {
if (cb.checked) {
const labelText = cb.nextElementSibling?.textContent ||
cb.parentElement?.textContent?.trim() ||
cb.value;
selectedItems.push({ checkbox: cb, label: labelText });
}
});
tagsContainer.innerHTML = '';
if (selectedItems.length === 0) {
tagsContainer.innerHTML = '<span class="tags-placeholder">No selections</span>';
} else {
selectedItems.forEach(function(item) {
const tag = document.createElement('span');
tag.className = 'selection-tag';
tag.innerHTML = '<span class="tag-text">' + item.label + '</span><span class="tag-remove">×</span>';
tag.querySelector('.tag-remove').addEventListener('mousedown', function(e) {
e.preventDefault();
e.stopPropagation();
item.checkbox.checked = false;
item.checkbox.dispatchEvent(new Event('change', { bubbles: true }));
// Update the visual checkbox in the dropdown
const items = grid.querySelectorAll('.custom-checkbox-item');
items.forEach(function(gridItem, index) {
if (checkboxes[index] === item.checkbox) {
gridItem.classList.remove('selected');
gridItem.querySelector('.custom-checkbox').classList.remove('checked');
gridItem.setAttribute('aria-selected', 'false');
}
});
updateSelectionCount();
updateTags();
});
tagsContainer.appendChild(tag);
});
}
}
// Toggle dropdown
trigger.addEventListener('mousedown', function(e) {
e.preventDefault();
e.stopPropagation();
const isOpen = panel.classList.contains('open');
// Close all other dropdowns
document.querySelectorAll('.custom-dropdown-panel.open').forEach(function(p) {
p.classList.remove('open');
p.previousElementSibling?.previousElementSibling?.classList.remove('open');
});
if (!isOpen) {
panel.classList.add('open');
trigger.classList.add('open');
searchInput.focus();
currentFocusIndex = -1;
}
});
// Done button handler
doneBtn.addEventListener('mousedown', function(e) {
e.preventDefault();
e.stopPropagation();
panel.classList.remove('open');
trigger.classList.remove('open');
});
// Search functionality
searchInput.addEventListener('input', function() {
const searchTerm = this.value.toLowerCase();
const items = grid.querySelectorAll('.custom-checkbox-item');
let visibleCount = 0;
items.forEach(function(item) {
const label = item.getAttribute('data-label');
if (label && label.includes(searchTerm)) {
item.style.display = '';
visibleCount++;
} else {
item.style.display = 'none';
}
});
noResults.style.display = visibleCount === 0 ? 'block' : 'none';
});
// Select All handler
selectAllBtn.addEventListener('mousedown', function(e) {
e.preventDefault();
e.stopPropagation();
const items = grid.querySelectorAll('.custom-checkbox-item');
items.forEach(function(item, index) {
if (item.style.display !== 'none') {
checkboxes[index].checked = true;
item.classList.add('selected');
item.querySelector('.custom-checkbox').classList.add('checked');
item.setAttribute('aria-selected', 'true');
}
});
checkboxes[0]?.dispatchEvent(new Event('change', { bubbles: true }));
updateSelectionCount();
updateTags();
});
// Clear All handler
clearAllBtn.addEventListener('mousedown', function(e) {
e.preventDefault();
e.stopPropagation();
const items = grid.querySelectorAll('.custom-checkbox-item');
items.forEach(function(item, index) {
if (item.style.display !== 'none') {
checkboxes[index].checked = false;
item.classList.remove('selected');
item.querySelector('.custom-checkbox').classList.remove('checked');
item.setAttribute('aria-selected', 'false');
}
});
checkboxes[0]?.dispatchEvent(new Event('change', { bubbles: true }));
updateSelectionCount();
updateTags();
});
// Keyboard navigation
let currentFocusIndex = -1;
function getVisibleItems() {
return Array.from(grid.querySelectorAll('.custom-checkbox-item')).filter(item => item.style.display !== 'none');
}
function setFocusedItem(index) {
const visibleItems = getVisibleItems();
// Remove focus from all items
visibleItems.forEach(item => item.classList.remove('keyboard-focused'));
if (index >= 0 && index < visibleItems.length) {
currentFocusIndex = index;
visibleItems[index].classList.add('keyboard-focused');
visibleItems[index].scrollIntoView({ block: 'nearest' });
}
}
panel.addEventListener('keydown', function(e) {
const visibleItems = getVisibleItems();
switch (e.key) {
case 'ArrowDown':
e.preventDefault();
if (currentFocusIndex < visibleItems.length - 1) {
setFocusedItem(currentFocusIndex + 1);
} else {
setFocusedItem(0);
}
break;
case 'ArrowUp':
e.preventDefault();
if (currentFocusIndex > 0) {
setFocusedItem(currentFocusIndex - 1);
} else {
setFocusedItem(visibleItems.length - 1);
}
break;
case 'Enter':
case ' ':
if (currentFocusIndex >= 0 && document.activeElement !== searchInput) {
e.preventDefault();
visibleItems[currentFocusIndex]?.dispatchEvent(new MouseEvent('mousedown', { bubbles: true }));
}
break;
case 'Escape':
e.preventDefault();
panel.classList.remove('open');
trigger.classList.remove('open');
trigger.focus();
break;
}
});
// Initialize
updateSelectionCount();
updateTags();
}
// Close dropdowns when clicking outside
document.addEventListener('mousedown', function(e) {
if (!e.target.closest('.custom-dropdown-wrapper')) {
document.querySelectorAll('.custom-dropdown-panel.open').forEach(function(panel) {
panel.classList.remove('open');
panel.previousElementSibling?.previousElementSibling?.classList.remove('open');
});
}
});
// Initialize all dropdowns
function initDropdowns() {
dropdownConfigs.forEach(function(config) {
createCustomDropdown(config.fieldName, config.label);
});
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initDropdowns);
} else {
initDropdowns();
}
})();
Skill Level & Compatibility
Difficulty:
⭐⭐⭐⭐☆ (Intermediate → Advanced)
Best For:
- WordPress developers
- Form builder users (JetFormBuilder, custom forms, etc.)
- Front-end developers building reusable UI components
Requirements:
- Basic HTML & CSS knowledge
- JavaScript fundamentals
- Familiarity with DOM manipulation
Why Use This Snippet?
✔ No jQuery
✔ No dependencies
✔ Fully customizable
✔ Production-ready
✔ Accessible & responsive
Perfect for enhancing forms, filters, surveys, and advanced UI components in WordPress projects.
Usage Instructions
Installation (WPCode Snippets)
Step 1: Add CSS
- Copy the CSS section
- Paste it into:
- Your theme’s style.css, or
- WPCode Snippet → CSS Snippet, or
- Your page builder’s custom CSS panel
Step 2: Add JavaScript
- Copy the JavaScript section
- Paste it into:
- WPCode Snippet → JavaScript Snippet
- Ensure the script loads after page content (use defer or footer placement)
Step 3: Configure Target Fields
Update the checkbox field IDs inside the JavaScript:
const checkboxFields = [
'your-field-id-1',
'your-field-id-2',
'your-field-id-3'
];
Customization Options
Colors
#0a5c36 – Primary dark green
#28a745 – Accent green
#c9a227 – Gold highlight
Layout
grid-template-columns: repeat(3, 1fr);
(Change the number of columns as needed)
Tooltip Trigger Length
labelText.length > 25
(Adjust character count for tooltip activation)
Testing Checklist
- Open dropdown and verify options load
- Search and filter results
- Test Select All / Clear All
- Remove individual tags
- Keyboard navigation (↑ ↓ Enter Esc)
- Done button closes dropdown
- Click outside closes dropdown
- Hover over long labels for tooltips