이 튜토리얼에서는 덜 사용되는 HTML5 <datalist>
요소에 대해 깊이 있는 살펴보겠습니다. 이 요소를 사용하면 자바스크립트 없이 가볍고, 접근 가능하며, 브라우저 간 호환성을 지원하는 자동완성 폼 컨트롤을 구현할 수 있습니다.
<select>
는 어떤 문제가 있나요?
HTML5 <select>
컨트롤은 사용자가 적은 범위의 옵션 중에서 선택할 때 이상적입니다. 다음과 같은 경우에는 덜 실용적입니다:
- 많은 옵션이 있는 경우, 예를 들어 국가나 직함
- 사용자가 목록에 없는 자신의 옵션을 입력하고 싶은 경우
명백한 해결책은 자동완성 컨트롤입니다. 이를 사용하면 사용자가 몇 글자를 입력함으로써 더 빠른 선택을 위해 사용 가능한 옵션을 제한할 수 있습니다.
<select>
는 입력을 시작할 때 올바른 위치로 이동하지만, 이것이 항상 명확한 것은 아닙니다. 모든 기기에서 작동하지 않으며(터치스크린 등), 1초나 2초 내에 초기화됩니다.
개발자들은 종종 많은 자바스크립트 기반 솔루션 중 하나를 선택하지만, 맞춤형 자동완성 컨트롤이 항상 필요한 것은 아닙니다. HTML5 <datalist>
요소는 가볍고, 접근 가능하며, 자바스크립트에 의존하지 않습니다. 이 요소가 버그가 있거나 지원이 부족하다는 소문을 들어보셨을 수도 있지만, 2021년에는 그렇지 않습니다. 그러나 브라우저 간 일관성과 주의사항이 있습니다.
<datalist>
빠른 시작
200개가 넘는 선택지 중에서 국가를 선택하는 것은 자동완성 컨트롤의 이상적인 사용 사례입니다. HTML 페이지 내에서 모든 국가에 대한 자식 <option>
요소를 가진 <datalist>
를 정의하세요:
<datalist id="countrydata">
<option>Afghanistan</option>
<option>Åland Islands</option>
<option>Albania</option>
<option>Algeria</option>
<option>American Samoa</option>
<option>Andorra</option>
<option>Angola</option>
<option>Anguilla</option>
<option>Antarctica</option>
...etc...
</datalist>
그런 다음, 데이터 리스트의 id
를 모든 <input>
필드의 list
속성으로 참조할 수 있습니다:
<label for="country">country</label>
<input type="text"
list="countrydata"
id="country" name="country"
size="50"
autocomplete="off" />
혼란스럽게도, autocomplete="off"
를 설정하는 것이 가장 좋습니다. 이렇게 하면 사용자가 <datalist>
의 값을 보여주지만 브라우저에서 이전에 입력한 값은 보여주지 않습니다.
결과:
이것은 Microsoft Edge에서의 기본 렌더링입니다. 다른 애플리케이션들은 비슷한 기능을 구현하지만, 플랫폼과 브라우저에 따라 모양이 다릅니다.
<option>
옵션
<option>
의 텍스트 자식으로 라벨을 사용하는 것이 일반적입니다:
<datalist id="mylist">
<option>label one</option>
<option>label two</option>
<option>label three</option>
</datalist>
value
속성을 사용하면 동일한 결과를 얻을 수 있습니다:
<datalist id="mylist">
<option value="label one" />
<option value="label two" />
<option value="label three" />
</datalist>
참고: HTML5에서는 닫는 />
슬래시가 선택 사항이지만, 코딩 오류를 방지하는 데 도움이 될 수 있습니다.
다음과 같은 형식으로 선택한 라벨에 따라 값을 설정할 수도 있습니다.
옵션 1:
<datalist id="mylist">
<option value="1">label one</option>
<option value="2">label two</option>
<option value="3">label three</option>
</datalist>
옵션 2:
<datalist id="mylist">
<option value="1" label="label one" />
<option value="2" label="label two" />
<option value="3" label="label three" />
</datalist>
두 경우 모두, 유효한 옵션을 선택할 때 입력 필드가 1
, 2
또는 3
으로 설정되지만, 브라우저마다 UI가 다릅니다:
- 크롬은 값과 라벨이 모두 포함된 목록을 보여줍니다. 옵션을 선택하면 값만 남게 됩니다.
- 파이어폭스는 라벨만 포함된 목록을 보여주며, 옵션을 선택하면 값으로 변경됩니다.
- 엣지는 값만 표시합니다.
다음 CodePen 예제는 모든 변형을 보여줍니다:
SitePoint(@SitePoint)가 제작한
HTML5 <datalist> 자동완성 예제를 CodePen에서 보실 수 있습니다.
구현 방식은 진화할 것이지만, 현재로서는 사용자를 혼란스럽게 할 가능성이 높으므로 값과 라벨을 사용하지 않는 것이 좋습니다. (아래에서 대안에 대해 논의합니다.)
<datalist>
브라우저 지원 및 대체 방안
<datalist>
요소는 현대 브라우저와 인터넷 익스플로러 10 및 11에서 잘 지원됩니다:
여러 구현 노트가 있지만, 대부분의 사용에는 영향을 주지 않습니다. 최악의 경우는 필드가 표준 텍스트 입력으로 돌아가는 것입니다.
IE9 이하를 반드시 지원해야 하는 경우, <datalist>
가 실패할 때 표준 <select>
와 텍스트 입력을 결합하는 대체 패턴을 사용할 수 있습니다. 국가 예제를 적용하면:
<label for="country">country</label>
<datalist id="countrydata">
<select name="countryselect">
<option></option>
<option>Afghanistan</option>
<option>Åland Islands</option>
<option>Albania</option>
<option>Algeria</option>
<option>American Samoa</option>
<option>Andorra</option>
<option>Angola</option>
<option>Anguilla</option>
<option>Antarctica</option>
...etc...
</select>
<label for="country">or other</label>
</datalist>
<input type="text"
id="country" name="country"
size="50"
list="countrydata"
autocomplete="off" />
HTML5 <datalist> 자동완성 대체 방법은 SitePoint(@SitePoint)
가 CodePen에 게시했습니다.
현대 브라우저에서 <option>
요소는 <datalist>
의 일부가 되며, “기타” 레이블은 표시되지 않습니다. 위의 예시와 똑같이 보이지만, countryselect
폼 값은 빈 문자열로 설정됩니다.
IE9 이하에서는 매우 긴 <select>
와 텍스트 입력 필드 모두 활성화됩니다:
이 두 값 모두 구형 IE에서 입력할 수 있습니다. 애플리케이션은 다음 중 하나를 선택해야 합니다:
- 어느 것이 가장 유효한지 결정하거나,
- 다른 것이 변경될 때 하나를 재설정하는 작은 JavaScript 함수를 사용
<datalist>
를 비텍스트 컨트롤에 사용하기
크롬 기반 브라우저는 <datalist>
값을 다음에도 적용할 수 있습니다:
-
타입이
"date"
인 입력입니다. 사용자는YYYY-MM-DD
값으로 정의된 범위의 옵션 중에서 선택할 수 있지만, 지역 형식으로 표시됩니다. -
색상 유형의 입력을 위한
"color"
입니다. 사용자는 정의된 6자리 16진수 값의 색상 옵션 선택이 가능합니다(3자리 값은 작동하지 않음). -
유형이
"range"
인 입력입니다. 슬라이더에는 틱 마크가 표시되지만, 이는 입력할 수 있는 값을 제한하지 않습니다.
코드 펜에서 SitePoint(@SitePoint)가 작성한
HTML5 <datalist> on other input types를 확인하세요.
CodePen에서.
<datalist>
CSS 스타일링
<select>
박스를 스타일링하는 데 어려움을 겪었던 적이 있다면, … 그건 쉬웠어요!
<input>
은 일반적으로 스타일링할 수 있지만, 연결된 <datalist>
와 그 자식 <option>
요소들은 CSS로 스타일링할 수 없습니다. 목록 렌더링은 플랫폼과 브라우저에 의해 완전히 결정됩니다.
I hope this situation improves, but for now, a solution is proposed at MDN which:
- 기본 브라우저 동작을 재정의합니다.
<datalist>
를<div>
처럼 취급하여 CSS로 스타일링할 수 있게 합니다.- 자바스크립트로 모든 자동완성 기능을 복제합니다.
I’ve enhanced it further and the code is available on GitHub. To use it, load the script anywhere in your HTML page as an ES6 module. The jsDelivr CDN URL can be used:
<script src="https://cdn.jsdelivr.net/npm/datalist-css/dist/datalist-css.min.js"></script>
또는 번들러를 사용하고 있다면 npm
으로 설치할 수 있습니다:
npm install datalist-css
당신의 <datalist>
요소들은 <option>value</option>
형식을 사용해야 합니다. 예를 들면:
<datalist id="mylist">
<option>label one</option>
<option>label two</option>
<option>label three</option>
</datalist>
참고: <option value="value" />
는 사용할 수 없습니다. 스타일링이 불가능한 빈 요소로 이어지기 때문입니다!
그런 다음 CSS를 추가하여 일부 또는 전체 <datalist>
및 <option>
요소를 스타일링할 수 있습니다. 예를 들면:
datalist {
position: absolute;
max-height: 20em;
border: 0 none;
overflow-x: hidden;
overflow-y: auto;
}
datalist option {
font-size: 0.8em;
padding: 0.3em 1em;
background-color: #ccc;
cursor: pointer;
}
/* 활성 옵션 스타일링 */
datalist option:hover, datalist option:focus {
color: #fff;
background-color: #036;
outline: 0 none;
}
예시:
SitePoint(@SitePoint)가 만든
HTML5 <datalist> 자동완성 CSS 스타일링을 CodePen에서 확인할 수 있습니다.
스타일링은 작동하지만, 노력이 그만한 가치가 있을까요? 나는 그렇지 않다고 생각합니다…
- 브라우저의 표준 키보드, 마우스 및 터치 컨트롤을 접근성을 고려하여 재구현하는 것은 어렵습니다. MDN 예제는 키보드 이벤트를 지원하지 않으며, 개선하려고 노력했지만 어떤 기기에서는 문제가 발생할 것입니다.
- CSS 문제를 해결하기 위해 200줄의 JavaScript에 의존하고 있습니다. 이는 1.5kB로 최소화되지만, 같은 페이지에서 많은 긴
<datalist>
요소를 요구하면 성능 문제를 야기할 수 있습니다. - JavaScript가 필수적인 경우, 더 예쁘고 일관성 있는, 경험 많은 JavaScript 컴포넌트를 사용하는 것이 바람직할까요?
JavaScript가 실패할 경우 스타일링이 없는 표준 HTML5 <datalist>
로 대체되지만, 이는 사소한 이점일 뿐입니다.
Ajax로 강화된 <datalist>
를 만들 수 있습니다.
디자이너가 브라우저 스타일 차이를 받아들일 수 있다고 가정하면, JavaScript를 사용하여 표준 <datalist>
기능을 강화할 수 있습니다. 예를 들면:
<datalist>
에서 알려진 값만을 허용하는 선택적 유효성 검사를 구현합니다.- Ajax 호출에 의해 검색 API로부터 반환된 데이터에서
<option>
요소를 설정합니다. - 옵션을 선택할 때 다른 필드 값을 설정합니다. 예를 들어, “미국”을 선택하면 숨겨진 입력에 “US”가 설정됩니다.
코드는 주로 <option>
요소를 재정의해야 하며, 여러 가지 코딩 고려 사항이 있습니다:
- Ajax API 요청은 최소한의 문자 수가 입력될 때만 발생해야 합니다.
- 타이핑 이벤트는 디바운싱되어야 합니다. 즉, 사용자가 최소 0.5초 이상 타이핑을 멈추었을 때만 Ajax 호출이 트리거됩니다.
- 쿼리 결과는 캐싱되어야 하므로 동일한 호출을 반복하거나 구문 분석할 필요가 없습니다.
- 불필요한 쿼리는 피해야 합니다. 예를 들어, “un”을 입력하면 12개국이 반환됩니다. “unit”이나 “united”에 대한 추가 Ajax 호출은 필요하지 않습니다. 왜냐하면 모든 결과 옵션이 원래 12개의 결과에 포함되어 있기 때문입니다.
I’ve created a standard Web Component for this, and the code is available on GitHub. The CodePen example below allows you to select a valid country after entering at least two characters. A music artist autocomplete then returns artists who originated in that country with names matching the search string:
SitePoint(@SitePoint)가 만든
HTML5 <datalist> with Ajax autocomplete를 CodePen에서 볼 수 있습니다.
- 국가 조회 API는 restcountries.eu에서 제공합니다.
- 음악 아티스트 조회 API는 musicbrainz.org에서 제공합니다.
이를 자신의 애플리케이션에서 사용하려면 ES6 모듈로 HTML 페이지 어디에서나 스크립트를 로드하십시오. jsDelivr CDN URL을 사용할 수 있습니다:
<script src="https://cdn.jsdelivr.net/npm/datalist-ajax/dist/datalist-ajax.min.js"></script>
또는 번들러를 사용하는 경우 npm
으로 설치할 수 있습니다:
npm install datalist-ajax
데이터 입력 필드로 사용할 <input>
자식을 가진 <auto-complete>
요소를 생성하십시오. 예를 들어, 국가 검색은 다음을 사용합니다:
<label for="country">country lookup:</label>
<auto-complete
api="https://restcountries.eu/rest/v2/name/${country}?fields=name;alpha2Code;region"
resultname="name"
querymin="2"
optionmax="50"
valid="please select a valid country"
>
<input type="text" id="country" name="country" size="50" required />
</auto-complete>
<auto-complete>
요소 속성:
attribute | description |
---|---|
api |
the REST API URL (required) |
resultdata |
the name of the property containing a result array of objects in the returned API JSON (not required if only results are returned) |
resultname |
the name of the property in each result object which matches the search input and is used for datalist <option> elements (required) |
querymin |
the minimum number of characters to enter before a search is triggered (default: 1) |
inputdelay |
the minimum time to wait in milliseconds between keypresses before a search occurs (default debounce: 300) |
optionmax |
the maximum number of autocomplete options to show (default: 20) |
valid |
if set, this error message is shown when an invalid value is selected |
REST URL은 적어도 하나의 ${id}
식별자를 포함해야 합니다. 이는 <input>
에 설정된 id
값으로 대체됩니다. 위의 예시에서 ${country}
는 api
URL에서 자식 <input>
의 값을 참조하며, 이 입력은 id
가 "country"
입니다. URL은 일반적으로 자식 입력을 사용하지만, 페이지의 다른 필드를 참조할 수도 있습니다.
restcountries.eu API는 국가 데이터를 포함하는 단일 객체 또는 객체 배열을 반환합니다. 예를 들어:
[
{
"name": "Cyprus",
"alpha2Code": "CY",
"region": "Europe"
},
{
"name": "Sao Tome and Principe",
"alpha2Code": "ST",
"region": "Africa"
},
{
"name": "Andorra",
"alpha2Code": "AD",
"region": "Europe"
}
]
resultdata
속성은 설정할 필요가 없습니다. 이는 유일하게 반환되는 데이터이며(래퍼 객체가 없음) resultname
속성은 "name"
로 설정되어야 합니다. 이 속성은 datalist <option>
요소를 채우는 데 사용됩니다.
다른 필드는 옵션이 선택될 때 자동으로 채워질 수 있습니다. 다음 입력은 "alpha2Code"
및 "region"
속성 데이터를 받습니다. 이는 data-autofill
속성이 설정되어 있기 때문입니다:
<input data-autofill="alpha2Code" type="text" id="countrycode" name="countrycode" readonly />
<input data-autofill="region" type="text" id="region" name="region" readonly />
datalist-ajax
가 어떻게 작동하는지
마법을 유지하고 싶다면 이 섹션을 건너뛰어도 좋습니다! 230줄의 코드를 읽고 싶지 않으신가요?
코드는 처음에 <auto-complete>
내부에 <datalist>
를 새로 생성하고, list
속성을 사용하여 자식 <input>
에 연결합니다. input
이벤트 핸들러는 <input>
을 감시하여 최소한의 문자가 입력되고 사용자가 계속해서 입력하지 않을 때 runQuery()
함수를 호출합니다.
runQuery()
는 폼의 데이터로 API URL을 구성하고 Fetch API를 사용하여 Ajax 호출을 수행합니다. 반환된 JSON을 파싱한 후, <option>
요소를 포함하는 재사용 가능한 DOM 조각을 구축하고 캐시에 저장합니다.
A datalistUpdate()
function is called, which updates the <datalist>
with the appropriate cached DOM fragment. Further calls to runQuery()
avoid Ajax calls if a query has already been cached or a previous query can be used.
A change
event handler also monitors the <input>
, which is triggered when focus is moved from the field and the value has been modified. The function checks that the value matches a known option and, if necessary, uses the Constraint Validation API to show the error message provided in the valid
attribute.
유효한 옵션이 선택되면 변경 핸들러 함수는 일치하는 data-autofill
속성을 가진 모든 필드를 채웁니다. 자동 입력 필드에 대한 참조는 나중에 입력된 옵션이 유효하지 않을 경우 재설정할 수 있도록 유지됩니다.
그림자 DOM은 사용되지 않습니다. 이를 통해 자동 완성 <input>
(및 <datalist>
) 요소는 CSS로 스타일링할 수 있고 필요한 경우 다른 스크립트에서 액세스할 수 있습니다.
Dunkin’ <datalist>
HTML5 <datalist>
는 한계가 있지만 간단한 프레임워크와 무관한 자동 완성 필드가 필요한 경우에 이상적입니다. CSS 지원의 부족은 아쉽지만, 브라우저 벤더들이 결국 그 실수를 해결할 수도 있습니다.
이 튜토리얼에 표시된 코드 및 예제 중 하나라도 자신의 프로젝트에 채택할 수 있습니다.
FAQs About Lightweight Autocomplete Controls with the HTML5 Datalist
HTML5 datalist 요소란 무엇이며 어떻게 작동하나요?
HTML5 datalist 요소는 입력 요소에 대한 미리 정의된 옵션 목록입니다. 폼 요소에 “자동완성” 기능을 제공합니다. datalist 요소는 id 속성을 사용하여 특정 입력 요소와 연결됩니다. 입력 요소는 list 속성을 사용하여 datalist를 식별합니다. datalist 내에서는 입력 필드에 대한 사용 가능한 옵션을 나타내는 option 요소를 정의할 수 있습니다.
HTML5 datalist를 어떻게 자동완성으로 사용할 수 있나요?
HTML5 datalist를 자동완성으로 사용하려면 datalist를 입력 필드와 연결해야 합니다. 이는 입력 필드에 list 속성을 추가하고 그 값을 datalist의 id로 설정하여 수행됩니다. 그런 다음 브라우저는 사용자의 입력과 datalist에 정의된 옵션을 기반으로 자동완성 옵션을 제议합니다.
HTML5 datalist 요소를 모든 브라우저에서 사용할 수 있나요?
HTML5 datalist 요소는 Chrome, Firefox, Safari, Edge를 포함한 대부분의 최신 브라우저에서 지원됩니다. 하지만 Internet Explorer 9 이전 버전에서는 지원되지 않습니다. 현재 브라우저 호환성을 Can I Use과 같은 웹사이트에서 확인할 수 있습니다.
HTML5 datalist 옵션을 어떻게 스타일링 할 수 있나요?
불행히도 HTML5 datalist 요소의 스타일링 옵션은 매우 제한적입니다. 드롭다운 목록의 모양은 브라우저에 의해 제어되며 CSS로 쉽게 사용자 정의할 수 없습니다. 하지만 datalist와 연결된 입력 필드를 스타일링할 수는 있습니다.
단일 입력 필드에 여러 개의 datalists를 사용할 수 있나요?
아니요, 하나의 입력 필드에 여러 개의 datalist를 연결할 수는 없습니다. 입력 필드의 list 속성은 하나의 id만 가질 수 있으며, 이는 하나의 datalist에 해당합니다. 여러 세트의 옵션을 제공해야 하는 경우 JavaScript를 사용하여 사용자 입력에 따라 옵션을 동적으로 변경해야 할 수도 있습니다.
HTML5 datalist를 다른 입력 유형과 함께 사용할 수 있습니까?
예, HTML5 datalist는 텍스트, 검색, URL, 전화번호, 이메일, 날짜, 월, 주, 시간, datetime-local, 숫자, 범위, 색상과 같은 다양한 입력 유형과 함께 사용할 수 있습니다. 그러나 일부 입력 유형(예: 범위 또는 색상)과 함께 자동 완성 기능이 예상대로 작동하지 않을 수 있습니다.
HTML5 datalist를 select 요소와 함께 사용할 수 있습니까?
아니요, HTML5 datalist는 select 요소와 함께 사용할 수 없습니다. datalist는 입력 필드에 대한 자동 완성 제안을 제공하도록 설계되었으며, select 요소는 옵션 목록을 제공합니다. 드롭다운 목록이 필요한 경우 select 요소를 사용해야 합니다.
HTML5 datalist와 JavaScript를 함께 사용할 수 있습니까?
예, JavaScript를 사용하여 옵션을 동적으로 추가, 제거 또는 변경할 수 있습니다. 그러나 datalist의 옵션에는 onchange 또는 onclick과 같은 이벤트가 지원되지 않으므로 관련 입력 필드에 이벤트 리스너를 추가해야 합니다.
HTML5 datalist를 검색 필드에 사용할 수 있습니까?
예, HTML5 datalist는 검색 필드에 적합한 선택입니다. 사용자 입력에 따라 자동 완성 제안을 제공할 수 있으며, 이는 사용자 경험을 향상시킬 수 있습니다. 그러나 가능한 검색어로 datalist를 수동으로 채워야 합니다.
HTML5 datalist를 textarea와 함께 사용할 수 있나요?
아니요, HTML5 datalist는 textarea와 함께 사용할 수 없습니다. datalist는 입력 필드에 대한 자동완성 제안을 제공하도록 설계되었으며, textarea에는 사용할 수 없습니다. textarea에 자동완성 기능이 필요한 경우 JavaScript 라이브러리를 사용하거나 직접 솔루션을 구축해야 할 수도 있습니다.
Source:
https://www.sitepoint.com/html5-datalist-autocomplete/