Vue.js 3 & NodeJS/Vue 3

Vue CLI 부트스크랩 5 캐러셀 - Vue CLI Bootstrap 5, Carousel, carousel-item, carousel-control, Indicator

carrotweb 2022. 3. 13. 20:36
728x90
반응형

메인 페이지의 상단 영역을 Bootstrap의 Carousel(캐러셀)을 사용하여 가로로 슬라이드 시켜 여러 개의 상단 영역이 반복해서 나타나게 구성하겠습니다.

Bootstrap의 Carousel(캐러셀)은 CSS3과 JavaScript로 이미지나 텍스트 또는 콘텐츠 영역을 슬라이드 시키고 이전과 다음으로 이동시키기 위한 컨트롤과 위치를 표시하기 위해 Indicator(인디게이터)를 지원합니다.

Bootstrap의 Carousel(캐러셀) 구성은 다음과 같습니다.

<div id="mainTopCarousel" class="carousel slide" data-bs-ride="carousel">
	<div class="carousel-inner">
		<div class="carousel-item active">
			First Slide
		</div>
		<div class="carousel-item">
			Second Slide
		</div>
	</div>
</div>

.carousel class와 .slide class가 적용된 <div> 태그는 Carousel(캐러셀)의 전체 영역입니다. 그리고 data-bs-ride 속성을 통해 Bootstrap에 포함된 JavaScript에서 슬라이드가 동작되게 됩니다. data-bs-ride 속성이 없으면 슬라이드나 컨트롤이 되지 않습니다.

.carousel-inner class가 적용된 <div> 태그에는 슬라이드가 되는 콘텐츠 영역(.carousel-item가 적용된 <div> 태그)이 하나 이상 포함되어야 합니다. 두 개 이상일 때 슬라이드가 동작됩니다.

.carousel-item class가 적용된 <div> 태그 중에서 반드시 하나의 <div>에는 .active class가 적용되어야 합니다. 그렇지 않으면 슬라이드가 되는 콘텐츠 영역이 나타나지 않습니다.

