[HTML/CSS/JS] 팝업 구현 2(+매개 변수, 이벤트 전파 방지, 스크롤바)

happyyeom·2024년 10월 25일

팝업창을 매개변수를 사용하여 2개로 만들기

앞에서 팝업을 이 부분까지 구현했었다. 함수의 매개 변수를 이용하여 팝업창을 2개로 만들어보자.
우선 매개 변수를 사용하지 않는다고 하면 어떻게 구현할까?
html

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<!--jQuery사용을 위한 코드-->

<!--팝업1-->
<div class="popup-1 popup">
  <div class="popup__content">
  <!--부모 .popup클래스는 배경색을 흐리게 만드느데 사용하고 popup__content를 만들어
새로 팝업창을 만든다.-->
    <!--팝업 헤더-->
    <div class="popup__head">
      <div class="popup__btn-close"></div>
    </div>
    <!--팝업 내용-->
    <div class="popup__body">
      <div class="con">
        Lorem ...
      </div>
    </div>
  </div>
</div>

<!-- 팝업2 -->
<div class="popup-2 popup">
  <div class="popup__content">
    <div class="popup__head">
      <div class="popup__btn-close"></div>
    </div>
    <div class="popup__body">
      <div class="con">
        팝업2
      </div>
    </div>
  </div>
</div>

<section class="section-1">
  <div class="con">
    <!--팝업 생성 버튼-->
    <button class="btn-popup-1">팝업 1</button>
    Lorem ipsum...
  </div>
</section>



<section class="section-1">
  <div class="con">
    <button class="btn-popup-1">팝업 1</button>
    <button class="btn-popup-2">팝업 2</button>
    Lorem... 
  </div>
</section>

css

/*노말라이즈*/
body, ul, li {
  margin:0;
  padding:0;
  list-style:none;
}

a {
  color:inherit;
  text-decoration:none;
}

/*컨텐츠 너비만들고 가운데로 옮겨 양 옆 여백만들기*/
.con {
  margin-left:auto;
  margin-right:auto;
}

.con {
  max-width:1200px;
}

.popup {
  position:fixed;
  top:0;
  left:0;
  right:0;
  bottom:0;
  background-color:rgba(0,0,0,0.5);
  /*웹을 가득 채우고 배경색을 흐린 검정색으로 만든다.*/
  align-items:center;
  justify-content:center;
  display:flex;
  /*display를 flex로 만들어 팝업창(.popup__content)를 정가운데로 옮긴다.*/
  opacity:0;
  visibility:hidden;
  /*불투명도를 0으로 만들어 평소에 보이지 않게 만들고 visivility로 숨긴다. .active클래스가 추가되면 나타나게 한다.*/
  transition: opacity .3s, visibility .3s;
  /*opacity와 visibility에 재생시간을 부여한다.*/
}

.popup.active {
  opacity:1;
  visibility:visible;
  /*팝업을 다시 나타나게 하는 클래스를 만든다.*/
}

.popup__content {
  min-width:200px;
  min-height:200px;
  /*최소 너비, 높이 지정*/
  background-color:white;
  border:2px solid black;
  transform:translateY(-100%);
  /*평소에는 팝업창이 위에 있게 만들고 .active클래스 추가로 가운데 오게 만든다.*/
  transition: transform .3s;
  /*transform에 재생시간을 부여한다.*/
}

/*.popup과 .active클래스를 모두 가지고 있는 태그의 후손이면서
.popup__content를 가지고 있는 태그에게 적용하는 속성*/
/*원래는 .popup이 .active클래스를 가지고 있지 않으므로 이 속성이 활성화
되지 않지만 JS를 이용해 .popup이 .active클래스를 갖는 순간 활성화된다.*/
/*단순히 .active클래스를 라이브러리처럼 사용하는 것이 아니라 관련된 클래스를 만들어 
클래스를 추가하는 것만으로 여러 css속성이 추가되도록 구현한 것!!*/
.popup.active .popup__content {
  transform:translateY(0);
  /*다시 원래 자리로 오게하는 클래스를 만든다.*/
}

