Kris Selbekk
Kris Selbekk

Reputation: 7634

Styled select box with long options

I need to implement a custom select box with a max-width that's less than that of the options.

Styling the select box is easy enough (tons of guides are available all over the internet), here's my implementation of it:

HTML:

<div class="styled-select">
    <select>
        <option selected>All</option>
        <option>A short option</option>
        <option>A long option with way too much text</option>
        <option>Another way too long option, but even longer</option>
    </select>
</div>

CSS:

styled-select {
    overflow-x: hidden;
    width: 200px;
    background: #6d6d6d url("dropdown-image.png") 95% 50% no-repeat;
    padding: 5px;
}

.styled-select select {
    width: 130%;
    background: transparent;
    border: 0;
    color: white;
}

I created a JSFiddle to illustrate my problem. The extremely long string in the CSS is just a Base 64 encoded image.

Once a long option is selected, it will overflow the "fake" dropdown button and wreck havoc to my design. How can I hide the text overflowing the button, while still having a clickable "fake" button?

Upvotes: 0

Views: 215

Answers (1)

Terry
Terry

Reputation: 66133

My trick is to move the arrow into a pseudo-element, and position it absolutely within the .styled-select element. See fiddle here: http://jsfiddle.net/teddyrised/bx131j42/3/

.styled-select {
    position: relative;
    overflow-x: hidden;
    width: 200px;
    padding: 5px;
    background-color: #6d6d6d;
}
.styled-select::before {
    pointer-events: none;
    content: '';
    display: block;
    position: absolute;
    top: 0;
    bottom: 0;
    right: 0;
    width: 20%;
    background: #6d6d6d;
    background-image: (...);
    background-repeat: no-repeat;
    background-position: center center;
}

pointer-events: none is to ensure that the click event on the pseudo-element is ignored and passed to the <select> element lying underneath (which has a lower z-index). However, some browsers (IE10 and below, for example) do not support this. To circumvent this, you will have to use a real element (instead of a pseudo element, see my comment) and listen to the click handler on that element, and pass it off as a .focus() event on the <select> element, e.g.:

Markup:

<div class="styled-select">
    <span class="dummy-arrow"></span>
    <select><!-- options --></select>
</div>

JS:

$(function() {
    $('.dummy-arrow').click(function() {
        $(this).next('select').focus();
    });
});

Some tips:

  • <select> elements are notoriously hard to style because its appearance is highly OS specific. Some browsers/OS will honour the appearance: none declaration, but don't count on it. Instead, you might want to rely on a JS-based replacement/dummy.
  • If you want to remove the blue border around the select element on focus, use outline: none. However, note that this might affect usability of the site (if your select menu is not visually obvious).

Upvotes: 2

Related Questions