CSS - display: none 을 대체하는 방법

윤남주·2021년 11월 26일
0
post-thumbnail

자기소개 페이지를 만드는 마지막 과정에서, 나의 학력과 경력을 추가하였다.
하지만 이런 개인 정보를 대놓고 보여주기가 조금 부끄러워서(...) 버튼을 누르면 펼쳐지도록 하고자 하였다.
그때부터 시작된 고통...

일단 완성된 내 자기소개 페이지 : https://jujusnake.github.io/introduction/


1. 버튼 클릭 -> 클래스명 추가 스크립트

    <script>
      function showContent(content, button) {
        let element = document.getElementById(content);
        element.classList.toggle("show");

        let element2 = document.getElementById(button);
        element2.classList.toggle("active-button");
      }
    </script>

showContent라는 함수를 만들어 인자 두개를 받도록 하였다.

  • content : 어떤 것을 펼치도 닫을 지
  • button : 어떤 버튼을 눌러야 실행이 될지

그리고 content에 .show | button에는 .active-button이라는 클래스가 추가되도록 하였다.
여기까지는 직관적이고 쉬웠다. 하나의 함수로 학력과 경력 둘 다 사용할 수 있어서 좋고.


2. 문제는 CSS...

.bio button {
  font-size: 20px;
  font-weight: 700;
}

#study-content,
#work-content {
  display: none;
  font-size: 16px;
  line-height: 1.5em;
}

content 영역이 보이지 않도록 display: none;을 주었다.

.active-button {
  text-decoration: underline;
  margin-bottom: 28px;
}

.show {
  display: block;
}

버튼을 누를 시 위의 두 클래스가 추가된다.
버튼에는 밑줄이 그어지고, 아래에 마진 값이 생긴다.
컨텐츠 영역은 display가 block으로 바뀌며 보여지게 된다.

하지만 display: none은 transition을 먹지 않는다!!!
나는 띡띡 열리는 것보다 당연히 스무~스하게 열리고 닫히는 것을 원했기 때문에 다른 방법을 찾을 수 밖에 없었다...

1) visibility

visibility를 사용하면 display를 대체할 수 있지만, 문제는 얘도 transition 안먹는다. 그래서 사람들은 opacity까지 함께 사용하여 트랜지션을 주는 듯.

#study-content,
#work-content {
  visibility: hidden;
  opacity: 0;
  font-size: 16px;
  line-height: 1.5em;
  transition: opacity 300ms ease-in-out;
}

.show {
  visibility: visible;
  opacity: 1;
}

(transition의 작동 원리를 살펴보니 연속적인 숫자로 값을 줄 수 있는 속성에만 작동한다고 한다. 그러니까 visibility의 경우 hidden -> visible로 가는 비연속적 속성이므로 불가능. opacity의 경우 0~1까지의 연속적인 값을 가지는 속성이므로 가능)

하지만 난 opacity로 스무스한걸 원한게 아니란말야 ㅠㅠ
나는 그냥 위에서부터 쫘르르~ 펼치는 것을 원했다.
또한 visibility를 사용하면 빈 공간이 잡혀서 레이아웃이 틀어지는게 싫었다.

2) height

그래서 나는 height가 0에서 시작하여 auto로 스무스~ 하게 펼쳐지면 되는 일 아닐까? 하고 생각했다. overflow: hidden;을 같이 주면, 닫혀있을 때에는 빈 영역이 잡히지도 않고, 보이지도 않고.

#study-content,
#work-content {
  height: 0px;
  overflow: hidden;
  font-size: 16px;
  line-height: 1.5em;
  transition: auto 300ms ease-in-out;
}

.show {
  height: auto;
}

하지만... 이번엔 height: auto로의 트랜지션이 되지 않는다 ㅠㅠ
이쯤되니까 그냥 트랜지션이 있을 필요가 있을까? 하는 생각이 들었다.
하지만 다른 방법을 강구했다... height 값을 숫자로 지정해주면 해결이 되었지만, 그렇게 하면 추후에 콘텐츠가 추가될 때 대응이 귀찮다. auto를 계속 사용할 수 있는 방법을 원했다.

3) max-height

검색을 계속 해보니, height에 트랜지션을 주지 않고 max-height를 이용하는 방법이 있었다.

#study-content,
#work-content {
  max-height: 0px;
  overflow: hidden;
  font-size: 16px;
  line-height: 1.5em;
  transition: max-height 300ms ease-in-out;
}

.show {
  max-height: 200px !important;
}

닫혀있을 땐 max-height: 0px;을 준다. 그러면 당연히 영역이 0px이 되어서 보이지 않는다.
열 때는 max-height 값을 넉넉히 준다 (나는 임의로 200px, 하지만 그냥 100vh 등으로 줘도 될 것 같다).
이렇게 하면 height는 디폴트 값으로 auto이기 때문에 펼쳐져도 실제 차지하는 영역은 딱 content의 내용 만큼이다.

하지만 transition은 max-height에 0 ~ 200px로 변화하도록 주었기 때문에, 스무스하게 열리게 된다!
문제 해결!


그 이후에는 버튼에 주었던 margin-bottom에도 transition을 주어야했다.

.bio button {
  font-size: 20px;
  font-weight: 700;
  transition: margin-bottom 300ms ease-in-out;
}

안주면 마진이 생겼다 사라졌다 할 때, 딱딱하게 붙게 된다.

솔직히 쉬울거라 생각하고 도전했는데... 정말 오랫동안 붙들고 있었다.
하지만 결과는 만족스러워서 다행.

여기서 추가적으로 생각할 것이 있다면
접근성 측면에서 display, visibility, height 등의 속성을 쓸 때 스크린리더는 어떻게 반응하는지를 보아야할 것 같다.

그러면 첫 번째 velog 글 포스팅 끝-

profile
Dig a little deeper

0개의 댓글