티스토리 뷰
![]() |
![]() |
| 슬라이드 자동 재생 코드 | 슬라이드 자동 재생 코드_재생정지버튼추가 |
![]() |
![]() |
| 슬라이드 자동 재생 코드_재생정지버튼추가_페이지 | 슬라이드 자동 재생 코드 _재생정지버튼추가_페이지_인디케이터 |
![]() |
|
| 슬라이드 자동 재생 코드 _재생정지버튼추가_페이지_인디케이터 반응형 | |
슬라이드 자동 재생 코드.html
슬라이드 자동 재생 코드_재생정지버튼추가.html
슬라이드 자동 재생 코드_재생정지버튼추가.html
0.00MB
슬라이드 자동 재생 코드_재생정지버튼추가_페이지.html
슬라이드 자동 재생 코드_재생정지버튼추가_페이지.html
0.00MB
슬라이드 자동 재생 코드_재생정지버튼추가_페이지_인디케이터.html
슬라이드 자동 재생 코드_재생정지버튼추가_페이지_인디케이터.html
0.01MB
슬라이드 자동 재생 코드_재생정지버튼추가_페이지_인디케이터_반응형.html
슬라이드 자동 재생 코드_재생정지버튼추가_페이지_인디케이터_반응형.html
0.01MB
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>반응형 인디케이터 슬라이더</title>
<style>
/* 1. 반응형 레이아웃 설정 */
.slider-container {
width: 90%; /* 모바일에서도 여백이 있도록 비율 설정 */
max-width: 800px; /* 최대 너비 제한 */
aspect-ratio: 16 / 9; /* 이미지 비율 고정 (반응형의 핵심) */
margin: 50px auto;
overflow: hidden;
position: relative;
border-radius: 12px;
background: #eee;
}
.slide-track {
display: flex;
transition: transform 0.5s ease-in-out;
height: 100%;
}
.slide-track img {
flex: 0 0 100%; /* 부모 너비의 100%를 꽉 채움 */
width: 100%;
height: 100%;
object-fit: cover;
}
/* 버튼 및 컨트롤러는 이전과 동일하되, 모바일 배려 */
.nav-btn {
position: absolute; top: 50%; transform: translateY(-50%);
background: rgba(0,0,0,0.3); color: #fff; border: none;
padding: 10px; cursor: pointer; border-radius: 50%; width: 40px; height: 40px; z-index: 10;
}
.prev-btn { left: 10px; }
.next-btn { right: 10px; }
.control-panel {
position: absolute; bottom: 15px; left: 50%; transform: translateX(-50%);
display: flex; align-items: center; gap: 10px;
background: rgba(0,0,0,0.5); padding: 8px 15px; border-radius: 20px;
color: #fff; font-size: 12px; z-index: 10; white-space: nowrap;
}
.indicator-group { display: flex; gap: 8px; }
.dot {
width: 8px; height: 8px; background: rgba(255,255,255,0.4);
border-radius: 50%; cursor: pointer; border: none; padding: 0;
}
.dot.active { background: #fff; transform: scale(1.2); }
.play-pause-btn {
background: none; border: none; color: #fff; cursor: pointer;
font-weight: bold; border-left: 1px solid rgba(255,255,255,0.3);
padding-left: 10px; margin-left: 5px;
}
/* 모바일용 스타일 조정 */
@media (max-width: 480px) {
.nav-btn { width: 30px; height: 30px; padding: 5px; font-size: 12px; }
.control-panel { padding: 5px 10px; font-size: 10px; }
}
</style>
</head>
<body>
<div class="slider-container" id="sliderMain">
<div class="slide-track" id="track">
<img src="https://picsum.photos/id/10/800/450" alt="1">
<img src="https://picsum.photos/id/20/800/450" alt="2">
<img src="https://picsum.photos/id/30/800/450" alt="3">
</div>
<button class="nav-btn prev-btn" id="prevBtn">❮</button>
<button class="nav-btn next-btn" id="nextBtn">❯</button>
<div class="control-panel">
<div class="indicator-group" id="indicatorGroup">
<button class="dot active"></button>
<button class="dot"></button>
<button class="dot"></button>
</div>
<div class="page-num" id="pageNum">1 / 3</div>
<button class="play-pause-btn" id="playPauseBtn">PAUSE</button>
</div>
</div>
<script>
const sliderMain = document.getElementById('sliderMain');
const track = document.getElementById('track');
const nextBtn = document.getElementById('nextBtn');
const prevBtn = document.getElementById('prevBtn');
const playPauseBtn = document.getElementById('playPauseBtn');
const pageNum = document.getElementById('pageNum');
const dots = document.querySelectorAll('.dot');
let index = 0;
const totalSlides = dots.length;
let slideTimer;
let isPlaying = true;
// [반응형 핵심] 현재 슬라이더의 너비를 계산하는 함수
function updateUI() {
const sliderWidth = sliderMain.clientWidth; // 고정값이 아닌 현재 너비를 가져옴
track.style.transform = `translateX(-${index * sliderWidth}px)`;
pageNum.textContent = `${index + 1} / ${totalSlides}`;
dots.forEach((dot, i) => dot.classList.toggle('active', i === index));
}
// 브라우저 크기가 변할 때(resize) 슬라이더 위치를 재조정
window.addEventListener('resize', updateUI);
function nextSlide() {
index = (index < totalSlides - 1) ? index + 1 : 0;
updateUI();
}
function prevSlide() {
index = (index > 0) ? index - 1 : totalSlides - 1;
updateUI();
}
nextBtn.addEventListener('click', nextSlide);
prevBtn.addEventListener('click', prevSlide);
dots.forEach((dot, i) => {
dot.addEventListener('click', () => {
index = i;
updateUI();
});
});
function startAutoPlay() {
if (!slideTimer) slideTimer = setInterval(nextSlide, 3000);
}
function stopAutoPlay() {
clearInterval(slideTimer);
slideTimer = null;
}
playPauseBtn.addEventListener('click', () => {
if (isPlaying) {
stopAutoPlay();
playPauseBtn.textContent = 'PLAY';
} else {
startAutoPlay();
playPauseBtn.textContent = 'PAUSE';
}
isPlaying = !isPlaying;
});
startAutoPlay();
updateUI(); // 초기 위치 설정
</script>
</body>
</html>
※ 해당 내용은 Google Gmini3.0에서 작성되었습니다.
'WEB > JavaScript' 카테고리의 다른 글
| [JavaScript] 비밀번호가 8자 이상이고 특수문자가 포함여부 체크하기 (0) | 2026.01.03 |
|---|---|
| [JavaScript] 이메일 형식 체크 정규표현식 (0) | 2026.01.03 |
| [JavaScript] 자주하는 질문 FAQ 아코디언 메뉴 (0) | 2026.01.03 |
| [JavaScript] 탭메뉴, 아코디언, 모달 (0) | 2026.01.03 |
| [JavaScript] 모달 팝업 (0) | 2026.01.03 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- echart
- 연명의료결정제도 #사전연명의료의향서 #사전연명의료의향서등록기관 #광주사전연명의료의향서
- 좋은책
- 와이파이신호 #와이파이 #와이파이신호세게
- SQL명령어 #SQL
- thymeleaf
- 광주분식 #광주분식맛집 #상추튀김 #상추튀김맛집 #광주상추튀김
- 자바스크립트정규표현식
- 무료폰트 #무료웹폰트 #한수원한돋움 #한수원한울림 #한울림체 #한돋움체
- 증폭기 #아이피타임증폭기
- iptime와이파이증폭기 #와이파이증폭기설치
- lg그램pro #lg그램 #노트북 #노트북추천 #lg노트북
- 좋은책 #밥프록터 #부의원리
- jdk #jre
- 와이파이증폭기추천 #와이파이설치
- 자바스크립트 #javascript #math
- 정보처리기사 #정보처리기사요약 #정보처리기사요점정리
- 바지락칼국수 #월곡동칼국수 #칼국수맛집
- 테스크탑무선랜카드 #무선랜카드 #아이피타이무선랜카드 #a3000mini #무선랜카드추천
- 쇼팬하우어 #좋은책
- ajax
- 탭메뉴자바스크립트
- 자바스크립트break
- 썬크림 #닥터지썬크림 #내돈내산 #내돈내산썬크림 #썬크림추천 #spf50썬크림 #닥터지메디유브이울트라선
- sw기술자평균임금 #2025년 sw기술자 평균임금
- jQuery #jQuery이미지슬라이드 #이미지슬라이드
- 자바스크립트countiue
- css미디어쿼리 #미디어쿼리 #mediaquery
- 파비콘 #파비콘 사이트에 적용
- 파비콘사이즈
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |
글 보관함





