완벽하게 정렬된 사용자 지정 액세스 가능 라디오/체크박스 버튼

18133 단어 tutorialcss
맞춤형 라디오/체크박스 버튼을 만드는 것은 쉬운 일이 아닙니다. 액세스 가능하고 사용자 정의하기 쉬우며 라벨에 완벽하게 정렬되어야 합니다.

코디하우스에서 하는 방법입니다.

최종 결과



다음은 최종 결과(또는 download the CodyHouse UI component )의 미리 보기입니다.



HTML



구성 요소를 빌드할 때 고수하려고 하는 중요한 규칙은 가장 간단한 구조로 시작하여 필요한 경우에만 더 많은 요소(예: 래핑 부모)를 추가하는 것입니다.

라디오 및 체크박스 버튼에 필요한 것은 다음과 같습니다.

<!-- radio button -->
<div>
  <input class="radio" type="radio" name="radio-button" id="radio-1">
  <label for="radio-1">Choice 1</label>
</div>

<!-- checkbox button -->
<div>
  <input class="checkbox" type="checkbox" id="checkbox-1">
  <label for="checkbox-1">Option 1</label>
</div>

HTML 구조는 입력에 .radio/.checkbox 클래스를 추가한다는 점을 제외하면 기본 버튼에 사용하는 것과 동일합니다.

CSS



1단계는 기본 버튼을 시각적으로 숨기는 것입니다.

// hide native buttons
.radio,
.checkbox {
  position: absolute;
  margin: 0 !important;
  padding: 0 !important;
  opacity: 0;
  height: 0;
  width: 0;
  pointer-events: none;
}

절대 위치 요소에 대해 위/오른쪽/아래/왼쪽 값을 설정하지 않으면 흐름에서 제거되지만 이동하지는 않습니다. 그렇지 않으면 위치를 예측할 수 없고 버튼을 클릭할 때 페이지 상단으로 스크롤될 수 있기 때문에 중요합니다.

다음으로 +(인접한 형제 연결자)를 사용하여 레이블과 해당 ::before 의사 요소(사용자 정의 버튼)를 대상으로 지정하고 스타일을 지정합니다.

// label
.radio + label,
.checkbox + label { 
  user-select: none;
  cursor: pointer;
  line-height: 1.4;
}

// custom buttons - basic style
.radio + label::before,
.checkbox + label::before { 
  content: '';
  display: inline-block;
  width: 18px;
  height: 18px;
  background-color: var(--color-bg);
  border: 2px solid var(--color-contrast-low);
  margin-right: var(--space-xxxs); // gap between custom input and label
  transition: .2s;
}

// radio only style
.radio + label::before {
  border-radius: 50%; 
}

// checkbox only style
.checkbox + label::before {
  border-radius: 4px;
}

이 시점에서 몇 가지 CSS 사용자 지정 속성을 만들 수 있습니다. 이렇게 하면 나중에 버튼을 수정하기로 결정하면 사용자 정의가 훨씬 쉬워진다는 장점이 있습니다. 모든 CSS를 검사하는 대신 변수를 보고 업데이트할 수 있습니다.

:root {
  // radios and checkboxes
  --checkbox-radio-size: 18px;
  --checkbox-radio-gap: var(--space-xxxs); // gap between button and label
  --checkbox-radio-border-width: 2px;
  --checkbox-radio-line-height: var(--body-line-height);

  // radio buttons
  --radio-marker-size: 8px;

  // checkboxes
  --checkbox-marker-size: 12px;
  --checkbox-radius: 4px;
}

// replace fixed values with variables - example 👇
.checkbox + label::before {
  border-radius: var(--checkbox-radius);
}

입력의 선택 상태를 대상으로 지정하고 레이블 의사 요소에 스타일을 적용합니다.

// :checked
.radio:checked + label::before,
.checkbox:checked + label::before {
  background-color: var(--color-primary);
  border-color: var(--color-primary);
}

// radio button :checked
.radio:checked + label::before {
  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cg class='nc-icon-wrapper' fill='%23ffffff'%3E%3Ccircle cx='8' cy='8' r='8' fill='%23ffffff'%3E%3C/circle%3E%3C/g%3E%3C/svg%3E");
  background-size: var(--radio-marker-size);
}

// checkbox button :checked
.checkbox:checked + label::before {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpolyline points='1 6.5 4 9.5 11 2.5' fill='none' stroke='%23FFFFFF' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'/%3E%3C/svg%3E");
  background-size: var(--checkbox-marker-size);
}

데이터 URI를 통해 SVG 마커를 추가하기 위해 background-image 속성을 사용하고 있습니다. 이 기술의 장점은 CSS에서 아이콘의 두께( stroke-width='2' )와 색상( stroke='%23FFFFFF' )을 사용자 정의할 수 있다는 것입니다.

우리가 지금까지 가지고 있는 것:

조정



가장 어려운 부분은 라디오/체크박스 버튼을 레이블과 정렬하는 것입니다.

먼저 레이블의 표시 속성을 inline-flex로 설정하고 align-items를 flex-start로 설정합니다.

:root {
  // ...
  --checkbox-radio-gap: var(--space-xxxs);
  --checkbox-radio-line-height: var(--body-line-height);
}

// label
.radio + label,
.checkbox + label { 
  display: inline-flex;
  align-items: flex-start; // align button and label to top
  line-height: var(--checkbox-radio-line-height);
  // ...
}

// custom buttons - basic style
.radio + label::before,
.checkbox + label::before { 
  flex-shrink: 0; // prevent the button from shrinking
  margin-right: var(--checkbox-radio-gap); // gap
  // ...
}

그렇게 함으로써 레이블이 여러 줄로 나뉘는 경우 표시되는 왼쪽 정렬 문제를 수정했으며 버튼과 레이블을 위쪽으로 수직 정렬했습니다.



버튼과 레이블을 세로로 정렬하려면 레이블의 높이를 계산해야 합니다. 이는 글꼴 크기에 line-height를 곱한 것과 같습니다.



선 높이는 var(--checkbox-radio-line-height) 사용자 정의 속성에 저장됩니다. 레이블의 글꼴 크기 계산 값은 예측할 수 없지만(예: 유틸리티 클래스를 사용하여 변경할 수 있음) label::before 의사 요소의 경우 글꼴 크기는 항상 1em과 같습니다!

높이를 알면 수식을 사용하여 사용자 지정 라디오/확인란 버튼을 레이블의 첫 번째 줄에 정렬하는 매우 특정한 양의 버튼을 아래로 누를 수 있습니다. 🤯

.radio + label::before,
.checkbox + label::before {
  // ..
  position: relative;
  top: calc((1em * var(--checkbox-radio-line-height) - var(--checkbox-radio-size)) / 2);
}

이 수식은 모든 글꼴 크기 및 글꼴 모음 값과 호환됩니다.

캐주얼하고 예측할 수 없는 마이너스 마진 트릭은 이제 그만! 🎉

접근성



사용자 정의 요소를 생성하지 않았기 때문에 구성 요소에 액세스할 수 있으며 화면 판독기가 이를 적절하게 알립니다.



그러나 :focus 효과를 포함하는 것을 잊지 마십시오(네이티브 버튼은 표시되지 않음).

// :focus
.radio:focus + label::before,
.checkbox:focus + label::before {
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px alpha(var(--color-primary), 0.2);
}

최종 결과



최종 결과는 다음과 같습니다! UI 프레임워크에서 할 수 있습니다download this component.



CodyHouse.co에서 원래 게시됨

좋은 웹페이지 즐겨찾기