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 createElement for 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
← Validation i18n →