Skip to content

Instantly share code, notes, and snippets.

@smonn
Last active December 17, 2015 06:49
Show Gist options
  • Save smonn/5568246 to your computer and use it in GitHub Desktop.
Save smonn/5568246 to your computer and use it in GitHub Desktop.
Custom HTML select with CSS and JavaScript.

Inspired by Roger Johansson's accessible, keyboard friendly custom select menu. The only real difference is that this snippet does not rely on jQuery (or any other third-party libraries). The minified and compressed code is less than 2 kB, which means this can be used without feeling bad for people with poor network bandwidth! Yay!

Simple usage, just include the JavaScript and CSS and then just before the closing <body> tag:

<script>
customSelectors('custom', 'custom-select');
</script>

Live demo

.custom-select-container {
position: relative;
margin: 5px 0 0 0;
overflow: hidden;
}
.custom-select-container .replaced {
border: 0;
filter: alpha(opacity=0); /* Move to IE-specific CSS file if you want to. */
line-height: 24px;
height: 28px;
opacity: 0;
position: relative;
width: 100%;
z-index: 10;
padding: 0;
margin: 0;
}
.custom-select-label {
display: block;
left: 0;
position: absolute;
top: 0;
width: 100%;
z-index: 1;
}
.custom-select-label > span {
background-color: #fff;
background-image: url('custom-field-buttons.gif');
background-repeat: no-repeat;
background-position: right -1px;
display: block;
padding: 5px 7px;
border: 1px solid #d7d7d7;
font-size: 12px;
line-height: 16px;
}
.custom-select-active > span {
border: 1px solid #b9b9b9;
background-position: right -29px;
}
.custom-select-text {
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin-right: 28px;
}
/*jslint browser: true */
(function (window, document) {
'use strict';
var createElement = function (tagName) {
return document.createElement(tagName);
},
getElements = function (tagName) {
return document.getElementsByTagName(tagName);
},
appendChild = function (parent, child) {
parent.appendChild(child);
},
addEvent = function (element, type, callback) {
if (element.addEventListener) {
element.addEventListener(type, callback, false);
} else if (element.attachEvent) {
element.attachEvent('on' + type, callback);
} else {
element['on' + type] = callback;
}
},
initialize = function (select, classNamePrefix) {
var parent = select.parentNode,
wrapper = createElement('div'),
spanOuter = createElement('span'),
spanMiddle = createElement('span'),
spanInner = createElement('span'),
getSelectedText = function () {
return select.options[select.selectedIndex].text;
},
createLabel = function () {
return document.createTextNode(getSelectedText());
},
label = createLabel(),
removeClass = function () {
spanOuter.className = spanOuter.className.replace(classNamePrefix + '-active ', '');
},
addClass = function () {
removeClass();
spanOuter.className = classNamePrefix + '-active ' + spanOuter.className;
},
change = function () {
spanInner.removeChild(label);
label = createLabel();
select.setAttribute('title', getSelectedText());
appendChild(spanInner, label);
};
select.setAttribute('title', getSelectedText());
select.className += ' replaced';
wrapper.className = classNamePrefix + '-container';
spanOuter.className = classNamePrefix + '-label';
spanInner.className = classNamePrefix + '-text';
spanOuter.setAttribute('aria-hidden', 'true');
appendChild(parent, wrapper);
appendChild(wrapper, select);
appendChild(wrapper, spanOuter);
appendChild(spanOuter, spanMiddle);
appendChild(spanMiddle, spanInner);
appendChild(spanInner, label);
addEvent(select, 'keyup', change);
addEvent(select, 'change', change);
addEvent(select, 'mouseover', addClass);
addEvent(select, 'mouseout', removeClass);
addEvent(select, 'focus', addClass);
addEvent(select, 'blur', removeClass);
};
window.customSelectors = function (classNameFilter, classNamePrefix) {
var i,
selectElements = getElements('select');
for (i = 0; i < selectElements.length; i += 1) {
if (selectElements[i].className.indexOf(classNameFilter) >= 0) {
initialize(selectElements[i], classNamePrefix);
}
}
};
}(window, document));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment