프로그래머스 웹 프론트엔드 과제 with vanillaJS 3

jeky22·2021년 1월 18일
1
post-thumbnail

문제

이미지 상세 보기 모달 관련

  • 디바이스 가로 길이가 768px 이하인 경우, 모달의 가로 길이를 디바이스 가로 길이만큼 늘려야 합니다.
  • 필수 이미지를 검색한 후 결과로 주어진 이미지를 클릭하면 모달이 뜨는데, 모달 영역 밖을 누르거나 / 키보드의 ESC 키를 누르거나 / 모달 우측의 닫기(x) 버튼을 누르면 닫히도록 수정해야 합니다.

템플릿 코드 분석

.ImageInfo {
  position: fixed;
  left: 0;
  top: 0;
  /*width: 100%;*/
  width: 100vw;
  height: 100vh;
  background-color: rgba(0, 0, 0, 0.5);
}
.ImageInfo .content-wrapper {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}

문제 요구사항인 가로길이 768px 이하인 경우, 모달의 길이 늘리기는 복잡한 코드가 필요한 것이 아닙니다. 2편에서 작성한 미디어 쿼리에 한줄만 더 쓰면 되기 때문입니다.


@media (max-width: 768px) {
    .SearchResult {
        grid-template-columns: repeat(2, minmax(250px, 1fr));
    }
    .ImageInfo .content-wrapper {
        /* 템플릿 코드에 width는 주로 vw로 사용되었습니다. */
        /*width: 100vw;*/
        width: 100%;
    }
}

VW vs %

이렇게 vw 단위로 선언을 하게되면 768px 미만인 경우, 모달창을 닫을 수 있는 x버튼이 스크롤바에 의해서 짤리게 되어 기능상으로도, 외관상으로도 좋지 않습니다.

이는 vw가 가진 특수성때문입니다. vw(viewport width)는 열려있는 화면의 상대적인 길이 이기 때문에, 스크롤바를 포함하게 됩니다. 따라서 100vw로 선언된 width는 스크롤바에 가려지는 부분이 생기게 됩니다. 모바일 뷰의 경우 스크롤바가 생기지 않기 때문에 이런 선언이 허용되지만 웹의 경우 좋지 않습니다.

참고자료: 블로그 링크

이 경우, 모바일 뷰와 웹 뷰 모두를 만족하려면 %로 선언하여 width를 조절하여야 합니다. %는 부모 요소의 길이 만큼이 보장되기 때문에, 스크롤바가 있다면 그 부분을 포함하지 않아 x버튼이 보이게 됩니다.

height가 긴 경우

image의 height가 길다면 사진이 vh보다 커져 디바이스를 넘어버리게 됩니다. 따라서 image의 max-height를 설정하여 overflow되지 않도록 조절해야합니다.

modal창 끄기

모달창을 끄기위해서는 이벤트 리스너를 달아주어야 합니다. 먼저 템플릿 코드처럼 ImageInfo class에 onClose 함수를 파라미터로 전달합니다. (onClose 역할은 class SearchResult onclick 함수와 반대로 visible을 false로 만드는 것 입니다.)

this.imageInfo = new ImageInfo({
  $target,
  data: {
    visible: false,
    image: null,
    id: null
  },
  onClose: ()=> {
    this.imageInfo.setState({
      visible: false,
      image: null
    });
  }
});

이렇게 선언하게 되면 ImageInfo.js 파일에서 자유롭게 onClose함수를 사용할 수 있게 됩니다.
ImageInfo class constructure에 onclose 함수를 이용하여 이벤트 리스너를 추가할 수 있습니다.

constructor({ $target, data, onClose }) {
 
  /*중략*/
  
  this.onClose=onClose

  document.body.addEventListener("click",(e)=>{
    if(e.target.className==="ImageInfo"||e.target.className==="close")
    this.onClose();
  })

  document.body.addEventListener("keyup", e => {
    if (e.keyCode === 27) {
      this.onClose();
    }
  });
}

ImageInfo가 클릭된 상태에서는 모달창을 제외한 부분이 모두 ImageInfo 클래스를 가지고 있습니다. 또한 x버튼 은 close라는 클래스를 가지고 있기 때문에 클릭 이벤트 타겟에 맞춰 설정하면 됩니다.

profile
프론트엔드 개발자

0개의 댓글