Inspiration for Custom Select Elements

Some inspiration for styling a custom version of the select element. There are many possibilities and today we are exploring some ideas of how to let the user select a choice in style.

From our sponsor: Elementor, a design oriented WordPress website builder for pros

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.

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>

… 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">
			<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>
	<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>

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?#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!

Tagged with:

Mary Lou

ML is a freelance web designer and developer with a passion for interaction design. She studied Cognitive Science and Computational Logic and has a weakness for the smell of freshly ground peppercorns.

Stay up to date with the latest web design and development news and relevant updates from Codrops.

CSS Reference

Learn about all important CSS properties from the basics with our extensive and easy-to-read CSS Reference.

It doesn't matter if you are a beginner or intermediate, start learning CSS now.

Feedback 109

Comments are closed.
  1. 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.

  2. 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,

    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):?>
      <?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

  3. 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();

  4. Hello, amazing solution, im try to customize elastic, but how can add the icon at active element? anyone can help me? thx

  5. Hi Mary Lou,

    How can i fill the selectFX from ajax? Or how can i destroy the selectFX and create it again?


    • did you find the answer?

      first add id (selectBox) to element select




      function addOptions()
      var xhr = new XMLHttpRequest();
      var url =”myURL”;“GET”, url);
      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++)
      lCategoria += "”+cat_descripcion+””;
      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 ??

  6. 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.

  7. 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:
    /* Options */
    .cs-select .cs-options {
    position: absolute;
    overflow: hidden;
    width: 100%;
    background: #fff;
    visibility: hidden;

    .cs-select.cs-active .cs-options {
    visibility:visible ;

    /* 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.

  8. 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!

  9. 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?

  10. Love this but really difficult to use with angular on select elements. ng-options or even ng-repeat breaks it…

  11. 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);
    $(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


  12. 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;

  13. 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

  14. 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!


  15. Love these selects! When using the Box select I cannot get the list to scroll and show all the options. Please help!

  16. Use this code

    Apply SelectFX

    (function () {
    []‘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

  17. 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