유지보수 시 편한 스위치 만들기

김솔·2021년 7월 21일
0
post-thumbnail

실무에서 프로젝트 진행하다가 갑자기(?!) 클라이언트가 스타일 변경을 요청했을 때,
width 하나 바꿔 달라는데 다른 속성도 변경해야하는 일이 생긴 적 있으신가요?
스위치의 경우에서 SASS로 해결해봅시다!!

문제점

  • 위 스위치에서 width 값이 변경되는 경우
    • 스위치 사이즈가 변경에 따라, checked 시 써클의 left 값도 함께 조절 해줘야합니다.
  • 위 스위치에서 height 값이 변경되는 경우
    • 스위치 사이즈가 변경에 따라, 써클의 width , height 값도 함께 조절 해줘야합니다.
  • 써클의 사이즈가 변경되는 경우 ( 스위치와 써클 사이 간격이 조정되는 경우 )
    • 써클의 y좌표가 중앙에 맞춰져야하기 때문에 top 값도 함께 조절 해줘야합니다.
      ( 물론 top : 50% , transform : translateY(-50%) 속성을 적용 시 고려하지 않아도 됩니다 :) )
    • 써클의 y좌표가 변경되었으니 x좌표도 바뀌어야겠죠?
      미체크 시 , 체크 시 left 값 역시 조절 해야줘야합니다.

해결책

  • 스위치의 width , height , 써클과 스위치 사이 간격인 padding 값을 세워두고,
    위 3가지 value를 기준으로 써클의 크기 , left , top 등등을 계산해두면 되겠다!

코드를 작성해봅시다.

<input type="checkbox" class="switch" />

스위치를 적용시킬 checkbox input의 className을 "switch" 로 선언해줍시다.

// 스위치 너비 값
$width: 50px;
// 스위치 높이 값
$height: 26px;
// 스위치 내 padding
$padding: 3px;
// not-checked 시 스위치 배경 색
$not-checked-color: #DBDBDB;
// checked 시 스위치 배경 색
$checked-color: #FE9898;
// 서클 배경 색
$circle-color: #FFFFFF;
// 서클의 너비 및 높이 : 스위치의 높이 - padding-top - padding-bottom
$circle-size: #{$height - ($padding * 2)};
// 체크될 시 서클의 left 좌표 : 스위치 너비 - 서클 사이즈 - padding-right
$checked-circle-left: calc(#{$width} - #{$circle-size} - #{$padding});
// 서클의 box-shadow
$circle-shadow: 0 3px 6px rgba($color: #000000, $alpha: 0.1);
// 스위치 , 서클의 전환 속도
$transition: 0.21s;

위처럼 변수를 준비해줄께요!

.switch {
  appearance: none;
  -moz-appearance: none;
  -webkit-appearance: none;
  width: $width;
  height: $height;
  border-radius: #{$height / 2};
  background-color: $not-checked-color;
  transition: $transition;
  position: relative;
  cursor: pointer;
}

그리고 스위치에 적용시켜보겠습니다!
appearance : none 으로 브라우저에서 씌운 기본 checkbox input 스타일을 벗겨내야겠죠?
position: relative 로 가상 요쇼인 써클이 스위치를 기준으로 움직일 수 있게 설정해주세요.
border-radius는 양쪽을 둥글게 할꺼라서, height의 절반 값으로 설정해줬어요.

여기까지 잘 따라오셨다면 아래와 같은 화면을 보실 수 있으실꺼에요!


.switch {
  ...
  
  &::after {
    content: "";
    position: absolute;
    display: block;
    left: $padding;
    top: $padding;
    width: $circle-size;
    height: $circle-size;
    border-radius: 50%;
    background-color: $circle-color;
    transition: $transition;
    box-shadow: $circle-shadow;
  }
}

스위치의 가상 요소인 써클을 만들어주세요!
position: absolute로 상위 요소인 스위치를 기준으로 포지션을 잡겠습니다.
left, top : 스위치와 간격 설정을 위해 위에서 선언한 $padding 변수를 사용해주세요.

여기까지도 잘 작성하셨다면 아래와 같이 써클이 함께 보일겁니다 :)


이젠 checked 시 처리를 진행해볼께요!

.switch {
  ...
  
  &:checked {
    background-color: $checked-color;

    &::after {
      left: $checked-circle-left;
    }
  }
}

&:checked를 .switch 바로 아래 선언해 줌으로써
스위치가 체크되었을 때 스위치의 배경색을 변경해줍니다!

그리고 .switch:chekced 바로 아래 ::after ( 가상 요소 )의 left 값을
위에서 선언해둔 $checked-circle-left 값으로 덮어 씌울께요!

여기까지 잘 따라오셨다면 아래와 같이 이쁜 스위치를 보실 수 있어요 :)


스타일 변경 요청 대응해보기!

자, 이제 클라이언트의 수정 사항을 아주 간단하게 대응해볼께요!

클라이언트 : switch의 width 값을 20 더 늘려주세요!
나 : $width: 50px; -> $width:70px;

소스 단 한 줄 수정으로 체크 , 미 체크시 대응이 정상적으로 이루어졌어요!


클라이언트 : 추가로 switch의 height 값을 10 더 늘려주세요!
나 : $height: 26px; -> $height: 36px;

네! 처리되었습니다~


클라이언트 : 아 근데 지금보니까 써클이 좀 큰 것 같네요. 써클 사이즈 3씩 줄어주세요!
나 : (...) 네 알겠습니다~! $padding: 3px; -> $padding: 6px;


최종소스

.switch {
  // 스위치 너비 값
  $width: 70px;
  // 스위치 높이 값
  $height: 36px;
  // 스위치 내 padding
  $padding: 6px;
  // not-checked 시 스위치 배경 색
  $not-checked-color: #dbdbdb;
  // checked 시 스위치 배경 색
  $checked-color: #fe9898;
  // 스위치 , 서클의 전환 속도
  $transition: 0.21s;
  // 서클의 너비 및 높이 : 스위치의 높이 - padding-top - padding-bottom
  $circle-size: #{$height - ($padding * 2)};
  // 체크될 시 서클의 left 좌표 : 스위치 너비 - 서클 사이즈 - padding-right
  $checked-circle-left: calc(#{$width} - #{$circle-size} - #{$padding});
  // 서클의 box-shadow
  $circle-shadow: 0 3px 6px rgba($color: #000, $alpha: 0.1);
  // 서클 배경 색
  $circle-color: #fff;

  appearance: none;
  -moz-appearance: none;
  -webkit-appearance: none;
  width: $width;
  height: $height;
  border-radius: #{$height / 2};
  background-color: $not-checked-color;
  transition: $transition;
  position: relative;
  cursor: pointer;

  &::after {
    content: "";
    position: absolute;
    display: block;
    left: $padding;
    top: $padding;
    width: $circle-size;
    height: $circle-size;
    border-radius: 50%;
    background-color: $circle-color;
    transition: $transition;
    box-shadow: $circle-shadow;
  }

  &:checked {
    background-color: $checked-color;

    &::after {
      left: $checked-circle-left;
    }
  }
}

마무리

base가 되는 변수를 세워두고 그들을 기준으로 나머지 값을 채워넣었더니
위처럼 클라이언트의 수정 요청 사항이 간단히 이루어졌죠!

처음에는 힘들고 어려울 수 있지만, 차근차근 간단한 부분부터 적용해 나아간다면,
스타일 수정 때문에 머리를 쥐어짜며 야근하는 일은 줄어들 것 같네요 :)

profile
React + TS 💙

0개의 댓글