티스토리 뷰

<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>JS UI Components 실습</title>
<style>
/* 기본 스타일 */
body { font-family: sans-serif; line-height: 1.6; padding: 20px; color: #333; }
section { margin-bottom: 50px; border-bottom: 1px solid #eee; padding-bottom: 30px; }
h2 { color: #007bff; }
/* 1. 탭 메뉴 스타일 */
.tab-btn-group { display: flex; gap: 10px; margin-bottom: 15px; }
.tab-btn { padding: 10px 20px; cursor: pointer; border: 1px solid #ddd; background: #fff; }
.tab-btn.active { background: #007bff; color: #fff; border-color: #007bff; }
.tab-content { display: none; padding: 20px; border: 1px solid #ddd; }
.tab-content.active { display: block; }
/* 2. 아코디언 스타일 */
.acc-item { border: 1px solid #ddd; margin-bottom: 5px; border-radius: 4px; overflow: hidden; }
.acc-btn { width: 100%; padding: 15px; text-align: left; background: #f8f9fa; border: none; cursor: pointer; font-weight: bold; }
.acc-btn:hover { background: #e2e6ea; }
.acc-content { max-height: 0; overflow: hidden; transition: max-height 0.3s ease-out; background: #fff; }
.acc-inner { padding: 15px; border-top: 1px solid #eee; }
/* 3. 모달 스타일 */
.gallery { display: flex; gap: 10px; }
.gallery img { width: 150px; cursor: pointer; border-radius: 8px; transition: transform 0.2s; }
.gallery img:hover { transform: scale(1.05); }
.modal-overlay {
position: fixed; top: 0; left: 0; width: 100%; height: 100%;
background: rgba(0,0,0,0.8); display: none; align-items: center; justify-content: center;
}
.modal-overlay.active { display: flex; }
.modal-content { position: relative; max-width: 80%; }
.modal-content img { width: 100%; border-radius: 10px; }
.close-btn {
position: absolute; top: -40px; right: 0; color: #fff;
font-size: 30px; cursor: pointer;
}
</style>
</head>
<body>
<section>
<h2>1. 탭 메뉴</h2>
<div class="tab-btn-group">
<button class="tab-btn active">메뉴 A</button>
<button class="tab-btn">메뉴 B</button>
</div>
<div class="tab-content-group">
<div class="tab-content active">첫 번째 탭의 내용입니다.</div>
<div class="tab-content">두 번째 탭의 내용입니다.</div>
</div>
</section>
<section>
<h2>2. 아코디언</h2>
<div class="acc-item">
<button class="acc-btn">Q1. 자바스크립트가 어렵나요?</button>
<div class="acc-content">
<div class="acc-inner">네, 하지만 직접 짜보면 재미있습니다!</div>
</div>
</div>
<div class="acc-item">
<button class="acc-btn">Q2. 퍼블리셔도 로직을 알아야 하나요?</button>
<div class="acc-content">
<div class="acc-inner">그럼요! 유지보수와 소통에 큰 도움이 됩니다.</div>
</div>
</div>
</section>
<section>
<h2>3. 모달 팝업 (갤러리)</h2>
<div class="gallery">
<img src="https://picsum.photos/id/10/400/300" alt="이미지1">
<img src="https://picsum.photos/id/20/400/300" alt="이미지2">
</div>
<div class="modal-overlay" id="modalOverlay">
<div class="modal-content">
<span class="close-btn">×</span>
<img src="" alt="확대 이미지" id="modalImg">
</div>
</div>
</section>
<script>
/**
* 1. 탭 메뉴 로직
*/
const tabBtns = document.querySelectorAll('.tab-btn');
const tabContents = document.querySelectorAll('.tab-content');
tabBtns.forEach((btn, index) => {
btn.addEventListener('click', () => {
// 초기화
tabBtns.forEach(b => b.classList.remove('active'));
tabContents.forEach(c => c.classList.remove('active'));
// 활성화
btn.classList.add('active');
tabContents[index].classList.add('active');
});
});
/**
* 2. 아코디언 로직
*/
const accBtns = document.querySelectorAll('.acc-btn');
accBtns.forEach(btn => {
btn.addEventListener('click', function() {
const content = this.nextElementSibling;
// toggle 처럼 동작하게 함
if (content.style.maxHeight && content.style.maxHeight !== '0px') {
content.style.maxHeight = '0px';
} else {
// 열기 전 모든 아코디언 닫기 (선택사항)
// document.querySelectorAll('.acc-content').forEach(c => c.style.maxHeight = '0px');
content.style.maxHeight = content.scrollHeight + 'px';
}
});
});
/**
* 3. 모달 로직
*/
const galleryImgs = document.querySelectorAll('.gallery img');
const modal = document.getElementById('modalOverlay');
const modalImg = document.getElementById('modalImg');
const closeBtn = document.querySelector('.close-btn');
// 이미지 클릭 시 열기
galleryImgs.forEach(img => {
img.addEventListener('click', () => {
const src = img.getAttribute('src');
modalImg.setAttribute('src', src);
modal.classList.add('active');
});
});
// 닫기 버튼 클릭 시
closeBtn.addEventListener('click', () => modal.classList.remove('active'));
// 배경 클릭 시 닫기
modal.addEventListener('click', () => modal.classList.remove('active'));
// 버블링 방지 (이미지 클릭 시엔 안 닫히게)
modalImg.addEventListener('click', (e) => e.stopPropagation());
</script>
</body>
</html>
※ 해당 내용은 Google Gmini3.0에서 작성되었습니다.
'WEB > JavaScript' 카테고리의 다른 글
| [JavaScript] 이메일 형식 체크 정규표현식 (0) | 2026.01.03 |
|---|---|
| [JavaScript] 자주하는 질문 FAQ 아코디언 메뉴 (0) | 2026.01.03 |
| [JavaScript] 모달 팝업 (0) | 2026.01.03 |
| [JavaScript] 아코디언 코드 (0) | 2026.01.03 |
| [JavaScript] 공지사항 더보기 데이터 가져오기 (0) | 2026.01.03 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 연명의료결정제도 #사전연명의료의향서 #사전연명의료의향서등록기관 #광주사전연명의료의향서
- 무료폰트 #무료웹폰트 #한수원한돋움 #한수원한울림 #한울림체 #한돋움체
- 광주분식 #광주분식맛집 #상추튀김 #상추튀김맛집 #광주상추튀김
- echart
- thymeleaf
- 파비콘 #파비콘 사이트에 적용
- 바지락칼국수 #월곡동칼국수 #칼국수맛집
- 증폭기 #아이피타임증폭기
- 와이파이신호 #와이파이 #와이파이신호세게
- 자바스크립트countiue
- 쇼팬하우어 #좋은책
- jdk #jre
- lg그램pro #lg그램 #노트북 #노트북추천 #lg노트북
- ajax
- 자바스크립트정규표현식
- jQuery #jQuery이미지슬라이드 #이미지슬라이드
- 탭메뉴자바스크립트
- 와이파이증폭기추천 #와이파이설치
- 자바스크립트break
- 썬크림 #닥터지썬크림 #내돈내산 #내돈내산썬크림 #썬크림추천 #spf50썬크림 #닥터지메디유브이울트라선
- 테스크탑무선랜카드 #무선랜카드 #아이피타이무선랜카드 #a3000mini #무선랜카드추천
- iptime와이파이증폭기 #와이파이증폭기설치
- 정보처리기사 #정보처리기사요약 #정보처리기사요점정리
- 파비콘사이즈
- 좋은책 #밥프록터 #부의원리
- SQL명령어 #SQL
- 좋은책
- css미디어쿼리 #미디어쿼리 #mediaquery
- 자바스크립트 #javascript #math
- sw기술자평균임금 #2025년 sw기술자 평균임금
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | ||||
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 25 | 26 | 27 | 28 | 29 | 30 | 31 |
글 보관함
