Adding a Tooltip to a HTML Dropdown List

February 26, 2023

I’ve been playing about with some little features of my new site. The specific feature that I was working on was the ability to show any text that doesn’t fit into a drop-down list as a tooltip. If you want to see the final product, it’s here (feel free to add any useful resources!)

Typically, to add a tooltip to a HTML element, you’d set the title property, however, drop-down lists don’t have them; as a result, you can basically create the whole thing yourself. Starting with the HTML, you can create a simply div element:

<div>
    @Html.DropDownListFor(a => a.SelectedResource, 
        new SelectList(Model.ResourceList, "Id", "DisplayDescription"), null, 
        new { @class = "select-list-full-size", @size = "3" });        
</div>

<div id="tooltip"></div>

The next step is to add a little Javascript to get the two elements:

const select = document.querySelector('#SelectedResource');
const tooltip = document.querySelector('#tooltip');

There’s a couple of ways to do this - you can hide and show the tooltip element, but I wanted it to fade in and out, so I simply change the opacity of the tooltip:

select.addEventListener('mouseover', (event) => {            
    if (event.target.tagName === 'OPTION') {
        tooltip.innerText = event.target.innerText;
        tooltip.style.top = event.clientY + 'px';
        tooltip.style.left = event.clientX + 'px';
        tooltip.style.opacity = 0.7;
    }
});

select.addEventListener('mouseout', (event) => {
    if (event.target.tagName === 'OPTION') {
        tooltip.style.opacity = 0;
    }
});

The animation of fading in and out is a little CSS:

#tooltip {
    position: absolute;
    top: 0;
    left: 0;
    background-color: #000;
    color: #fff;
    padding: 5px;
    opacity: 0;
    transition: opacity 0.5s ease-in-out;
}

#tooltip.show {
    opacity: 0.7;
}

Finally, you need to handle the situation where the mouse moves within the dropdown, as well as outside the entire element:

select.addEventListener('change', (event) => {
    const selectedOption = event.target.selectedOptions[0];
    if (tooltip.innerText != selectedOption.innerText) {
        tooltip.innerText = selectedOption.innerText;
    }
});

It’s probably more fiddly than it needs to be, but it does the job. I guess that someone will tell me there’s a Javascript plug-in or library that does all this for me!



Profile picture

A blog about one man's journey through code… and some pictures of the Peak District
Twitter

© Paul Michaels 2024