DEV Community

Cover image for šŸ”„šŸ”„ how to style select input in css
Modern Web
Modern Web

Posted on

šŸ”„šŸ”„ how to style select input in css

Hello, glad you are here. I am kunaal and today we will see how to make a custom select input, a custom options input. You can see demo below.

Demo

Video Tutorial -

If you find this article hard or for better explanation. You can watch video tutorial.

If you like the video tutorial. Please consider subscribing my youtube channel.

Let's code

In index.html inside body tag write this

<div class="container">
    <button class="select" name="select" value="options">options</button>
    <div class="options">
        <p class="item active">option 1</p>
        <p class="item">option 2</p>
        <p class="item">option 3</p>
        <p class="item">option 4</p>
    </div>
</div>
Enter fullscreen mode Exit fullscreen mode

And add some CSS

*{
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

*:focus{
    outline: none;
}

body{
    width: 100%;
    height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
    background: #ff6767;
    font-family: 'roboto', sans-serif;
}

.container{
    position: relative;
}

.select{
    position: relative;
    width: 200px;
    height: 40px;
    border-radius: 10px;
    border: none;
    text-transform: capitalize;
    color: #fff;
    background: #292929;
    text-align: left;
    padding: 0 15px;
    font-size: 16px;
    cursor: pointer;
}

.select::after{
    content: '';
    position: absolute;
    right: 20px;
    top: 50%;
    transform: translateY(-50%) rotate(45deg);
    width: 6px;
    height: 6px;
    border-right: 2px solid #fff;
    border-bottom: 2px solid #fff;
}

.select:hover{
    background: #222222;
}

.select.active{
    background: #222222;
    border-bottom-left-radius: 0;
    border-bottom-right-radius: 0;
}

.options{
    position: absolute;
    top: 40px;
    left: 0;
    width: 100%;
    height: fit-content;
    background: rgba(0, 0, 0, 0.5);
    border-bottom-left-radius: 10px;
    border-bottom-right-radius: 10px;
    overflow: hidden;
    display: none;
}

.options.active{
    display: block;
}

.options .item{
    color: #fff;
    text-transform: capitalize;
    width: 100%;
    height: 30px;
    padding: 0 15px;
    line-height: 30px;
    cursor: pointer;
}

.options .item.active{
    background: #292929;
}
Enter fullscreen mode Exit fullscreen mode

we also need to write JS. So let's write some

const select = document.querySelector('.select');
const optionBox = document.querySelector('.options');
const options = [...document.querySelectorAll('.options .item')];

let activeOption = 0; // default should be 0

window.onclick = (e) => {
    if(!e.target.className.includes('select')){
        select.classList.remove('active');
        optionBox.classList.remove('active');
    } else{
        select.classList.toggle('active');
        optionBox.classList.toggle('active');
    }
}

options.forEach((item, i) => {
    item.onmousemove = () => {
        hoverOptions(i);
    }
})

const hoverOptions = (i) => {
    options[activeOption].classList.remove('active');
    options[i].classList.add('active');
    activeOption = i;
    setValue();
}

window.onkeydown = (e) => {
    if(select.className.includes('active')){
        e.preventDefault();
        if(e.key === 'ArrowDown' && activeOption < options.length - 1){
            hoverOptions(activeOption + 1);
        } else if(e.key === 'ArrowUp' && activeOption > 0){
            hoverOptions(activeOption - 1);
        } else if(e.key === 'Enter'){
            select.classList.remove('active');
            optionBox.classList.remove('active');
        }
    }
}

const setValue = () => {
    select.innerHTML = select.value = options[activeOption].innerHTML;
}

setValue();
Enter fullscreen mode Exit fullscreen mode

I hope you understood everything. If you have any doubt or you find any mistake that I made or you have any suggestion feel free to ask me in comment.

If you are interested in programming and want to know how I a 15yr old teen do coding make these design. You can follow me on my Instagram. I am also planning to post my game development stuff on Instagram.

My youtube Channel, Instagram

Top comments (7)

Collapse
 
jameslivesey profile image
James Livesey

Looks really nice, but unfortunately this isn't accessible at all to blind/visually impaired users who use screen readers, or users with reduced motor ability who use either the keyboard only or switches. Would love to see an accessible version! Until then, I'm gonna stick to the default semantic <select>...

Collapse
 
themodernweb profile image
Modern Web • Edited

Ah ! My bad I totally forgot this scenario but no worry you can use this select in your forms you just have to do some changes.

Step 1-. Inside CSS file remove this line

*:focus{
    outline: none;
}
Enter fullscreen mode Exit fullscreen mode

Step 2- Then in JS add focus and blur event to select button

select.onfocus = () => {
    select.classList.add('focus');
}

select.onblur = () => {
    select.classList.remove('focus');
}
Enter fullscreen mode Exit fullscreen mode

Step 3- And last modify window.keypress function little bit.

window.onkeydown = (e) => {
    if(select.className.includes('active') || select.className.includes('focus')){
        if(e.key === 'ArrowDown' && activeOption < options.length - 1){
            e.preventDefault();
            hoverOptions(activeOption + 1);
        } else if(e.key === 'ArrowUp' && activeOption > 0){
            e.preventDefault();
            hoverOptions(activeOption - 1);
        } else if(e.key === 'Enter'){
            e.preventDefault();
            select.classList.remove('active');
            optionsBox.classList.remove('active');
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

And now you can easily access this select button from tab and change options with keys.

I hope you find this helpful.
Thank you.

Collapse
 
themodernweb profile image
Modern Web

Ohh! My bad I totally forgot this scenario but no worry you can use this select in your forms you just have to do some changes.

  1. Inside CSS file remove this line
*:focus{
    outline: none;
}
Enter fullscreen mode Exit fullscreen mode
  1. Then in JS add focus and blur event to select button
select.onfocus = () => {
    select.classList.add('focus');
}

select.onblur = () => {
    select.classList.remove('focus');
}
Enter fullscreen mode Exit fullscreen mode
  1. And last modify window.keypress function little bit.
window.onkeydown = (e) => {
    if(select.className.includes('active') || select.className.includes('focus')){
        if(e.key === 'ArrowDown' && activeOption < options.length - 1){
            e.preventDefault();
            hoverOptions(activeOption + 1);
        } else if(e.key === 'ArrowUp' && activeOption > 0){
            e.preventDefault();
            hoverOptions(activeOption - 1);
        } else if(e.key === 'Enter'){
            e.preventDefault();
            select.classList.remove('active');
            optionsBox.classList.remove('active');
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

And now you can easily access this select button from tab and change options with keys.

I hope you find this helpful.
Thank you.

Collapse
 
sfritsch09 profile image
Sebastian Fritsch

Thanks so much for that and I managed to create a React version of yours :)

export default function Selector({ label, value, onChange, options }) {
    const selectRef = useRef();
    const optionsRef = useRef();
    const [hover, setHover] = useState('');

    const handleOptions = (e) => {
        if (!e.target.className.includes('select')) {
            selectRef.current.classList.remove('active');
            optionsRef.current.classList.remove('active');
        } else {
            selectRef.current.classList.toggle('active');
            optionsRef.current.classList.toggle('active');
        }
    };
    return (
        <SelectWrapper>
            <label>{label}</label>
            <button ref={selectRef} className="select" onClick={handleOptions}>
                {value}
                <div ref={optionsRef} className="options">
                    {options.map((option, index) => (
                        <p
                            key={index}
                            onClick={onChange}
                            className={hover === option.value || value === option.value ? 'item active' : 'item'}
                            value={option.value}
                            onMouseOver={() => setHover(option.value)}
                        >
                            {option.label}
                        </p>
                    ))}
                </div>
            </button>
        </SelectWrapper>
    );
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
guscarpim profile image
Gustavo Scarpim

haha very nice!

Collapse
 
mafee6 profile image
Mafee7

Chrome should add ::-webkit-options-dropdown
L

Collapse
 
hosseinmobarakian profile image
Hossein Mobarakian

ty for this tutorial