버튼이 버튼이 아닌 경우

게시 됨: 2022-03-10
요약 요약 ↬ 동그랗고 눈에 띄는 모든 것이 버튼으로 간주되는 것은 아닙니다. 이 기사에서 Vadim은 사용자를 위한 적절한 대화형 버튼을 만드는 방법을 설명합니다. 이 버튼은 다른 것과 혼동되어서는 안 됩니다.

사용자가 클릭하고 어떤 일이 발생하는 인터페이스의 일부가 있다고 가정해 보겠습니다. 나에게 버튼처럼 들리지만 지금은 "클릭이 많은 것"이라고 부르겠습니다. 당신은 그것이 버튼이라는 것을 확신합니다. 그것은 둥글고 멋진 토마토 색상으로 눈에 띄며 상호 작용을 요구합니다. 그러나 잠시 생각해보자. 장기적으로 시간을 절약할 수 있습니다. 약속합니다.

'뭔가'라는 글자가 있는 토마토 버튼 같은 것.
'클릭이 많은 것'을 위한 디자인(큰 미리보기)

이 클릭적인 것의 텍스트가 "자세히 알아보기"이고 이를 클릭하면 사용자가 다른 페이지의 기사로 이동하게 된다면 어떻게 될까요? 흠. 파란색 밑줄이 그어진 단어 "닫기"가 있으면 팝업 대화 상자가 닫힙니다. 파란색 밑줄이 쳐져 있어서 링크인가요? 당연히 아니지.

버튼형 링크와 링크형 버튼
링크 또는 버튼 딜레마(큰 미리보기)
점프 후 더! 아래에서 계속 읽기 ↓

와! 그냥 보기에는 링크인지 버튼인지 알 방법이 없는 것 같습니다. 그건 미친 짓이야! 올바른 요소를 선택하기 전에 이것이 무엇을 하는지 이해해야 합니다. 그러나 그것이 무엇을 하는지 아직 알지 못하거나 단순히 혼란스럽다면 어떻게 될까요? 우리를 위한 편리한 순서도가 있습니다.

순서도: 버튼입니다. 그렇지 않은 경우 링크입니다. 그게 다야
올바른 요소를 선택하기 위한 과학적 순서도(큰 미리보기)
  1. 버튼입니다.
  2. 그렇지 않은 경우 링크입니다.
  3. 그게 다야

그렇다면 모든 것이 버튼입니까? 아니요. 하지만 클릭하거나 유사한 방식으로 상호 작용할 수 있는 거의 모든 요소의 버튼으로 시작할 수 있습니다. 그리고 다른 페이지로 이동하는 것과 같이 부족한 부분이 있으면 대신 링크를 사용하세요. 그리고 아니요, 포인터는 <a href> 로 만드는 이유가 아닙니다. cursor: pointer 가 있습니다.

'무언가' 텍스트가 있는 집중된 토마토 버튼
포커스 스타일을 제공하는 것을 잊지 마십시오. (큰 미리보기)