.popup__head {
  padding:10px;
}

.popup__btn-close {
  width:30px;
  height:30px;
  /*X표를 만들기위해 네모 틀을 만든다.*/
  margin-left:auto;
  /*.popup__head의 오른쪽에 붙인다.*/
  position:relative;
  /*before, after태그를 absolute로 하고 이 태그를 유령의 집으로 만든다.*/
  cursor:pointer;
  transition:transform 0.3s;
  /*transform(rotate)에 재생시간을 부여한다. 돌아가는 애니매이션 구현*/
}

.popup__btn-close:hover {
  transform:rotate(185deg);
  /*hover시 185도 돌아간다.*/
}

.popup__btn-close::before,
.popup__btn-close::after {
  content:"";
  background-color:black;
  position:absolute;
  top:40%;
  left:0;
  width:100%;
  height:20%;
  transform:rotate(45deg);
  /*before, after태그를 막대기처럼 만들어 하나는 45도 하나는 -45도 기울여
  X표처럼 만든다.*/
  transition:box-shadow 0.3s;
  /*box-shadow에 재생시간을 부여한다.*/
  
}

.popup__btn-close::after {
  transform:rotate(-45deg);
}

.popup__btn-close:hover::before,
.popup__btn-close:hover::after {
  box-shadow:0 0 3px black;
  /*hover시 그림자가 생기도록 한다.*/
}

.popup__body {
  padding:0 10px;
  /*팝업 내용에 양엽 padding값 부여*/
}

JS

console.clear();

//popup-1을 열고 닫는 함수
function Popup1__init() {
  $('.btn-popup-1').click/*.btn-popup-1을 클릭하면*/(function() {
    $('.popup-1').addClass('active');/*popup-1를 가진 태그에 active클래스를 추가한다.*/
  });
  $('.popup-1 .popup__btn-close')/*popup-1클래스를 가진 태그의 후손인 .popup__btn-close를 클릭하면*/.click(function() {
    $('.popup-1').removeClass('active');/*popup-1를 가진 태그에게서 active클래스를 제거한다.*/
  });
}

Popup1__init();

//popup-2을 열고 닫는 함수
function Popup2__init() {
  $('.btn-popup-2').click/*.btn-popup-2을 클릭하면*/(function() {
    $('.popup-2').addClass('active');/*popup-2를 가진 태그에 active클래스를 추가한다.*/
  });
  $('.popup-2 .popup__btn-close')/*popup-2클래스를 가진 태그의 후손인 .popup__btn-close를 클릭하면*/.click(function() {
    $('.popup-2').removeClass('active');/*popup-2를 가진 태그에게서 active클래스를 제거한다.*/
  });
}

Popup2__init();

CSS코드는 동일하고 JS코드를 보면 두 함수는 서로 구별하기 위해 부여한 .popup-뒤의 숫자를 제외하면 코드가 동일하다. 이것을 이용해서 숫자 부분을 매개변수로 사용해 두 함수를 합쳐보자.

function Popup__init(no){
  $('.btn-popup-' + no).click(function (){
    $('.popup-' + no).addClass('active');
  });
  $('.popup-' + no + ' .popup__btn-close').click(function(){
  $('.popup-' + no).removeClass('active');
  });
}

Popup__init(1);
Popup__init(2);

팝업창 외 부분을 클릭해도 팝업이 꺼지도록 설정

이번에는 팝업창을 제외한 부분을 클릭하면 팝업이 꺼지는 것을 구현해보자. stopPropagation을 이용해야 하는데 .popup을 클릭하면 창이 꺼지도록하되 창 안을 누르면 꺼지면 안되기에 팝업창 부분인 .popup__content는 이벤트를 전파 방지로 해두면 된다.

function Popup__init(no){
  $('.btn-popup-' + no).click(function (){
    $('.popup-' + no).addClass('active');
  });
  $('.popup-' + no + ',.popup-' + no + ' .popup__btn-close').click(function(){
  $('.popup-' + no).removeClass('active');
  });
  
  $('.popup-' + no + ' .popup__content').click(function(e){
  e.stopPropagation();
  });
  /*
  또는
  $('.popup-' + no + ' .popup__content').click(function(){
  return false;
  });
  */
}

