본문 바로가기
JavaScript

[javascript] classList를 사용한 커스텀 select 메뉴 만들기

by teamnova 2023. 1. 10.
728x90

안녕하세요. 오늘은 classList를 select 메뉴를 커스텀해서 아래와 같이 만들어보겠습니다. 

 

커스텀 메뉴 완성본

우선 만들고자 하는 커스텀 내용은

1.option들을 클릭시에 볼 수있도록 하게 만들고

2. option 선택 시 선택된 내용이 select에 적용되고(1,2 classList 사용)

3.select 메뉴를 만드는데 내용이 많아 option이 한없이 길어지는 경우, 검색을 통해 찾을 수 있게 만든다.

입니다. 오늘은 이 중 1,2번까지 진행해보겠습니다.

 

우선 classList에 대해 알아봅시다. classList의 add,remove,replace,toggle을 통해 클래스 값을 수정할 수 있습니다. 사용예제는 아래에 첨부하였으니 자세한 내용은 아래 링크를 통해 참고바랍니다.

https://developer.mozilla.org/en-US/docs/Web/API/Element/classList

 

Element.classList - Web APIs | MDN

The Element.classList is a read-only property that returns a live DOMTokenList collection of the class attributes of the element. This can then be used to manipulate the class list.

developer.mozilla.org

//출처 https://developer.mozilla.org/en-US/docs/Web/API/Element/classList

const div = document.createElement("div");//div태그 생성.
div.className = "foo";
//생성된 div 태그에 clasName 부여.
// our starting state: <div class="foo"></div>

div.classList.remove("foo");//div태그의 클래스"foo"삭제
div.classList.add("anotherclass");
//div태그에 새로운 클래스 추가.
// <div class="anotherclass"></div>

div.classList.add("foo", "bar", "baz");
div.classList.remove("foo", "bar", "baz");
//여러개의 태그명을 추가 또는 삭제할 수 있음.

// toggle을 사용하면 클래스명 추가삭제를 on off처럼 적용할 수 있다.
div.classList.toggle("visible");

// add/remove visible, depending on test conditional, i less than 10
//횟수를 지정할 수 있음.
div.classList.toggle("visible", i < 10);

//contains를 사용해 특정 클래스명이 있는지 확인할 수 있음.
console.log(div.classList.contains("foo"));

// add or remove multiple classes using spread syntax
// spread syntax(전개구문)을 사용해서 배열형태로 클래스명을 추가 또는 삭제할 수 있음.
const cls = ["foo", "bar"];
div.classList.add(...cls);
div.classList.remove(...cls);

//특정 클래스명을 지정하는 클래스명으로 변경. foo => bar
div.classList.replace("foo", "bar");

 

 

그럼이제 classList를 사용하여 위 gif와 같이 커스텀 select 메뉴를 만들어보겠습니다. 

 

custom_menu.html 

<div class="wrapper">
  <div class="select">
    <span>나라를 선택해주세요</span>
    <span class="material-icons">expand_more</span>
  </div><!--select-->
  <div class="content">
    <div class="search-box">
      <span class="material-icons">search</span>     
      <input class="filter" type="text" placeholder="검색">
    </div><!--search box-->
    <ul class="options">
    </ul>
  </div><!--content-->
</div><!--wrapper-->
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">

custom_menu.css

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

.wrapper{
  width: 360px;
  margin:20px auto 0;
}
.select, .options li{
  display:flex;
  cursor:pointer;
  align-items:center;
}
.select{
  height:60px;
  padding:0 20px;
  background:#4285f4;
  border-radius:10px;
  color:#ffffff;
  justify-content:space-between;
}
.content{
  display:none;/*원래 안보이도록 설정*/
  background:#ffffff;
  margin-top:5px;
  padding:15px;
  border-radius:10px;
}

.active .content {/*wrapper에 active클래스가 추가되면 보이도록하기*/
  display:block;
}

.content .search-box{
  position: relative;
}
.search-box .material-icons{
  left:15px;
  line-height:53px;
  position: absolute;
}
.search-box input{
  height:53px;
  width:100%;
  outline:none;
  font-size:17px;
  padding:0 10px 0 43px;
  border: 1px solid #aabb;
  border-radius:10px;
}
.content .options{
  margin-top:10px;
  max-height:250px;
  overflow-y:auto;
}
.options::-webkit-scrollbar-track{
  backgound:#f1f1f1;
  border-radius:25px;
}

.options::-webkit-scrollbar-thumb{
  backgound:#ccc;
  border-radius:25px;
}

.options li{
  height:50px;
  padding:0 13px;
  border-radius:7px;
}
.options li:hover{
   background:#f2f2f2;
}

custom_menu.js

const wrapper = document.querySelector('.wrapper');//전체 frame
const select = document.querySelector('.select');//선택영역

let countries = 
["가나","가봉","감비아","과테말라","그레나다","그리스","기니","네덜란드","대한민국"];
//위 countries를 li에 세팅

select.addEventListener('click',function(){//선택영역 클릭시
  wrapper.classList.toggle('active');
  //classList api로 클래스명 추가/삭제 반복.
  //css클래스 설정을 통해 클래스 추가,삭제될 때마다 보이고 안보이고가 결정됨.
});

addLi();

function addLi(){ //ul내부에 countries 배열에 있는 모든 국가들 추가하기.
  countries.forEach(country=> {
    let li = `<li onclick="changeClickedName(this)">${country}</li>`;
    options.insertAdjacentHTML("beforeend",li);
  })
}

완성되면 아래와 같이 클릭시 option들을 보여주는 것을 확인할 수 있습니다.

 

 

자세한 내용은 아래 링크 추가적으로 참고 바랍니다.

https://developer.mozilla.org/ko/docs/Web/API/Element/insertAdjacentHTML

 

Element.insertAdjacentHTML() - Web API | MDN

insertAdjacentHTML() 메서드는 HTML or XML 같은 특정 텍스트를 파싱하고, 특정 위치에 DOM tree 안에 원하는 node들을 추가 한다. 이미 사용중인 element 는 다시 파싱하지 않는다. 그러므로 element 안에 존재하

developer.mozilla.org

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach

 

Array.prototype.forEach() - JavaScript | MDN

forEach() 메서드는 주어진 함수를 배열 요소 각각에 대해 실행합니다.

developer.mozilla.org