HOWTO · HTML
HTML 버튼을 링크처럼 작동하게 만드는 방법
HTML에서 버튼 모양의 앵커, JavaScript 버튼, 폼 제출 컨트롤을 언제 사용하는지 알아봅니다.
이 페이지의 내용
HTML 컨트롤로 URL을 여는 방법은 원하는 결과에 따라 달라집니다. 페이지를 이동하려면 href가 있는 <a>를 사용하고 CSS로 버튼처럼 보이게 만드세요. 동작을 실행하려면 <button>, 폼 데이터를 전송하려면 제출 컨트롤을 사용합니다. <button>이나 <input>을 <a> 안에 넣지 마세요. 모두 대화형 요소이므로 의미와 키보드 동작이 충돌합니다.
결과에 따라 앵커와 버튼을 선택하기
주소를 바꾸거나 문서와 파일을 열고 다른 페이지로 이동하는 경우에는 앵커가 알맞습니다. href에 실제 목적지가 있으면 사용자가 새 탭으로 열거나 주소를 복사하고 북마크하거나 키보드로 접근할 수 있습니다.
현재 페이지를 바꾸거나 대화 상자와 패널을 열거나 스크립트를 실행하는 경우에는 <button type="button">을 사용합니다. 직사각형 모양이라고 해서 button이 링크가 되는 것은 아닙니다. 요소의 역할은 실제 동작과 일치해야 합니다.
탐색을 위해 <a>를 버튼처럼 꾸미기
단순히 페이지를 이동하는 컨트롤이라면 이 방법을 권장합니다. 목적지는 href에 두고 의미 있는 링크 텍스트와 눈에 보이는 포커스 스타일을 제공하세요. /docs/를 실제 주소로 바꾸면 됩니다.
<a class="button-link" href="/docs/">Open the documentation</a>
.button-link {
display: inline-block;
padding: 0.65rem 1rem;
border-radius: 0.35rem;
background: #1769aa;
color: #fff;
text-decoration: none;
}
.button-link:hover {
background: #0d4f80;
}
.button-link:focus-visible {
outline: 3px solid #f5b700;
outline-offset: 2px;
}
결과는 버튼처럼 보이지만 링크로 남습니다. 새 탭에서 열리는 경우에는 텍스트에도 표시하세요.
<a href="https://example.com/docs" target="_blank" rel="noopener">
Open the documentation (new tab)
</a>
버튼을 흉내 내려고 href="#" 또는 href="javascript:void(0)"를 사용하지 마세요. 실제 목적지가 아니며 스크롤과 북마크에서 예상하지 못한 동작이 생길 수 있습니다. href는 상대 경로, 절대 HTTPS URL, 프래그먼트 등이 될 수 있습니다. CSS는 모양만 바꾸므로 링크의 기본 브라우저 기능은 유지됩니다.
실제 버튼 동작일 때만 <button>과 JavaScript 사용하기
이동 전에 상태를 확인하거나 다른 작업을 해야 한다면 button을 유지할 수 있습니다. 타입을 명시하고 addEventListener로 리스너를 등록하세요. window.location.assign()이 이동을 수행합니다.
<button type="button" id="docs-button">Open the documentation</button>
<script>
document.querySelector("#docs-button").addEventListener("click", () => {
window.location.assign("https://example.com/docs");
});
</script>
이 예제는 포인터, Enter, Space로 활성화되지만 JavaScript가 필요합니다. 단순한 탐색에는 JavaScript가 꺼져도 사용할 수 있는 앵커를 선택하세요. 큰 애플리케이션에서는 인라인 onclick 대신 모듈에서 리스너를 등록합니다. 비어 있거나 잘못된 목적지는 경계 조건이므로 assign() 전에 동적 값을 검증하세요.
데이터를 전송할 때는 폼 사용하기
서버로 필드를 보낼 때는 폼의 action에 목적지를 지정하고 제출 컨트롤을 사용합니다. 이는 일반 링크 탐색이 아니라 폼 제출입니다.
<form action="/search" method="get">
<label for="query">Search</label>
<input id="query" name="q" type="search">
<button type="submit">Search</button>
</form>
CSS button을 제출하면 폼 인코딩에 따라 /search?q=CSS+button 같은 요청이 됩니다. 모양만을 위해 빈 폼을 사용하지 마세요. 특정 type="submit" 버튼에 다른 목적지를 주려면 formaction을 사용할 수 있습니다.
기존 프로젝트가 value 기반 표현을 요구한다면 <input type="submit">도 유효합니다.
<form action="/docs/" method="get">
<input type="submit" value="Open the documentation">
</form>
value가 표시 라벨이 됩니다. 이 input을 앵커로 감싸지 마세요. <input type="button">은 단독으로 제출하거나 이동하지 않으므로 스크립트가 필요합니다.
링크를 열지 않는 버튼 문제 해결하기
- 이동이 목적이면 CSS로 버튼처럼 보여도 마크업은
<a href="...">여야 합니다. - 폼에서 제출하지 않는 동작에는
type="button"을 지정하세요. 타입을 생략하면 submit이 되어 페이지를 다시 로드할 수 있습니다. - JavaScript button이 작동하지 않으면 콘솔, 선택자, 스크립트 로드를 확인하세요. JavaScript가 꺼져 있으면 handler는 실행되지 않습니다.
- 키보드 사용자가 포커스를 알 수 있도록
:focus-visible을 유지하세요. - 일반 링크에 중첩된
<button>이나<input>을 사용하지 마세요.
정리하면 탐색에는 <a href="...">, 동작에는 <button type="button">, 데이터 전송에는 폼 안의 submit button을 사용합니다. 이렇게 구분하면 브라우저와 보조 기술이 예측 가능한 의미를 얻습니다.