이번 포스팅에서는 모바일웹 환경을 위한 밑에서 위로 올라오는 모달창인 바텀시트 팝업에 대해 만들어보는 시간을 가져보겠습니다.
모달 창은 UI 의 중요한 요소로, 사용자의 주의를 필요로 하는 정보를 표시하기 위해 현재 페이지 위에 오버레이되는 방식으로
나타납니다. 다양한 목적과 상황에 맞게 여러 종류의 모달 창을 사용할 수 있습니다.
모달의 종류에는 팝업모달(Popup Modal), 바텀시트(Bottom Sheet ) , 다이얼로그 (Dialog) , 드로어 (Drawer) 로 크게
나눠볼 수 있는데 이번 만들기 시리즈에서는 바텀시트 모달 을 제공합니다.
또한, 이번 만들기 시리즈에서는 기본 예제 뿐 아니라, 효과 및 광고 배너 를 추가하려고 합니다.
추후 포스팅 에 다이얼로그, 드로어 등 다양한 모달창을 만들어서 제공하도록 하겠습니다.
모바일 환경에서 만들기 시리즈 다른 글
[개발 같이해요/HTML&CSS] - [ CSS ] 모바일 환경을 위한 CSS 햄버거 메뉴 만들기
[개발 같이해요/HTML&CSS] - [ CSS ] 모바일 환경을 위한 스크롤애니메이션 만들기
[개발 같이해요/HTML&CSS] - [ CSS ] 모바일 환경을 위한 다크모드 토글 만들기
[개발 같이해요/HTML&CSS] - [ CSS ] 모바일 환경을 위한 모달창 만들기 - 팝업모달
# 1. 완성된 바텀시트 모달 화면
# 2. 기본 폴더 구조
BOTTOMSHEETMODAL 폴더 구조 입니다.
├── ad-banner.jpg
├── bsmodal.html
├── css/
│ └── style.css
└── js/
└── script.js
# 3. HTML 소스 구조
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>바텀시트 모달</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<button id="openModal">모달 열기</button>
<div id="modal" class="modal">
<div class="modal-content">
<span id="closeModal" class="close">×</span>
<!-- 위쪽 영역: 축하 메시지 -->
<div class="modal-header">
<div id="fireworksContainer"></div> <!-- 폭죽 효과 컨테이너 -->
<h2>축하합니다!</h2>
</div>
<!-- 아래쪽 영역: 광고 배너 -->
<div class="modal-body">
<img src="ad-banner.jpg" alt="광고 배너" style="width:80%;">
</div>
</div>
</div>
<script src="js/script.js"></script>
</body>
</html>
모달 헤더에 폭죽효과 , 모달 바디 에 광고 이미지 를 추가하는 코드 입니다.
# 4. CSS 소스 구조
/* 기본 버튼 스타일 */
button {
background-color: #ff9800; /* 주황색 배경 */
color: white; /* 흰색 텍스트 */
padding: 10px 20px; /* 패딩 */
border: none; /* 테두리 없음 */
cursor: pointer; /* 커서 포인터 */
border-radius: 4px; /* 둥근 모서리 */
font-size: 16px; /* 폰트 크기 */
}
/* 버튼 호버 효과 */
button:hover {
background-color: #e68a00; /* 호버 시 색상 변경 */
}
/* 기본 모달 스타일 */
.modal {
display: none; /* 기본적으로 숨김 */
position: fixed; /* 화면에 고정 */
left: 0;
bottom: 0; /* 하단에 위치 */
width: 100%; /* 화면 너비에 맞춤 */
background-color: white;
box-shadow: 0 -5px 10px rgba(0,0,0,0.2); /* 상단 그림자 효과 */
transition: transform 0.3s ease-out; /* 부드러운 애니메이션 효과 */
border-top-left-radius: 20px; /* 상단 왼쪽 모서리 */
border-top-right-radius: 20px; /* 상단 오른쪽 모서리 */
}
/* 모달 바디 스타일 */
.modal-content {
padding: 16px;
text-align: center;
}
/* 모달 바디 (광고 영역) 스타일 */
.modal-body img {
width: 50%; /* 이미지가 모달 너비에 맞게 조정 */
height: auto; /* 이미지 비율 유지 */
}
/* 닫기 버튼 스타일 */
.close {
float: right;
font-size: 28px;
}
.close:hover,
.close:focus {
cursor: pointer;
}
/* 모달 헤더 스타일 */
.modal-header {
position: relative; /* 폭죽효과 가 이 영역 내에서만 떨어지도록 설정 */
overflow: hidden; /* 영역 밖으로 나가는 폭죽 숨기기 */
margin-bottom: 20px; /* 헤더와 바디 사이 간격 */
}
/* 폭죽 효과 스타일 */
#fireworksContainer {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none; /* 마우스 이벤트 무시 */
display: flex;
justify-content: center;
align-items: center;
overflow: hidden; /* 컨테이너 밖으로 나간 애니메이션 숨김 */
}
# 5. JAVASCRIPT 소스 구조
자바스크립트 코드는 주석으로 설명해놓도록 하겠습니다.
궁금하신점 있으시면 댓글 달아주세요.
// 요소 선택
const modal = document.getElementById("modal");
const openBtn = document.getElementById("openModal");
const closeBtn = document.getElementById("closeModal");
// 모달 열기 이벤트 리스너
openBtn.addEventListener("click", () => {
modal.style.display = "block";
modal.style.transform = "translateY(0)"; // 위에서 아래로 슬라이드
});
// 모달 닫기 이벤트 리스너
closeBtn.addEventListener("click", () => {
modal.style.transform = "translateY(100%)"; // 아래로 슬라이드하며 닫힘
setTimeout(() => modal.style.display = "none", 300); // 애니메이션 후 숨김
createFirework();
});
// 모달 외부 클릭 시 닫기
window.addEventListener("click", (event) => {
if (event.target == modal) {
modal.style.transform = "translateY(100%)";
setTimeout(() => modal.style.display = "none", 300);
}
});
document.addEventListener('DOMContentLoaded', function() {
setInterval(createFirework, 3000); // 3초마다 폭죽 효과를 반복합니다.
});
function createFirework() {
const fireworksContainer = document.getElementById('fireworksContainer');
if (!fireworksContainer) return; // 폭죽 컨테이너가 없으면 함수 종료
// 기존에 폭죽 조각들이 남아있다면 제거
while (fireworksContainer.firstChild) {
fireworksContainer.removeChild(fireworksContainer.firstChild);
}
for (let i = 0; i < 20; i++) { // 폭죽 조각 개수
const firework = document.createElement('div');
firework.style.position = 'absolute';
firework.style.width = '5px';
firework.style.height = '5px';
firework.style.backgroundColor = getRandomColor(); // 무작위 색상
firework.style.borderRadius = '50%';
firework.style.left = '50%';
firework.style.top = '50%';
const angle = Math.random() * 360;
const distance = Math.random() * 100 + 50; // 폭죽 조각이 퍼지는 거리
fireworksContainer.appendChild(firework);
// 애니메이션 정의 및 실행
firework.animate([
{ transform: `translate(-50%, -50%)` },
{ transform: `rotate(${angle}deg) translateX(${distance}px)` }
], {
duration: 800 + Math.random() * 200, // 지속 시간
easing: 'ease-out', // 속도 곡선
fill: 'forwards' // 애니메이션 종료 상태 유지
});
firework.animate([
{ opacity: 1 },
{ opacity: 0 }
], {
duration: 1000,
delay: 500,
fill: 'forwards'
});
}
}
function getRandomColor() {
const letters = '0123456789ABCDEF';
let color = '#';
for (let i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
# 6.마무리
이번 포스팅에서는 모바일환경에서 요즘 많이 쓰이는 바텀시트 팝업 모달 을 구현해보았습니다.
모바일 환경에서의 웹 개발은 사용자 경험(UX)을 최우선으로 고려해야 합니다. 오늘 구현한 바텀시트 팝업모달은 카카오페이지 등에서 요즘 자주 보이는 UI/UX 입니다. 주로 광고배너 를 많이 띄우는 용도로 활용합니다.
다음 포스팅에서도 모바일 환경을 위한 다양한 효과를 만드는 작업을 해보도록 하겠습니다.