Popup__init(1);
Popup__init(2);


팝업창 스크롤바 유동적으로 생기게 하기

위 예시처럼 사용자가 웹의 크기를 줄여서 팝업의 내용을 다 담을 수 없을 때, 자동으로 내용을 담은 곳 팝업의 body부분에 스크롤 바가 생기는 것을 구현해보자.
추가해준 코드(css)

.popup__body {
  max-height:calc(100vh - 54px);
  /*
  여기서 팝업 바디의 최대 높이는 전체 웹의 높이에서 
  팝업 헤더의 높이를 제외해야하므로 전체 웹 높이인 100vh에
  .popup__btn-close { height:30px; }
  .popup__head { padding:10px; }
  .popup__content { border:2px solid black; }
  30 + 10 * 2(위 아래 10px씩) + 2 * 2(위 아래 2px씩) = 54px을
  뺀 값으로 한다.
  */
  overflow-y:auto;
  /*body의 높이가 100vh - 54px를 넘는 순간부터 자동으로 y축 스크롤이
  생기도록*/
  padding:0 10px;
  /*양 옆 여백 만들기*/
}


팝업이 나오는 동안 html수준의 스크롤 바는 나오지 않도록 설정

추가해준 코드
css

.overflow-hidden{
  overflow-y:hidden;
}

JS 함수 수정

console.clear();

function Popup__init(no) {
  $('.btn-popup-' + no).click(function() {
    $('.popup-' + no).addClass('active');
    $('html').addClass('overflow-hidden');
    /*.btn-popup-(no)(팝업(no) 버튼)을 클릭하면 html태그에
    스크롤 바를 숨기는 클래스를 추가한다.*/
  });
  
  $('.popup-' + no + ' .popup__btn-close, .popup-' + no).click(function() {
    $('.popup-' + no).removeClass('active');
    $('html').removeClass('overflow-hidden');
    /*.popup-(no)(팝업창 안 X버튼)을 클릭하면 html태그에게서
    스크롤 바를 숨기는 클래스를 제거한다.*/
  });
  
  $('.popup-' + no + ' .popup__content').click(function() {
    return false;
  });
}
Popup__init(1);
Popup__init(2);


함수를 나누어 웹을 열면 팝업이 열려있는 상태로 설정

웹을 열면 팝업이 이미 열려있는 상태로 만들어보자. 원래의 JS함수에서 함수를 나누어서 여는 함수만 다시 작동해주면 된다.
원래 함수

console.clear();

function Popup__init(no) {
  $('.btn-popup-' + no).click(function() {
    /*---------------Popup__show(no);-------------*/
    $('.popup-' + no).addClass('active');
    $('html').addClass('popup-' + no + '-actived');
    /*--------------------------------------------*/
  });
  
  $('.popup-' + no + ' .popup__btn-close, .popup-' + no).click(function() {
    /*---------------Popup__hide(no);-------------*/
    $('.popup-' + no).removeClass('active');
    $('html').removeClass('popup-' + no + '-actived');
    /*--------------------------------------------*/
  });
  
  $('.popup-' + no + ' .popup__content').click(function() {
    return false;
  });
}
Popup__init(1);
Popup__init(2);

수정한 함수

console.clear();

function Popup__init(no) {
  $('.btn-popup-' + no).click(function() {
    Popup__show(no);
  });
  
  $('.popup-' + no + ' .popup__btn-close, .popup-' + no).click(function() {
    Popup__hide(no);
  });
  
  $('.popup-' + no + ' .popup__content').click(function() {
    return false;
  });
}

function Popup__show(no) {
  $('.popup-' + no).addClass('active');
  $('html').addClass('popup-' + no + '-actived');
}

function Popup__hide(no) {
  $('.popup-' + no).removeClass('active');
  $('html').removeClass('popup-' + no + '-actived');
}

Popup__init(1);
Popup__init(2);

Popup__show(1);
Popup__show(2);

profile
🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳

0개의 댓글