자세한 내용은 Bootstrap의 Carousel(https://getbootstrap.com/docs/5.1/components/carousel/)를 참조하세요.

먼저 콘솔을 실행하고 Vue 프로젝트가 있는 C:\workspaces\nodeserver\testvue 폴더로 이동합니다. 그리고 콘솔에서 npm run 명령어를 실행합니다.

npm run serve

 

 

메인 페이지 기본 상단 영역 슬라이딩(캐러셀) 만들기

1. C:\workspaces\nodeserver\testvue\src\views\Home.vue 파일을 오픈합니다.

<template> 태그에 Bootstrap의 Carousel(캐러셀)를 추가합니다.

<template>
	<div id="mainTopCarousel" class="carousel slide" data-bs-ride="carousel">
		<div class="carousel-inner">
			<div class="carousel-item active">
				First Slide
			</div>
			<div class="carousel-item">
				Second Slide
			</div>
		</div>
	</div>
	<div class="main-top-promotion">
		<video class="main-top-promotion-video" autoplay="autoplay" loop="loop" muted="muted">
			<source src="../assets/AdobeStock_197561178_AdobeCreativeCloudExpress.mp4" type="video/mp4">
		</video>
		<div class="container">
			<div class="row align-items-center">
				<div class="col-sm-12 col-md-6 text-md-start">
					<div class="py-3 py-md-5">
						<h1 class="text-white fw-bold">
							Welcome to Your <br>Vue.JS Application
						</h1>
						<p class="text-white mb-4 fs-5">
							당신의 이야기가 세상을 바꿉니다.
						</p>
						<router-link :to="{name:'BoardWrite'}" class="btn btn-success">나의 이야기 쓰기</router-link>
					</div>
				</div>
			</div>
		</div>
	</div>
	<div class="home">
		<img alt="Vue logo" src="../assets/logo.png">
		<HelloWorld msg="Welcome to Your Vue.js App"/>
	</div>
</template>
 
 
상단에 영역이 추가되고 5초마다 슬라이드 되는 것을 확인할 수 있습니다.

 

2. First Slide으로 메인 상단 영역을 이동시킵니다.

<template>
	<div id="mainTopCarousel" class="carousel slide" data-bs-ride="carousel">
		<div class="carousel-inner">
			<div class="carousel-item active">
				<div class="main-top-promotion">
					<video class="main-top-promotion-video" autoplay="autoplay" loop="loop" muted="muted">
						<source src="../assets/AdobeStock_197561178_AdobeCreativeCloudExpress.mp4" type="video/mp4">
					</video>
					<div class="container">
						<div class="row align-items-center">
							<div class="col-sm-12 col-md-6 text-md-start">
								<div class="py-3 py-md-5">
									<h1 class="text-white fw-bold">
										Welcome to Your <br>Vue.JS Application
									</h1>
									<p class="text-white mb-4 fs-5">
										당신의 이야기가 세상을 바꿉니다.
									</p>
									<router-link :to="{name:'BoardWrite'}" class="btn btn-success">나의 이야기 쓰기</router-link>
								</div>
							</div>
						</div>
					</div>
				</div>
			</div>
			<div class="carousel-item">
				Second Slide
			</div>
		</div>
	</div>
	<div class="home">
		<img alt="Vue logo" src="../assets/logo.png">
		<HelloWorld msg="Welcome to Your Vue.js App"/>
	</div>
</template>

 

5초마다 슬라이드 되는 것을 확인할 수 있습니다. 그렇지만 Second Slide에는 내용이 없어 영역이 작아지는 것도 알 수 있습니다.

 

Second Slide에도 콘텐츠를 추가해 보겠습니다.

비디오는 어도비 스톡(Adobe Stock)에서 무료 라이선스로 다운로드하고 VideoSmaller 사이트에서 MP4 파일의 크기를 줄였습니다.

 

3. 다운로드한 비디오 MP4 파일을 C:\workspaces\nodeserver\testvue\src\assets 폴더에 복사합니다.

4. Second Slide에 다음처럼 콘텐츠를 추가합니다.

<template>
	<div id="mainTopCarousel" class="carousel slide" data-bs-ride="carousel">
		<div class="carousel-inner">
			<div class="carousel-item active">
				<div class="main-top-promotion">
					<video class="main-top-promotion-video" autoplay="autoplay" loop="loop" muted="muted">
						<source src="../assets/AdobeStock_197561178_AdobeCreativeCloudExpress.mp4" type="video/mp4">
					</video>
					<div class="container">
						<div class="row align-items-center">
							<div class="col-sm-12 col-md-6 text-md-start">
								<div class="py-3 py-md-5">
									<h1 class="text-white fw-bold">
										Welcome to Your <br>Vue.JS Application
									</h1>
									<p class="text-white mb-4 fs-5">
										당신의 이야기가 세상을 바꿉니다.
									</p>
									<router-link :to="{name:'BoardWrite'}" class="btn btn-success">나의 이야기 쓰기</router-link>
								</div>
							</div>
						</div>
					</div>
				</div>
			</div>
			<div class="carousel-item">
				<div class="main-top-promotion">
					<video class="main-top-promotion-video" autoplay="autoplay" loop="loop" muted="muted">
						<source src="../assets/AdobeStock_375502954_AdobeCreativeCloudExpress.mp4" type="video/mp4">
					</video>
					<div class="container">
						<div class="row align-items-center">
							<div class="col-sm-12 col-md-6 text-md-start">
								<div class="py-3 py-md-5">
									<h1 class="text-white fw-bold">
										반려동물과의 <br>희로애락(喜怒哀樂)
									</h1>
									<p class="text-white mb-4 fs-5">
										나의 반려생활을 공유합니다.
									</p>
									<router-link :to="{name:'BoardList'}" class="btn btn-primary mx-2">반려생활 소식</router-link> 
									<router-link :to="{name:'BoardWrite'}" class="btn btn-success">나의 반려생활 쓰기</router-link>
								</div>
							</div>
						</div>
					</div>
				</div>
			</div>
		</div>
	</div>
	<div class="home">
		<img alt="Vue logo" src="../assets/logo.png">
		<HelloWorld msg="Welcome to Your Vue.js App"/>
	</div>
</template>

 

비디오를 배경으로 하니 웹 사이트가 멋있어집니다.

 

 

5. 슬라이드 영역에 컨트롤을 추가합니다.

<button class="carousel-control-prev" type="button" data-bs-target="#mainTopCarousel" data-bs-slide="prev">
	<span class="carousel-control-prev-icon" aria-hidden="true"></span>
	<span class="visually-hidden">Previous</span>
</button>
<button class="carousel-control-next" type="button" data-bs-target="#mainTopCarousel" data-bs-slide="next">
	<span class="carousel-control-next-icon" aria-hidden="true"></span>
	<span class="visually-hidden">Next</span>
</button>

.carousel-control-prev class가 적용된 <div> 태그는 이전 버튼이고 .carousel-control-next class가 적용된 <div> 태그는 다음 버튼입니다.

슬라이드를 컨트롤하기 위해 data-bs-target 속성에 Carousel(캐러셀)의 아이디(mainTopCarousel)를 추가합니다.

 

<template>
	<div id="mainTopCarousel" class="carousel slide" data-bs-ride="carousel">
		<div class="carousel-inner">
			<div class="carousel-item active">
				<div class="main-top-promotion">
					<video class="main-top-promotion-video" autoplay="autoplay" loop="loop" muted="muted">
						<source src="../assets/AdobeStock_197561178_AdobeCreativeCloudExpress.mp4" type="video/mp4">
					</video>
					<div class="container">
						<div class="row align-items-center">
							<div class="col-sm-12 col-md-6 text-md-start">
								<div class="py-3 py-md-5">
									<h1 class="text-white fw-bold">
										Welcome to Your <br>Vue.JS Application
									</h1>
									<p class="text-white mb-4 fs-5">
										당신의 이야기가 세상을 바꿉니다.
									</p>
									<router-link :to="{name:'BoardWrite'}" class="btn btn-success">나의 이야기 쓰기</router-link>
								</div>
							</div>
						</div>
					</div>
				</div>
			</div>
			<div class="carousel-item">
				<div class="main-top-promotion">
					<video class="main-top-promotion-video" autoplay="autoplay" loop="loop" muted="muted">
						<source src="../assets/AdobeStock_375502954_AdobeCreativeCloudExpress.mp4" type="video/mp4">
					</video>
					<div class="container">
						<div class="row align-items-center">
							<div class="col-sm-12 col-md-6 text-md-start">
								<div class="py-3 py-md-5">
									<h1 class="text-white fw-bold">
										반려동물과의 <br>희로애락(喜怒哀樂)
									</h1>
									<p class="text-white mb-4 fs-5">
										나의 반려생활을 공유합니다.
									</p>
									<router-link :to="{name:'BoardList'}" class="btn btn-primary mx-2">반려생활 소식</router-link> 
									<router-link :to="{name:'BoardWrite'}" class="btn btn-success">나의 반려생활 쓰기</router-link>
								</div>
							</div>
						</div>
					</div>
				</div>
			</div>
		</div>
		<button class="carousel-control-prev" type="button" data-bs-target="#mainTopCarousel" data-bs-slide="prev">
			<span class="carousel-control-prev-icon" aria-hidden="true"></span>
			<span class="visually-hidden">Previous</span>
		</button>
		<button class="carousel-control-next" type="button" data-bs-target="#mainTopCarousel" data-bs-slide="next">
			<span class="carousel-control-next-icon" aria-hidden="true"></span>
			<span class="visually-hidden">Next</span>
		</button>
	</div>
	<div class="home">
		<img alt="Vue logo" src="../assets/logo.png">
		<HelloWorld msg="Welcome to Your Vue.js App"/>
	</div>
</template>

 

컨트롤이 포함되었지만 콘텐츠 영역과 겹쳐집니다. 그래서 콘텐츠 영역에 margin이나 padding으로 추가여 처리하거나 컨트롤의 위치를 변경해야 합니다.

 

저는 <style>에 컨트롤의 width을 15%에서 7%로 줄었습니다.

.carousel-control-next, .carousel-control-prev {
  width: 7% !important;
}

또는 콘텐츠 영역에 있는 .row class에 "mx-5"를 추가합니다.

<div class="row align-items-center mx-5">

콘텐츠 영역에 margin이 추가되면 모바일에서 margin으로 인해 콘텐츠 영역이 작아져 콘텐츠 내용이 다음 라인으로 내려가 영역의 높이가 변경됩니다. 그래서 margin이나 padding을 추가할 경우 고려해야 합니다.

 

 

 

6. 슬라이드 영역에 Indicator(인디게이터)를 추가합니다.

<div class="carousel-indicators">
	<button type="button" data-bs-target="#mainTopCarousel" data-bs-slide-to="0" class="active" aria-current="true" aria-label="Slide 1"></button>
	<button type="button" data-bs-target="#mainTopCarousel" data-bs-slide-to="1" aria-label="Slide 2"></button>
</div>

.carousel-indicators class가 적용된 <div> 태그 안에는 슬라이드(콘텐츠 영역) 수만큼 Indicator(인디게이터) 버튼을 추가해야 합니다.

슬라이드를 컨트롤하기 위해 <button> 태그의 data-bs-target 속성에 Carousel(캐러셀)의 아이디(mainTopCarousel)를 추가합니다.

<button> 태그의 data-bs-slide-to 속성은 슬라이드(콘텐츠 영역)의 번호입니다. 번호는 0번부터 시작합니다.

첫 번째 .carousel-item class가 적용된 <div>가 0번입니다.

슬라이드 영역에 Indicator(인디게이터)를 추가되면 모바일에서 콘텐츠 영역과 겹쳐집니다. 그래서 콘텐츠 영역에 적용된 padding을 PC와 모바일에 동일하게 적용되도록 수정합니다.

<div class="py-3 py-md-5"> --> 수정 전
<div class="py-5"> --> 수정 후

 

전체 소스입니다.

<template>
	<div id="mainTopCarousel" class="carousel slide" data-bs-ride="carousel">
		<div class="carousel-indicators">
			<button type="button" data-bs-target="#mainTopCarousel" data-bs-slide-to="0" class="active" aria-current="true" aria-label="Slide 1"></button>
			<button type="button" data-bs-target="#mainTopCarousel" data-bs-slide-to="1" aria-label="Slide 2"></button>
		</div>
		<div class="carousel-inner">
			<div class="carousel-item active">
				<div class="main-top-promotion">
					<video class="main-top-promotion-video" autoplay="autoplay" loop="loop" muted="muted">
						<source src="../assets/AdobeStock_197561178_AdobeCreativeCloudExpress.mp4" type="video/mp4">
					</video>
					<div class="container">
						<div class="row align-items-center">
							<div class="col-sm-12 col-md-6 text-md-start">
								<div class="py-5">
									<h1 class="text-white fw-bold">
										Welcome to Your <br>Vue.JS Application
									</h1>
									<p class="text-white mb-4 fs-5">
										당신의 이야기가 세상을 바꿉니다.
									</p>
									<router-link :to="{name:'BoardWrite'}" class="btn btn-success">나의 이야기 쓰기</router-link>
								</div>
							</div>
						</div>
					</div>
				</div>
			</div>
			<div class="carousel-item">
				<div class="main-top-promotion">
					<video class="main-top-promotion-video" autoplay="autoplay" loop="loop" muted="muted">
						<source src="../assets/AdobeStock_375502954_AdobeCreativeCloudExpress.mp4" type="video/mp4">
					</video>
					<div class="container">
						<div class="row align-items-center">
							<div class="col-sm-12 col-md-6 text-md-start">
								<div class="py-5">
									<h1 class="text-white fw-bold">
										반려동물과의 <br>희로애락(喜怒哀樂)
									</h1>
									<p class="text-white mb-4 fs-5">
										나의 반려생활을 공유합니다.
									</p>
									<router-link :to="{name:'BoardList'}" class="btn btn-primary mx-2">반려생활 소식</router-link> 
									<router-link :to="{name:'BoardWrite'}" class="btn btn-success">나의 반려생활 쓰기</router-link>
								</div>
							</div>
						</div>
					</div>
				</div>
			</div>
		</div>
		<button class="carousel-control-prev" type="button" data-bs-target="#mainTopCarousel" data-bs-slide="prev">
			<span class="carousel-control-prev-icon" aria-hidden="true"></span>
			<span class="visually-hidden">Previous</span>
		</button>
		<button class="carousel-control-next" type="button" data-bs-target="#mainTopCarousel" data-bs-slide="next">
			<span class="carousel-control-next-icon" aria-hidden="true"></span>
			<span class="visually-hidden">Next</span>
		</button>
	</div>
	<div class="home">
		<img alt="Vue logo" src="../assets/logo.png">
		<HelloWorld msg="Welcome to Your Vue.js App"/>
	</div>
</template>

<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue';

export default {
	name: 'Home',
	components: {
		HelloWorld
	}
};
</script>

<style>
.main-top-promotion {
  position: relative;
  width: 100%;
}

.main-top-promotion-video {
  height: 100%;
  width: 100%;
  margin: 0px;
  padding: 0px;
  position: absolute;
  left: 0;
  top: 0;
  object-fit: cover;
}

.main-top-promotion > .container {
  position: relative;
}

.carousel-control-next, .carousel-control-prev {
  width: 7% !important;
}
</style>

 

 

728x90
반응형