<dl class="custom-dropdown" aria-expanded="false">
  <dt class="custom-dropdown__title" data-value="">Select a country</dt>
  <dd class="custom-dropdown__item" data-value="BR">Brazil</dd>
  <dd class="custom-dropdown__item" data-value="NL">Netherlands</dd>
  <dd class="custom-dropdown__item" data-value="ES">Spain</dd>
  <dd class="custom-dropdown__item" data-value="TK">Turkey</dd>
  <dd class="custom-dropdown__item" data-value="US">United States</dd>
</dl>

<select class="dropdown" data-observer-changes>
  <option value="">Select a country</option>
  <option value="BR">Brazil</option>
  <option value="NL">Netherlands</option>
  <option value="ES">Spain</option>
  <option value="TK">Turkey</option>
  <option value="US">United States</option>
</select>

<p class="console">Listener Select field change value: <span></span></p>
.custom-dropdown {
  $self: &;
  list-style: none;
  margin: 0;
  padding: 0;
  cursor: pointer;
  border: 2px solid;
  display: inline-flex;
  flex-direction: column;
  font-family: Arial, 'sans-serif';
  
  &__title,
  &__item {
    margin: 0;
    padding: 10px 20px;
  }
  
  &__title {
    display: block;
    
    #{$self}[aria-expanded="true"] &,
    #{$self}:hover &{
      color: red;
    }
  }
  
  &__item {
    display: none;
    
    &:hover {
      background: #dcdcdc;
    }
    
    #{$self}[aria-expanded="true"] & {
      display: block;
    }
  }
}

.console {
  padding: 10px;
  border: 1px dotted;
  font-family: Arial, 'sans-serif';
}
View Compiled
class CustomDropDown {
  constructor() {
    this.customDropdown = document.querySelector('.custom-dropdown');
    this.customDropdownItems = [...this.customDropdown.querySelectorAll('.custom-dropdown__item')];
    this.console = document.querySelector('.console');
    this.dropdown = document.querySelector('.dropdown');
    
    this.init();
  }
  
  toggleCustomDropdown(evt) {
    const customDropDownEl = evt.currentTarget;
    const customDropDownStatus = customDropDownEl.getAttribute('aria-expanded');

    customDropDownEl.setAttribute('aria-expanded', customDropDownStatus === 'true' ? 'false' : 'true');
  }

  selectedCustomDropDown(evt) {
    const customDropDownClicked = evt.target;
    const dropDownOptionHasSelected = this.dropdown.querySelector(`option[selected]`);
    const dropDownOptionNewSelected = this.dropdown.querySelector(`option[value=${customDropDownClicked.dataset.value}]`);
    
    if(dropDownOptionHasSelected) {
      dropDownOptionHasSelected.removeAttribute('selected', '');
    }

    if(dropDownOptionNewSelected) {
      dropDownOptionNewSelected.setAttribute('selected', '');
    }
    
    this.dropdown.value = customDropDownClicked.dataset.value;
  }

  showCountrySelected(value) {
    this.console.querySelector('span').textContent = value;
  }
 
  listenDropDownChanges() {
    const observer = new MutationObserver(mutations => {
      const dropDownOptionSelected = mutations
        .filter(item => item.target[item.attributeName])
        .map(item => item.target.value);

      if(dropDownOptionSelected) {
        this.showCountrySelected(dropDownOptionSelected);
      }
    });

    observer.observe(this.dropdown, {
      subtree: true,
      attributes: true,
      attributeFilter: ['selected']
    });
  }  
  
  registerEvents() {
    this.customDropdown.addEventListener('click', evt => this.toggleCustomDropdown(evt));
    this.customDropdownItems.forEach(item => {
      item.addEventListener('click', evt => this.selectedCustomDropDown(evt));
    });
    
    this.listenDropDownChanges();
  }
  
  init() {
    this.registerEvents();
  }
}

new CustomDropDown();
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.