From our sponsor: Ready to show your plugin skills? Enter the Penpot Plugins Contest (Nov 15-Dec 15) to win cash prizes!
Today we’d like to share some inspiration for custom select styles with you. In forms where we’d like to use custom styles for the input elements, we can use JavaScript libraries that transform the HTML elements into a structure that allows us to do some better styling, especially for more complex inputs like the select element. Once a custom structure is in place, the possibilities are really endless and the aim of creating a better experience for the user can be reached more easily.
What kind of style is used depends of course on what is represented and what you want to know from your user using the input element. When replacing the select element with a custom structure it is very important to keep the new element accessible. Providing a label and focus styles are just some of the things you should keep in mind. Read more about some form accessibility in the HTML Techniques for Web Content Accessibility Guidelines 1.0 by the W3C.
For demo purposes, we are using a very raw custom script in our examples where the custom select element can be accessed by i.e. using the TAB key and hitting space. Note that we haven’t provided any substantial focus styles.
Please note that some of the styles are experimental and for the sole purpose of showing what’s possible (in modern browsers).
In the demos we use icons from the following icon sets: Ionicons, Font Awesome, Linecons and Maki.
The SVG flags used in one of the demos are from the Flag Webicons Set by Sean Herron.
The round icons used in one of the demos are from the free Ballicons 2 set by Pixel Buddha.
Tiny break: 📬 Want to stay up to date with frontend and trends in web design? Subscribe and get our Collective newsletter twice a tweek.
Let’s take a look at our custom select script. Having a select
element like the following
<select class="cs-select cs-skin-rotate"> <option value="" disabled selected>Choose your option</option> <option value="1">Option 1</option> <option value="2">Option 2</option> <option value="3">Option 3</option> </select>
… we’ll transform it into this structure:
<div class="cs-select cs-skin-rotate"> <span class="cs-placeholder">Choose your option</span> <div class="cs-options"> <ul> <li data-option data-value="1" class="cs-selected"><span>Option 1</span></li> <li data-option data-value="2"><span>Option 2</span></li> <li data-option data-value="3"><span>Option 3</span></li> </ul> </div> <select class="cs-select cs-skin-rotate"> <option value="" disabled selected>Choose your option</option> <option value="1">Option 1</option> <option value="2">Option 2</option> <option value="3">Option 3</option> </select> </div>
We are keeping the actual select
element because we’ll actually use it to set the selected value, which in turn will be submitted if we submit a form.
The “placeholder” is recognized by being disabled and having an empty value. It’s not a necessary option, it can be left out and the first option would instead be added to the first list item, or the one that has the selected
attribute.
Optionally, we can define a data-link
and a data-class
in an option of the select
element. The link option will allow to actually open a hyperlink when clicking a list item. When custom classes are needed on a list item, the data-class
attribute can be used.
The following options are available:
newTab : true, // open links in new tab (when data-link used in option) stickyPlaceholder : true, // when opening the select element, the default placeholder (if any) is shown onChange : function( val ) { return false; } // callback when changing the value
The stickyPlaceholder defines if the default placeholder text is shown every time we open the select element.
The basic styles for our examples are in the cs-select.css. Here we define some necessary styles for making the custom select look like a plain dropdown. The specific skin classes need the skin style sheet and an example for a specific skin is the following (border example):
@font-face { font-family: 'icomoon'; src:url('../fonts/icomoon/icomoon.eot?-rdnm34'); src:url('../fonts/icomoon/icomoon.eot?#iefix-rdnm34') format('embedded-opentype'), url('../fonts/icomoon/icomoon.woff?-rdnm34') format('woff'), url('../fonts/icomoon/icomoon.ttf?-rdnm34') format('truetype'), url('../fonts/icomoon/icomoon.svg?-rdnm34#icomoon') format('svg'); font-weight: normal; font-style: normal; } div.cs-skin-border { background: transparent; font-size: 2em; font-weight: 700; max-width: 600px; } @media screen and (max-width: 30em) { .cs-skin-border { font-size: 1em; } } .cs-skin-border > span { border: 5px solid #000; border-color: inherit; transition: background 0.2s, border-color 0.2s; } .cs-skin-border > span::after, .cs-skin-border .cs-selected span::after { font-family: 'icomoon'; content: 'e000'; } .cs-skin-border ul span::after { content: ''; opacity: 0; } .cs-skin-border .cs-selected span::after { content: 'e00e'; color: #ddd9c9; font-size: 1.5em; opacity: 1; transition: opacity 0.2s; } .cs-skin-border.cs-active > span { background: #fff; border-color: #fff; color: #2980b9; } .cs-skin-border .cs-options { color: #2980b9; font-size: 0.75em; opacity: 0; transition: opacity 0.2s, visibility 0s 0.2s; } .cs-skin-border.cs-active .cs-options { opacity: 1; transition: opacity 0.2s; } .cs-skin-border ul span { padding: 1em 2em; backface-visibility: hidden; } .cs-skin-border .cs-options li span:hover, .cs-skin-border li.cs-focus span { background: #f5f3ec; }
Take a look at the demos and see some examples of how a custom select can be styled.
We hope you enjoy them and find them inspiring!
Hey Mary Lou and thank you very much for this script.
Just three little things I notice :
– a semi-colon is missing on selectFx.js, line 133, just before “options += ‘</ul></li>’;” because if you want to minify the script (with javascriptPacker for example) console show an error (; missing before statment). I search a long time to fix this issue. 🙂
– if you use several select on the same page, option elements of the first one are underneath the second select. To fix the issue, z-index of div.cs-select have to be smaller than z-index of .cs-select.cs-active (for example 100 for the first one and 200 for the second).
– if the first option is null (or empty), height of this element is smaller than height of the others. To fix the issue, a non-breaking space ( ) have to be used between option tag for the first element (<option value=”0″>  ;</option>)
Thanks a lot again.
Regards.
Jerry, the code is now updated! Thanks a lot! Cheers.
Hi!
How did you manage to have several selects (i tried the “slide” version) on one page?
When I have 2 or more included, they double their size an break the page 🙁
Hello, Mari!
I need a big help. I’m having trouble adding a link within the option tag. <a href rel=”nofollow”> tag to add or change the value and nothing happens. What can I do?
It’s amazing!!!! senin ta??a??n? yirim!!
Hey ! Thx a lot for your work. I appreciate it a lot. I have some trouble with the “data-link” attribute. It always open a new tab :/
Thank you so much for all the hard awesome work you do!
I have a weird problem using the first select type: I’m trying to use jquery on change of the select to do some other stuff, but I noticed that it doesn’t work if I use the customized css select.
$('#divID').on('change', '#selectID', function() { alert('hello'); });
It is of course working fine , but If I use it on the customized select it won’t work!
Guess it’s because of some javascript code used by the select, but I can’t figure it out why!
Any ideas ? Thanks in advance
How can I access the selected value in Javascript?
Thanks a lot!!
Hi Mary!
I’m trying to turn the “slide” select into an AngularJS directive. It works great so far, but as soon as I have more than one select on the page, it breaks.
For making sure I didn’t screw up with my directive I tried putting 2 slide select elements on one page, and it broke as well.
Do you have any idea why we can’t have multiple slide selects on one page?
I’d be very happy about input from you genius! 🙂
take care,
pedro
I’ve created a small jQuery port for this for everyone willing to use jQuery instead of loading classie.js. It’s on my GitHub.
If you need more of these, let me know.
In case anyone tried to use it, it had a bug which is now fixed, and the port is tested and properly working. Sorry about the hiccup.
i’m used this script and it’s not working for me, not simple, not ajax)
I’m edit selectFx.js
~300 stroke, before callback paste
var val1 = this.selPlaceholder.textContent;
var idCheck = $(‘select:has(option:contains(‘+val1+’))’).attr(‘id’);
and after // callback this.options.onChange( this.el.value );
insert this: $(‘#’+idCheck+”).trigger(‘change’);
And thx for your css, it’s very very good 🙂
While my drop down is open & trying to scroll by mouse scroll, it scrolls whole page insted of drop down list scroll ? Please help me …. Thanks in advance.
Dear Mary,
I am using “overlay” mode, it is simply amazing. Thanks. Yet I have one question. I need to trigger change event from outside. I init it as:
vwt_SelectInstance = new selectFx(el,{stickyPlaceholder:false, onChange:function(el){ $('.jq-exf-conditional').load("<?=base_url('app/load_form');?>",{f:el}); } });
How can I trigger onChange event after page is fully loaded.
< ?php if($id==TRUE):? > vwt_SelectInstance.trigger('change') // I need something like this :) < ?php endif;? >
Thanks for any help
What I achieved till now.. It works but a very dirty var I suppose. Any better suggestion?
<?php if($id):?> $('span.vwt-SelectPlaceholder').html($('select.vwt-Select').find('option:selected').text()); vwt_SelectInstance._toggleSelect(); $('.vwt-SelectOptions').find('li[data-value="<?=$id;?>"]').addClass('vwt-SelectSelected').trigger('click'); <?php endif;?>
By the way, I modified class names for myself.
I have to capture that selected value.when an select option change .i have to store that selected value.can you please provide code.
Advance Thanks for any help
I used the following script to capture the selected value with jQuery and assign the selected attribute to the select element – option
added an ID attribute to line 138 in the selectFx.js
var opts_el = ” + options + ”;
(function($) {
$(‘#lista li’).click(function () {
var texto = $(this).data(‘value’);
$(‘#selectelement option’).filter(function(){
return this.value == texto;
}).prop(“selected”, true).change();
});
})(jQuery);
Hello, amazing solution, im try to customize elastic, but how can add the icon at active element? anyone can help me? thx
Hi Mary Lou,
How can i fill the selectFX from ajax? Or how can i destroy the selectFX and create it again?
Thanks.
did you find the answer?
first add id (selectBox) to element select
html
TODAS
javascript
function addOptions()
{
var xhr = new XMLHttpRequest();
var url =”myURL”;
xhr.open(“GET”, url);
xhr.send();
xhr.onreadystatechange = function()
{
if (xhr.readyState == 4 && xhr.status == 200)
{
var arr_DHCategoria = JSON.parse(xhr.responseText);
if(arr_DHCategoria.Categoria.length >= 1)
{
var lCategoria = “”;
var cat_id = “”;
var cat_descripcion = “”;
lCategoria += “TODAS”
for(i = 0 ; i < arr_DHCategoria.Categoria.length; i++)
{
cat_id=arr_DHCategoria.Categoria[i].IdCategoria;
cat_descripcion=arr_DHCategoria.Categoria[i].Descripcion;
lCategoria += "”+cat_descripcion+””;
}
console.log(lCategoria);
document.getElementById(“selectBox”).innerHTML = lCategoria;
}
}
}
}
the elements are added without problem, but they are not seen inside the menu …. apparently I have to call the function “_createSelectEl” but I have not been successful.
Can somebody help me ??
I’m attempting to get this working locally but am struggling. I’m not sure why but I can’t get it to do anything. I’m including jquery as well as classie.js and selectFX.js and the relevant CSS yet I don’t get any drop down when I click. Could anyone give me an idea of what I may be doing incorrectly here? I have to be missing something.
I used the elastic css style, and I noticed that if u use a LONG list of options (I used STATES in USA) there is the possibility that the list of items, also if invisible, make the whole page longer than the usual, adding white space at the bottom of the page.
This is because of the DIV of the options that also if they are invisible, they “keep space” in the page.
I fixed the issue changing the css as follow:
ORIGINAL
/* Options */
.cs-select .cs-options {
position: absolute;
overflow: hidden;
width: 100%;
background: #fff;
visibility: hidden;
}
.cs-select.cs-active .cs-options {
visibility:visible ;
}
MODIFIED IN
/* Options */
.cs-select .cs-options {
position: absolute;
overflow: hidden;
width: 100%;
background: #fff;
display: none;
}
.cs-select.cs-active .cs-options {
display:block ;
}
I hope is helpful.
Cheers
Wow, awesome demos. I’m not designer, just coder, and I was looking around for some custom & beautiful styles for like those…. I’ll give you credits!
hi, hi im using underline model, in the process i need to clone the cs-select but the value is not able to select when it is cloned. any solution?
Love this but really difficult to use with angular on select elements. ng-options or even ng-repeat breaks it…
hi, hi im using underline model, in the process i need to clone the cs-select but the value is not able to select when cs-select is cloned. here is the function.
$(document).ready(function() {
$(‘.addButton’).on(‘click’, function() {
var index = $(this).data(‘index’);
if (!index) {
index = 1;
$(this).data(‘index’, 1);
}
index++;
$(this).data(‘index’, index);
var template = $(this).attr(‘data-template’);
$templateEle = $(‘#’ + template + ‘Template’);
$row = $templateEle.clone().insertBefore($templateEle).removeClass(‘hide’).attr(‘id’,”formgroupid_”+index);
$actualrow = $row.find(‘div.row’).attr(‘id’,”rowid_”+index);
$el = $row.find(‘input’).eq(0).attr(‘name’, template + ‘[]’);
$sel = $row.find(‘select’).attr(‘id’, ‘selone’+index);
$divsel = $actualrow.find(‘div.cs-select’).attr(‘id’, ‘childelem’+index);
// Set random value for checkbox and textbox
});
});
Cool and inspiring stuff!
Playing with the slide select, not sure if it is a bug or not, but its not adding the class ‘cs-selected’ to the already selected option. (On page load)
This will fix it: (line ~100 on selectFx.js)
if (el.attributes["selected"]) { classes += 'cs-selected'; if (el.selectedOpt && !this.foundSelected && !this.hasDefaultPlaceholder) { this.foundSelected = true; } }
How do we reset the select, so that the default option is selected, once the form is been submitted. document.getElementById(‘register-form’).reset(); is not working in this case
This is awesome, but I need som help to integrate this to my site. Anyone now how to trigger the option list to selected value?
Right now i do this by: “onchange=”woocs_redirect(this.value); void(0);”” to my select item. Use the woocommerce currency switcher dropdown.
Grateful for help!
Jesper
Just fabulous!!
Hi I’ve seen that in Safari 9.0.1 + this effect (rotate) http://tympanus.net/Development/SelectInspiration/index6.html when activated makes a strange effect, like a scale transform… How do you think it can be fixed?
Regards,
D.
Love these selects! When using the Box select I cannot get the list to scroll and show all the options. Please help!
Use this code
Apply SelectFX
(function () {
[].slice.call(document.querySelectorAll(‘select.cs-select’)).forEach(function (el) {
new SelectFx(el);
});
})();
find the Selected drop down item
(function () {
SelectFx.prototype.options = {
onChange: function (val) { alert(val); return false; }
}
})();
Enjoy, Thanks for the Javascript effort
Put the onChange code in the document.ready();
Awesome. Thank you. I will give it a try ^_^
Hi Mary
Thanks for the amazing tutorial.
How can I change the value to link to another site (anchor mode)? If I put the link in the “value” it don’t work.
I tried with but it doesn’t work. Any help?
Thank You
Hello!, mi name is Walter, thanks for DropDown!.
I need help, i using MVC, when post, send value, how restore value selected in cast return the page??
I need restore value selected then post. Thaks!
Mary..these styles are just awesome! I really like them and would like to use them BUT..
is there a way to execute a js-function instead of opening a link?
Thx in advance!
Guys, I solved link problem using data-class and jQuery
$(document).ready(function(){
$(“.selectOptions”).bind(“click”, function(ele){
console.log(ele.currentTarget.textContent);
console.log(ele.currentTarget.dataset.value);
console.log(ele);
switch(ele.currentTarget.dataset.value){
}
});
});
Option1
Option2
Option3
Guys, I solved link problem using data-class and jQuery
$(document).ready(function(){
$(“.selectOptions”).bind(“click”, function(ele){
console.log(ele.currentTarget.textContent);
console.log(ele.currentTarget.dataset.value);
console.log(ele);
switch(ele.currentTarget.dataset.value){
case 1: yourJSfunc(); break;
case 2: yourJSfunc(); break;
case 3: yourJSfunc(); break;
default: break;
}
});
});
Option1
Option2
Option3
1
2
3
inset data-class=”selectOptions” in TAG
any other ideas?
Be careful, bind is deprecated in jQuery 3.
Hey,
I was hoping you maybe shed some light on an issue I have with this.
I am trying to use this on a page that the link should update the results on the page using AJAX.
Is it possible? Currently it is reloading the page time.
Also when I update any of the other options using AJAX they work fine but the select box reloads using the browser default styling.
Thanks in advance – awesome tutorial!
Are you filling the “options” with ajax …?
what am I doing wrong ?
first add id (selectBox) to element select
html
TODAS
javascript
function addOptions()
{
var xhr = new XMLHttpRequest();
var url =”myURL”;
xhr.open(“GET”, url);
xhr.send();
xhr.onreadystatechange = function()
{
if (xhr.readyState == 4 && xhr.status == 200)
{
var arr_DHCategoria = JSON.parse(xhr.responseText);
if(arr_DHCategoria.Categoria.length >= 1)
{
var lCategoria = “”;
var cat_id = “”;
var cat_descripcion = “”;
lCategoria += “TODAS”
for(i = 0 ; i < arr_DHCategoria.Categoria.length; i++)
{
cat_id=arr_DHCategoria.Categoria[i].IdCategoria;
cat_descripcion=arr_DHCategoria.Categoria[i].Descripcion;
lCategoria += "”+cat_descripcion+””;
}
console.log(lCategoria);
document.getElementById(“selectBox”).innerHTML = lCategoria;
}
}
}
}
the elements are added without problem, but they are not seen inside the menu …. apparently I have to call the function “_createSelectEl” but I have not been successful.
Can somebody help me ??
Hi, nice form!! Love it!! I have a question, is there a way to use without the first element (like “select your language”) instead of that, i only need the firt flag active.
Hi, My name is Cavin and I’m a junior web designer and a freelance graphic designer. I’m awfully new to designing websites so i use platforms like WordPress and other site building platforms, so I’d like to know how to add these awesome HTML styles into WordPress.
Thanks in advance:)
This should work if you want to use this to link to another page:
$(‘.cs-options li’).on(‘click’, function() {
var link = $(this).attr(“data-value”);
if (link !== ‘null’) {
window.location = link;
}
});
Anyone know how to add multiple dropdowns on a page? If I add more then one it breaks.
Hi there, i need a little help with the elastic element for country languages. How can i add a link inside the option values? I dont know much about javascript.
Thanks in Advance,
Diogo
Hi there,
My jQuery form validation doesn’t work for this select element as it sees the placeholder as being selected as one of the options. Where can I change the js to stop seeing the placeholder as a selected option.
Thanks so much!
What should I do to mark the currently selected option after loading the page?
what am I doing wrong ?
first add id (selectBox) to element select
html
TODAS
javascript
function addOptions()
{
var xhr = new XMLHttpRequest();
var url =”myURL”;
xhr.open(“GET”, url);
xhr.send();
xhr.onreadystatechange = function()
{
if (xhr.readyState == 4 && xhr.status == 200)
{
var arr_DHCategoria = JSON.parse(xhr.responseText);
if(arr_DHCategoria.Categoria.length >= 1)
{
var lCategoria = “”;
var cat_id = “”;
var cat_descripcion = “”;
lCategoria += “TODAS”
for(i = 0 ; i < arr_DHCategoria.Categoria.length; i++)
{
cat_id=arr_DHCategoria.Categoria[i].IdCategoria;
cat_descripcion=arr_DHCategoria.Categoria[i].Descripcion;
lCategoria += "”+cat_descripcion+””;
}
console.log(lCategoria);
document.getElementById(“selectBox”).innerHTML = lCategoria;
}
}
}
}
the elements are added without problem, but they are not seen inside the menu …. apparently I have to call the function “_createSelectEl” but I have not been successful.
Can somebody help me ??
Does anyone know why the orginal dropdown option does not change? Maybe the script only changes the placeholder …
I tried with the method of JAG:
added an ID attribute to line 138 in the selectFx.js
var opts_el = “+ options +”;
(function ($) {
$ (‘# Lista li’) click (function () {
var texto = $ (this) .data (‘value’);
$ (‘# Selectelement option’). Filter (function () {
return this.value == texto;
}). prop (“selected”, true) .change ();
});
}) (JQuery);
But I can not integrate the code, I get syntax errors 🙁 I’m not very good in js but I learn 🙂
If anyone can help me that would be great! : D
Thank you