Custom templates using only emojis and CSS, with no external dependencies. Customize the appearance of items in the dropdown and selection.
Countries with Flags and Codes
Native flag emojis + badges with country codes.
View code
HTML
<select id="countries"></select>
JavaScript
const countriesData = [
{ id: 'us', text: 'United States', flag: '🇺🇸', code: 'US' },
{ id: 'br', text: 'Brazil', flag: '🇧🇷', code: 'BR' },
{ id: 'uk', text: 'United Kingdom', flag: '🇬🇧', code: 'UK' },
{ id: 'fr', text: 'France', flag: '🇫🇷', code: 'FR' },
{ id: 'de', text: 'Germany', flag: '🇩🇪', code: 'DE' }
];
new VanillaSmartSelect('#countries', {
data: countriesData,
placeholder: 'Select a country...',
allowClear: true,
templateResult: (item) => {
const div = document.createElement('div');
div.style.display = 'flex';
div.style.alignItems = 'center';
div.style.gap = '10px';
div.innerHTML = `
<span style="font-size: 24px;">${item.flag}</span>
<span style="font-weight: 500; flex: 1;">${item.text}</span>
<span style="background: #e9ecef; padding: 2px 8px; border-radius: 3px;
font-size: 11px; font-weight: 600;">${item.code}</span>
`;
return div;
},
templateSelection: (item) => {
return `${item.icon} ${item.text} - R$ ${item.price.toFixed(2).replace('.', ',')}`;
}
});
Users with Emoji Avatars
Colorful gradient avatars + role information.
View code
HTML
<select id="users"></select>
JavaScript
const usersData = [
{ id: 1, text: 'Ana Silva', role: 'Project Manager', emoji: '👩💼' },
{ id: 2, text: 'Carlos Santos', role: 'Senior Developer', emoji: '👨💻' },
{ id: 3, text: 'Maria Oliveira', role: 'UX/UI Designer', emoji: '👩🎨' },
{ id: 4, text: 'João Costa', role: 'Data Analyst', emoji: '👨🔬' },
{ id: 5, text: 'Paula Ferreira', role: 'Product Manager', emoji: '👩🚀' }
];
new VanillaSmartSelect('#users', {
data: usersData,
placeholder: 'Select a user...',
allowClear: true,
templateResult: (item) => {
const div = document.createElement('div');
div.style.display = 'flex';
div.style.alignItems = 'center';
div.style.gap = '12px';
div.innerHTML = `
<div style="font-size: 32px; width: 40px; height: 40px; display: flex;
align-items: center; justify-content: center;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 50%;">${item.emoji}</div>
<div>
<div style="font-weight: 500;">${item.text}</div>
<div style="font-size: 12px; color: #666;">${item.role}</div>
</div>
`;
return div;
},
templateSelection: (item) => {
return `${item.emoji} ${item.text}`;
}
});
Different Templates: Dropdown vs Selection
Demonstrates how to use detailed templates in dropdown and simplified ones in selection.
View code
HTML
<select id="employees"></select>
JavaScript
const employeesData = [
{ id: 1, text: 'Sarah Connor', role: 'Engineering Manager', department: 'Engineering', emoji: '👩💼' },
{ id: 2, text: 'Kyle Reese', role: 'Senior Developer', department: 'Engineering', emoji: '👨💻' },
{ id: 3, text: 'Miles Dyson', role: 'Tech Lead', department: 'Research', emoji: '👨🔬' },
{ id: 4, text: 'John Connor', role: 'Product Manager', department: 'Product', emoji: '👨🚀' }
];
new VanillaSmartSelect('#employees', {
data: employeesData,
placeholder: 'Select an employee...',
allowClear: true,
// Detailed template for dropdown
templateResult: (item) => {
const div = document.createElement('div');
div.style.display = 'flex';
div.style.alignItems = 'center';
div.style.gap = '12px';
div.innerHTML = `
<div style="width: 40px; height: 40px; display: flex; align-items: center;
justify-content: center; font-size: 24px; border-radius: 50%;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);">
${item.emoji}
</div>
<div>
<div style="font-weight: 500;">${item.text}</div>
<div style="font-size: 12px; color: #666;">
${item.role} • ${item.department}
</div>
</div>
`;
return div;
},
// Simplified template for selected item (name only)
templateSelection: (item) => {
return item.text;
}
});
✅ Flexibility: Use
templateResult to show detailed information in the dropdown
and templateSelection to keep the selection clean and compact.
Products with Icons and Prices
Emoji icons + name, category and formatted price.
View code
HTML
<select id="products"></select>
JavaScript
const productsData = [
{ id: 1, text: 'Notebook Pro', category: 'Electronics', price: 4299.90, icon: '💻', color: '#007bff' },
{ id: 2, text: 'Wireless Mouse', category: 'Peripherals', price: 89.90, icon: '🖱️', color: '#28a745' },
{ id: 3, text: 'Mechanical Keyboard', category: 'Peripherals', price: 349.90, icon: '⌨️', color: '#17a2b8' },
{ id: 4, text: 'Monitor 4K 27"', category: 'Electronics', price: 1899.90, icon: '🖥️', color: '#6f42c1' },
{ id: 5, text: 'HD Webcam', category: 'Accessories', price: 299.90, icon: '📹', color: '#fd7e14' }
];
new VanillaSmartSelect('#products', {
data: productsData,
placeholder: 'Select a product...',
allowClear: true,
templateResult: (item) => {
const div = document.createElement('div');
div.style.display = 'flex';
div.style.alignItems = 'center';
div.style.gap = '12px';
div.innerHTML = `
<div style="width: 40px; height: 40px; display: flex; align-items: center;
justify-content: center; border-radius: 8px; font-size: 24px;
background: ${item.color}20; color: ${item.color};">
${item.icon}
</div>
<div style="flex: 1;">
<div style="font-weight: 500;">${item.text}</div>
<div style="font-size: 12px; color: #666;">${item.category}</div>
</div>
<div style="font-weight: 600; color: #007bff;">
R$ ${item.price.toFixed(2).replace('.', ',')}
</div>
`;
return div;
},
templateSelection: (item) => {
return `${item.icon} ${item.text} - R$ ${item.price.toFixed(2).replace('.', ',')}`;
}
});
Tasks with Status (Multi-Select)
Multi-select with status icons and colored badges.
View code
HTML
<select id="tasks" multiple></select>
JavaScript
const tasksData = [
{ id: 1, text: 'Update documentation', status: 'active', statusText: 'In Progress', icon: '📝' },
{ id: 2, text: 'Fix bug #123', status: 'active', statusText: 'In Progress', icon: '🐛' },
{ id: 3, text: 'Review pull request', status: 'pending', statusText: 'Pending', icon: '👀' },
{ id: 4, text: 'Deploy to production', status: 'pending', statusText: 'Pending', icon: '🚀' },
{ id: 5, text: 'Implement feature X', status: 'completed', statusText: 'Completed', icon: '✅' }
];
const statusColors = {
active: { bg: '#d4edda', text: '#155724' },
pending: { bg: '#fff3cd', text: '#856404' },
completed: { bg: '#cce5ff', text: '#004085' },
cancelled: { bg: '#f8d7da', text: '#721c24' }
};
new VanillaSmartSelect('#tasks', {
data: tasksData,
placeholder: 'Select tasks...',
multiple: true,
maximumSelectionLength: 4,
templateResult: (item) => {
const div = document.createElement('div');
div.style.display = 'flex';
div.style.alignItems = 'center';
div.style.justifyContent = 'space-between';
div.style.gap = '12px';
const colors = statusColors[item.status];
div.innerHTML = `
<span style="font-size: 20px;">${item.icon}</span>
<span style="flex: 1;">${item.text}</span>
<span style="padding: 3px 10px; border-radius: 12px; font-size: 11px;
font-weight: 600; background: ${colors.bg}; color: ${colors.text};">
${item.statusText}
</span>
`;
return div;
},
templateSelection: (item) => {
return `${item.icon} ${item.text} - R$ ${item.price.toFixed(2).replace('.', ',')}`;
}
});
Categories with Counters
Simplified template in selection, detailed in dropdown.
View code
HTML
<select id="categories"></select>
JavaScript
const categoriesData = [
{ id: 1, text: 'Documents', icon: '📄', count: 127 },
{ id: 2, text: 'Images', icon: '🖼️', count: 543 },
{ id: 3, text: 'Videos', icon: '🎬', count: 89 },
{ id: 4, text: 'Music', icon: '🎵', count: 234 },
{ id: 5, text: 'Spreadsheets', icon: '📊', count: 67 }
];
new VanillaSmartSelect('#categories', {
data: categoriesData,
placeholder: 'Select a category...',
allowClear: true,
templateResult: (item) => {
const div = document.createElement('div');
div.style.display = 'flex';
div.style.alignItems = 'center';
div.style.gap = '10px';
div.innerHTML = `
<span style="font-size: 24px;">${item.icon}</span>
<div style="flex: 1;">
<span style="font-weight: 500;">${item.text}</span>
<span style="font-size: 11px; color: #666; background: #e9ecef;
padding: 2px 6px; border-radius: 10px; margin-left: 8px;">
${item.count} itens
</span>
</div>
`;
return div;
},
templateSelection: (item) => {
return `${item.icon} ${item.text}`;
}
});
How Templates Work
📋 Main Concepts:
- templateResult: Controls the appearance of items in the dropdown
- templateSelection: Controls the appearance of the selected item (selection field)
- Return: Can return HTML string or DOM element (createElement)
- Native emojis: Work in all modern browsers, no external images needed
- Inline CSS: Styles applied directly to elements for simplicity
Techniques and Best Practices
📋 Tips for Efficient Templates:
- createElement vs innerHTML: Use
createElementfor better security and performance - Data fallback: Always check if properties exist before using them
- Inline CSS vs classes: Inline is simpler for examples, classes are better for production
- Performance: Templates are rendered for each visible item - avoid heavy operations
- Test with volume: Check performance with 100+ items in the select
- Keep selection simple: templateSelection should be concise
- Details in dropdown: templateResult can have more information and visual elements
📌 Accessibility Recommendations:
- Contrast: Maintain adequate contrast between text and background (WCAG AA)
- Consistent sizes: Use consistent sizes for icons and visual elements
- Use native emojis: Work well with screen readers and don't depend on external resources
- Mobile responsive: Templates should work well on small screens
- Loading states: Provide visual feedback for loading remote data