CSS로 뉴모피즘 버튼 제작하기 [2/20]

가르송·2023년 2월 20일
1

매일공부

목록 보기
5/11
post-thumbnail

지난주에 만들었던 계산기를 리팩토링하면서 어딘가 어색하다는 생각이 들었다.
종이 위에서 톡(!) 튀어나온 것 같은 계산기를 만들고 싶었는데, figma 디자인과 임의로 작성한 코드가 섞이다 보니 기획과는 동떨어진 결과물이 나왔다. 요소마다 그림자의 색과 방향이 다른 것도 마음에 들지 않았다.

보다 자연스럽게 구현하기 위해 유튜브에서 WEB CIFAR의 How To Create Neumorphism Effect With CSS 영상을 들었다. 아래는 강의를 보며 정리한 내용과 의문점, 직접 실험해 본 내용을 담았다.

그림자의 방향

WEB CIFAR에 따르면, 자연스러운 그림자를 만들기 위해서는 좌상단에 광원을 두는 것이 좋다고 한다. 그러면 아래 이미지와 같이 버튼의 좌상단에는 빛이, 우하단에는 어두운 그림자가 발생한다.

단순한 버튼

.button {
  height: 50px;
  width: 50px;
  background: #dde1e7;
  box-shadow: -3px -3px 7px #ffffff73, 3px 3px 5px rgba(94, 104, 121, .288);
  border-radius: 5px;
}

.button-clicked {
  height: 50px;
  width: 50px;
  background: #dde1e7;
  box-shadow: inset -3px -3px 7px #ffffff73, inset 3px 3px 5px rgba(94, 104, 121, .288);
  border-radius: 5px;
}

클릭된 버튼 효과를 만들기 위해서는 기존 box-shadow 속성값에 inset을 부여하면 된다. 영상의 코드에는 position: absolute;position: relative; 속성도 있었으나 어떤 용도인지 확실하지 않고, 그 값이 없을 때에도 같은 결과가 나오기 때문에 코드에서 제거했다.

내부에 굴곡이 있는 버튼

테두리는 볼록 튀어나오고, 버튼 내부는 들어간 형태의 버튼이다.
버튼 내부에 또 하나의 원을 만들기 위해서는 ::after 를 사용해야 한다.

::after
내용의 앞에 content를 추가하는 가상 요소이다.
가상 요소란 꾸미기 위해서 의미 없는 태그를 추가해야 할 때, 태그 대신 실제로 존재하지 않는 가상의 요소를 만들어서 스타일을 꾸밀 수 있도록 해주는 css 기능이다.

추가하는 content의 내용은 content 속성으로 처리한다.
::after를 사용할 때에는 이 속성을 무조건 사용해야 한다. 따라서 추가할 내용이 없는 경우에는 아래 예시 코드와 같이 빈 문자열을 값으로 주면 된다.

코드는 다음과 같다.

.circle {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 50px;
  width: 50px;
  background: #dde1e7;
  box-shadow: inset -3px -3px 7px #ffffff73, inset 3px 3px 5px rgba(94, 104, 121, .288);
  border-radius: 50%;
}

.circle::after {
  content: '';
  height: 80%;
  width: 80%;
  box-shadow: inset -3px -3px 7px #ffffff73, inset 3px 3px 5px rgba(94, 104, 121, .288);
  border-radius: 50%;
}

::after 대신 border 속성을 활용하면?

나처럼 position: absolute;position: relative; 속성한 것에 의문을 가진 사람이 있는지 확인하기 위해 영상 댓글을 읽던 중 흥미로운 의견을 발견했다.

이 댓글에서 말하는 neumorphisum-3은 내부에 굴곡이 있는 버튼(unclicked)이다.
제안처럼 가상 요소를 사용하지 않고 구현할 수 있겠다는 생각이 들어 직접 실험해 보았다.

가상 요소를 활용하지 않은 코드

.button {
  display: flex;
  justify-content: center;
  align-items: center;
  box-sizing: border-box;

  height: 50px;
  width: 50px;
  background: #dde1e7;
  box-shadow: -3px -3px 7px #ffffff73, 3px 3px 5px rgba(94, 104, 121, .288), inset -3px -3px 7px #ffffff73, inset 3px 3px 5px rgba(94, 104, 121, .288);
  border: 5px solid transparent;
  border-radius: 50%;
}

가상 요소를 사용하는 대신 border: 5px solid transparent; 속성을 추가했다.
또한 border를 기준으로 원 안쪽에 그림자 효과를 주기 위해 .circle::after 의 box-shadow 속성값을 가져왔다.

단점

border 속성을 활용하면 훨씬 짧은 코드로 구현할 수 있지만 치명적인 단점이 있다. 바로 clicked 버전을 구현할 수 없다는 것... 😅

  • 가상 요소를 활용하는 방법 ➡️ 커다란 원 내부에 또 하나의 작은 원을 만든다. 큰 원과 작은 원 모두 그림자가 원 내부로 향하도록 설정한다.
  • border를 활용하는 방법 ➡️ 커다란 원 자체에 굵은 border를 설정한다. box-shadow 속성을 통해 그림자가 원 내부로 향하도록 하면 border 안쪽으로만 그림자가 생성된다. border 자체에 그림자 효과를 적용할 수 있는 방법은 없으므로 clicked 버전은 구현할 수 없다.

clicked 효과를 주지 않을 거라면 border를 활용해도 좋겠다.
하지만 버튼은 클릭을 전제로 만들어지는 엘리먼트이다. 뉴모피즘의 단점인 낮은 접근성을 개선하기 위해서라도 clicked 효과를 염두에 두고 처음부터 가상 요소를 활용하면 좋을 것 같다.

profile
개발도 운동도 뜻대로 되지 않을 때에는? 산책을 합니다.

0개의 댓글