좋습니다. <button> 버튼입니다. 이에 동의합니다. 템플릿에 넣고 일부 패딩, 반올림, 토마토 채우기, 흰색 텍스트 및 일부 포커스 스타일과 같은 디자인에 따라 스타일을 지정해 보겠습니다. 오, 당신이 너무 좋습니다.

 <button type="button" class="button"> Something </button> <style> .button { display: inline-block; padding: 10px 20px; border-radius: 20px; background-color: tomato; color: white; } .button:focus { outline: none; box-shadow: 0 0 0 5px #006AE3; } </style>

오래 걸리지 않았습니다. 배가 고파서 빨리 건물을 짓고 점심을 먹고 싶었습니다. 좋아, 어떻게 생겼는지 봅시다.

브라우저에서 렌더링된 못생긴 토마토 버튼
때로는 브라우저가 가장 친한 친구가 아닙니다. (큰 미리보기)

세상에! 브라우저에 문제가 있습니다. 이 버튼이 왜 이리 못생겼지? body 을 명시적으로 16px 로 설정했지만 font-family 가 잘못되었음에도 텍스트는 작습니다. 어리석은 의사 그림자가 있는 둥근 테두리는 너무 복고풍이어서 아직 트렌드도 아닙니다.

아, 브라우저의 기본 스타일입니다. 신중하게 실행 취소하거나 Normalize.css 또는 Reset.css를 추가해야 합니다. 그렇지 않으면 <div> 를 사용하고 잊어버릴 수 있습니다. 문제를 빨리 해결하는 것이 비용을 지불하는 것이 아닙니까? 당신은 배고프고 이것은 전혀 도움이 되지 않습니다. 그러나 당신은 전문가입니다. 함께 생각하고 생각하십시오.

어쨌든 <button><div> 의 차이점은 무엇입니까? 내장된 <button> 은 상호 작용할 수 있음을 의미하는 대화형 요소입니다. 깊다. 클릭할 수 있고 키보드로 집중할 수 있으며 스크린 리더에 접근 가능한 button 역할을 전달하여 사용자가 버튼임을 이해할 수 있습니다.

감동적인! HTML의 <button> 요소에 대해 알고 있을 뿐만 아니라 ARIA 및 화면 판독기 지원에 대해서도 한두 가지 알고 있습니다. 인터페이스가 얼마나 액세스 가능한지 테스트하기 위해 VoiceOver 또는 NVDA를 시도했을 수도 있습니다.

그래서, 당신은 트릭을하기로 결정했습니다. 브라우저의 스타일을 엉망 으로 만들지 않고 요소가 필요할 수 있는 사용자에게 적절한 대화형 버튼처럼 보이도록 만들 것입니다. 똑똑해!

 <div class="button" tabindex="0" role="button"> Something </div>

이제 제대로 보일 뿐만 아니라 tabindex="0" 속성 덕분에 키보드를 통해 초점을 맞출 수 있으며, 현명하게 role="button" 을 추가했기 때문에 스크린 리더는 이를 적절한 버튼으로 처리합니다. Git 커밋 && 푸시! 이 작업에 대한 몇 가지 추가 작업이 있지만 스타일 지정은 완료되었습니다. 무엇이 잘못될 수 있습니까? 점심 시간. 좋아 가자!

한 시간 후…

좋은 점심이었습니다! 우리의 클릭하기 쉬운 것으로 돌아가자. 계속 진행하기 전에 몇 가지 작업을 완료해야 합니다. 봅시다... 버튼이 클릭되면 doSomething 함수를 호출해야 하고 버튼을 클릭할 수 없도록 비활성화하는 방법이 있어야 합니다. 쉽게 들리네요. 이 버튼에 이벤트 리스너를 추가해 보겠습니다.

 <script> const buttons = document.querySelectorAll('.button'); [...buttons].forEach(button => { button.addEventListener('click', doSomething); }); function doSomething() { console.log('Something!'); } </script>

완료. 이제 사용자는 데스크탑에서 마우스로 클릭하고 터치스크린에서 손가락으로 탭할 수 있습니다. 클릭 이벤트는 안정적으로 실행되며 많은 것을 볼 수 있습니다! 당신의 콘솔에서. 다음 작업은 무엇입니까?

기다리다! 키보드 사용자에게 동일하게 작동하는지 확인해야 합니다. 버튼에 이 tabindex="0" 이 있기 때문에 포커스를 맞출 수 있으며 포커스가 맞춰지면 사용자는 스페이스바 또는 "Enter" 키를 눌러 첨부한 항목을 트리거할 수 있어야 합니다.

따라서 모든 키업을 포착하기 위해 다른 이벤트 리스너를 연결해야 하며 특정 키에 대해서만 함수를 트리거합니다. 터치 장치가 모든 탭을 클릭으로 변환할 만큼 충분히 똑똑하다는 사실에 하나님께 감사드립니다. 그렇지 않으면 많은 터치 이벤트도 첨부해야 합니다.

 <script> const buttons = document.querySelectorAll('.button'); [...buttons].forEach(button => { button.addEventListener('click', doSomething); button.addEventListener('keyup', (event) => { if (event.key == 'Enter' || event.key == ' ') { doSomething(); } }); }); function doSomething() { console.log('Something!'); } </script>

휴! 이제 키보드에서 클릭할 수 있는 항목에 완전히 액세스할 수 있습니다. 당신이 정말 자랑스럽습니다! 그리고 JavaScript는 정말 마법과 같습니다. JavaScript 없이는 무엇을 할 수 있을까요?

좋습니다. 마지막 작업은 무엇인가요? "버튼의 모양과 동작을 마비된 것으로 변경하는 비활성화된 상태여야 합니다." 무감각? 나는 그것이 회색이고 상호 작용에 반응하지 않는다는 것을 의미한다고 생각합니다. 자, BEM 이름 지정을 사용하여 스타일 시트에 상태를 추가해 보겠습니다.

 <div class="button button--disabled" tabindex="0" role="button"> Something </div> <style> .button--disabled { background-color: #9B9B9B; } </style> 
비활성화 상태가 적용된 회색 버튼
이 버튼은 편안하게 마비된 것처럼 보입니다. (큰 미리보기)

그것은 나에게 편안하게 무감각 해 보인다. 버튼을 비활성화해야 할 때마다 버튼을 회색으로 만들기 위해 button--disabled 된 수정자를 추가합니다. 그러나 아직 충분히 무감각하지 않습니다. 포인터와 키보드 모두에 의해 여전히 초점을 맞추고 트리거할 수 있습니다.

이런, 점점 까다로워지고 있습니다.

뿐만 아니라 탭 순서대로 버튼에 액세스할 수 없어야 합니다. 즉, tabindex 속성이 없어야 합니다. 그리고 버튼이 비활성화 상태인지 확인한 다음 기능 트리거를 중지해야 합니다. 또한 이 수정자는 동적으로 적용될 수 있습니다. CSS가 요소를 즉석에서 선택기와 일치시키고 스타일을 적용하는 것은 문제가 아니지만 이 버튼에 대한 다른 변경을 트리거하려면 일종의 돌연변이 관찰자가 필요할 수 있습니다.

나도 알아, 그렇지? 우리는 이것이 기능을 트리거하고 비활성화된 상태를 갖는 간단한 작은 버튼이라고 생각했습니다. 우리는 접근성과 그 모든 것들로 그것을 바로잡기 위해 노력했고, 이제 우리는 이 토끼굴에 깊숙이 들어왔습니다.

테이크아웃 음식을 먹자. 우리가 끝내고 이것을 적절하게 테스트할 때까지 저녁 식사를 위해 집에 가지 않을 것입니다. 블러디 W3C! 그들은 왜 우리의 삶을 더 쉽게 만들려고 하지 않습니까? 마치 그들이 우리를 걱정하는 것처럼!

사실, 그들은 ...

이 혼란에 빠지기 전에 몇 걸음 뒤로 물러나자. <button> 요소를 사용하여 이러한 작업을 시도하지 않는 이유는 무엇입니까? 브라우저의 못생긴 스타일뿐만 아니라 소매에 몇 가지 유용한 트릭이 있습니다. 아, 그리고 type="button" 잊지 마세요. 팝업의 "닫기" 버튼이 실수로 양식을 제출하는 것을 원하지 않습니다. type="submit" 이 기본값이기 때문입니다.

분명히 <button> 에 포커스가 있고 스페이스 바 또는 "Enter" 키를 누르면 모바일 장치가 탭, 톡, 핥기 또는 수신할 수 있는 모든 것을 받을 때와 마찬가지로 click 이벤트가 트리거됩니다. 오늘. 우리 코드에서 이벤트 리스너가 하나 더 적습니다! 멋진.

 // A click is enough! button.addEventListener('click', doSomething);

비활성화 상태의 경우 disabled 된 속성은 <button> 요소와 <fieldset> 을 포함한 모든 양식 요소에 사용할 수 있습니다. 농담이 아니다. 부모 <fieldset> 에 단일 속성을 적용하기만 하면 함께 그룹화된 전체 입력을 비활성화할 수 있다는 것을 알고 계셨습니까?

비활성화된 입력 그룹 및 버튼
단일 속성으로 비활성화된 입력 묶음(큰 미리보기)
 <fieldset disabled> <legend>A bunch of numb inputs</legend> <p> <label> <input type="radio" name="option"> Of course it's a link </label> </p> <p> <label> <input type="radio" name="option"> Obviously, it's a button </label> </p> <p> <label> <input type="radio" name="option"> I just wanna go home </label> </p> <button type="button">Button</button> </fieldset>

이제 알았습니다! 이 속성은 양식 요소의 모든 이벤트를 비활성화할 뿐만 아니라 탭 순서에서 제거합니다. 문제 해결됨!

 <button disabled type="button" class="button"> Something </button>

하지만 더 많은 것이 있습니다! 또한 CSS에서 :disabled 의사 클래스를 트리거합니다. 즉, BEM 수정자를 제거하여 스타일을 선언하고 내장된 동적 수정자를 대신 사용할 수 있습니다.

 .button:disabled { background-color: #9B9B9B; }

브라우저의 못생긴 스타일에 관해서는 단일 버튼을 수정하기 위해 Normalize.css 전체를 사용할 필요가 없습니다. 지혜의 원천으로 사용하십시오. 아래의 세 줄은 <div> 와의 성가신 차이점 대부분을 수정합니다. 더 필요한 경우 관련 부품을 복사할 수 있습니다.

 .button { font-size: 100%; font-family: inherit; border: none; }

완료. HTML은 결국 그렇게 나쁘지 않습니다!

그러나 때때로 놀라움을 금치 못한다면 HTML 사양에서 답을 확인하십시오. 수년에 걸쳐 훨씬 더 친숙해졌으며 좋은 사용법과 접근성 예제로 가득 차 있습니다. 물론 HTML5 Doctor는 여전히 <section> 요소와 <article> 요소의 차이점을 파악하고 문서 개요가 아직 문제인지(실제로는 아님) 확인할 수 있는 신뢰할 수 있는 곳입니다. 결국 Mozilla의 HTML 문서를 읽게 될 좋은 기회가 있으며 후회하지 않을 것입니다.

이제 이 작업이 완료되었습니다! 무엇 향후 계획? 검색 필드가 있는 드롭다운 캐러셀 캘린더? 어머! 좋은 결과 내길 바랄 게. 그러나 기억하십시오: <button> 은 당신의 친구입니다!

SmashingMag에 대한 추가 정보:

  • 더 나은 버튼을 디자인하는 방법
  • 포괄적인 토글 버튼 구축
  • 고스트 버튼 디자인: 이것이 정말로 여전히 존재합니까(왜)?
  • 디자인 패턴: 규칙을 깨도 괜찮을 때