4 Steps Simple Custom Dropdown Arrow With Pure CSS

Welcome to a tutorial on how to create a custom dropdown arrow using pure CSS and HTML. Yes, we can pretty much do any customization with modern HTML and CSS. But strangely, there is no straightforward way to customize a dropdown arrow in pure CSS.

There are no direct CSS properties to change the dropdown arrow of <select>. To customize the dropdown arrow:

  1. Wrap the select box – <div class="cselect"><select><option>Demo</option></select></div>
  2. Hide the default arrow – .cselect select { apperance: none }
  3. Create a custom arrow using HTML symbol – .cselect::after { content: "\25b6" }
  4. Position the custom arrow – .cselect { position: relative } .cselect::after { position: absolute; top: 0; right: 0 }

That covers the basic mechanics, but let us walk through a detailed example in this guide – Read on!

ⓘ I have included a zip file with all the source code at the start of this tutorial, so you don’t have to copy-paste everything… Or if you just want to dive straight in.

 

QUICK SLIDES

 

 

TABLE OF CONTENTS

Download & Demo Custom Dropdown Useful Bits & Links
Tutorial Video The End

 

DOWNLOAD & DEMO

Firstly, here is the download link to the example code as promised.

 

QUICK NOTES

If you spot a bug, feel free to comment below. I try to answer short questions too, but it is one person versus the entire world… If you need answers urgently, please check out my list of websites to get help with programming.

 

EXAMPLE CODE DOWNLOAD

Click here to download the source code, I have released it under the MIT license, so feel free to build on top of it or use it in your own project.

 

 

THE DEMO

 

 

PURE CSS CUSTOM DROPDOWN

All right, let us now dive into the example of how to customize a dropdown using pure CSS only.

 

PART 1) WRAP THE SELECT BOX

cselect.html
<div class="cselect"><select>
  <option>Good Boy Doge</option>
  <option>Evil Cate</option>
  <option>Sneezing Panda</option>
  <option>Confession Bear</option>
  <option>Fabulous Llama</option>
</select></div>

No sweat. All we need in the HTML is to wrap a normal <select> within a <div> wrapper.

 

 

PART 2) CUSTOM HTML SYMBOL DROPDOWN ARROW 

cselect.css
/* (A) BASIC CUSTOM DROPDOWN MECHANICS */
/* (A1) HIDE DEFAULT ARROW */
.cselect select { appearance: none; }

/* (A2) DEFINE OUR OWN CUSTOM ARROW */
.cselect::after { content: "\25b6"; }

/* (A3) POSITION CUSTOM ARROW */
.cselect { position: relative; }
.cselect::after {
  position: absolute;
  top: 0; right: 0;
}

Now, here comes the irritating part – CSS does not have a direct property to set the dropdown arrow, we have to do it through “alternative means”.

  • (A1) Hide the default dropdown arrow using appearance: none.
  • (A2) Attach an HTML symbol to .cselect::after to build our own custom arrow.
  • (A3) Position the custom dropdown arrow.

 

PART 3) CUSTOM DROPDOWN BOX DIMENSIONS

cselect.css
/* (B) DIMENSTIONS */
/* (B1) MAKE <SELECT> FILL THE WRAPPER */
.cselect select { width: 100%; }
.cselect { max-width: 400px; } /* OPTIONAL */

/* (B2) ALL SAME HEIGHT */
.cselect, .cselect::after, .cselect select {
  box-sizing: border-box;
  height: 40px;
}

/* (B3) A SQUARE CUSTOM ARROW BOX */
/* ADD BORDER-RADIUS: 50% TO TURN IT CIRCLE */
.cselect::after { width: 40px; }

Next, we fix a funky-looking custom dropdown box by setting the dimensions.

  • (B1) Make the <select> fill up the <div> wrapper.
  • (B2) “Standardize” the height of all the <div> <select> <div>::after.
  • (B3) Finally, turn the dropdown arrow into a square (same width and height).

 

 

PART 4) COSMETICS

cselect.css
/* (C) COSMETICS */
/* (C1) OVERRIDE DEFAULT SELECT BOX STYLES */
.cselect select {
  border: 1px solid #ccc;
  background: #fafafa;
  padding: 5px 10px;
}

/* (C2) DROPDOWN ARROW BOX */
.cselect::after {
  /* COLORS */
  color: #fff;
  background: #cfdcff;
  /* CENTER ARROW IN BOX */
  display: flex;
  align-items: center;
  justify-content: center;
}

/* (C3) FUNKY ANIMATIONS */
.cselect::after { transition: all 0.3s; }
.cselect:hover::after {
  transform: rotate(90deg);
  background: #274396;
  color: #fff;
}

/* (C4) REMOVE DEFAULT HIGHLIGHTS */
.cselect select:active,
.cselect select:focus,
.cselect select:hover {
  outline: none;
}

No need to panic, this final part is just the cosmetics – Font, color, borders, etc… Feel free to customize this to your own liking.

 

 

EXTRA) ARROW ON THE LEFT SIDE

cselect.css
/* (D) ARROW ON LEFT SIDE */
.left.cselect select { padding-left: 50px; }
.left.cselect::after {
  right: auto;
  left: 0;
  border-radius: 50%;
}

Easy. Just set .cselect::after to left: 0.

 

USEFUL BITS & LINKS

That’s all for the tutorial, and here is a small section on some extras and links that may be useful to you.

 

A SMALL LIMITATION

Just a small note – The custom dropdown arrow is purely “cosmetic”. Clicking on it will not trigger focus on the select list.

 

CAN WE CUSTOMIZE THE DROPDOWN ITEMS!?

No, not directly. Every browser renders the <select> differently – On a desktop, the selectable list will be below the box. But on mobile, it will probably become a popup selection list instead. The only way to do it is to make your own “entirely customized selectable list made from scratch”.

 

TUTORIAL VIDEO

 

INFOGRAPHIC CHEAT SHEET

Custom CSS Dropdown (click to enlarge)

 

THE END

Thank you for reading, and we have come to the end of this guide. I hope that it has helped you with your project, and if you want to share anything with this guide, please feel free to comment below. Good luck and happy coding!

3 thoughts on “4 Steps Simple Custom Dropdown Arrow With Pure CSS”

  1. Hi
    Thank you for this quick and easy method. It helped me and one thing that I added was the z-index so clicking the arrow “seem” to activate the dropdown:
    simply added :
    .cselect select { z-index: 2; }
    .cselect::after { z-index: 1; }
    Thanks again!

    1. No, there’s no CSS to directly control it. Also on mobile browsers, this will probably be rendered differently as a scrollable popup list.

Leave a Comment

Your email address will not be published. Required fields are marked *