๐Ÿ’ญ [๊ณผ์ œ ๊ธฐ๋ก] - ์˜ค๋Š˜์˜ ์ง‘ Clone (JS- Swiper, CSS - :hover)

์ •์€ยท2023๋…„ 11์›” 24์ผ

๐Ÿ’ญ ๊ธฐ๋ก

๋ชฉ๋ก ๋ณด๊ธฐ
1/2

"์˜ค๋Š˜์˜ ์ง‘" ์‚ฌ์ดํŠธ๋ฅผ ํด๋ก  ์ฝ”๋”ฉํ•˜๋ฉด์„œ ๊ฒช์€ ์–ด๋ ค์›€๊ณผ ๋ฐฐ์šด ๋‚ด์šฉ์„ ๊ณต์œ ํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. HTML, CSS, JavaScript๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์–ด๋–ป๊ฒŒ ๋ ˆ์ด์•„์›ƒ์„ ๊ตฌ์„ฑํ•˜๊ณ  ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๋Š”์ง€ ์•Œ์•„๋ณด๊ณ , ํŠนํžˆ ์–ด๋ ค์› ๋˜ JS-Swiper์™€ CSS์˜ :hover์— ๋” ์ง‘์ค‘ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.


1. ์–ด๋ ค์› ๋˜ ๋ถ€๋ถ„

๐Ÿ’ก ๋ณต์žกํ•œ ๋ ˆ์ด์•„์›ƒ ๋ฐ ๋””์ž์ธ ์ผ์น˜

"์˜ค๋Š˜์˜ ์ง‘"์€ ์„ธ๋ฐ€ํ•˜๊ฒŒ ๋””์ž์ธ๋œ ๋ณต์žกํ•œ ๋ ˆ์ด์•„์›ƒ์„ ๊ฐ€์ง€๊ณ  ์žˆ์–ด, Flex์™€ Grid๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์›๋ณธ๊ณผ ์œ ์‚ฌํ•œ ๋””์ž์ธ์„ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ์–ด๋ ค์› ์Šต๋‹ˆ๋‹ค. ํŠนํžˆ, ๋ฐ˜์‘ํ˜• ๋””์ž์ธ์„ ์ ์šฉํ•˜๋ฉด์„œ ๋””๋ฐ”์ด์Šค๋ณ„๋กœ ์ ์ ˆํ•œ ๋ ˆ์ด์•„์›ƒ์„ ๊ตฌ์„ฑํ•˜๋Š” ๊ฒƒ์ด ๋„์ „์ ์ด์—ˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ’ก Swiper ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์ดํ•ด์™€ ์ ์šฉ

Swiper ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ฒ˜์Œ ์‚ฌ์šฉํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ดˆ๊ธฐ ์„ค์ • ๋ฐ ์˜ต์…˜ ์ดํ•ด๊ฐ€ ์–ด๋ ค์› ์Šต๋‹ˆ๋‹ค. ์Šฌ๋ผ์ด๋“œ ๊ฐ„ ๊ฐ„๊ฒฉ, ๋ฌดํ•œ ๋ฃจํ”„, ์ž๋™ ์žฌ์ƒ ๋“ฑ ๋‹ค์–‘ํ•œ ์˜ต์…˜์„ ์ ์šฉํ•˜๋ฉด์„œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ๋™์ž‘ ์›๋ฆฌ๋ฅผ ํŒŒ์•…ํ•˜๋Š” ๋ฐ ์‹œ๊ฐ„์ด ๊ฑธ๋ ธ์Šต๋‹ˆ๋‹ค.

๐Ÿ’ก CSS :hover ํšจ๊ณผ ๋ฐ ์• ๋‹ˆ๋ฉ”์ด์…˜

์‚ฌ์šฉ์ž์™€์˜ ์ƒํ˜ธ์ž‘์šฉ์„ ๋†’์ด๊ธฐ ์œ„ํ•ด CSS์˜ :hover ํšจ๊ณผ ๋ฐ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์ ์šฉํ•˜๋Š” ๋ถ€๋ถ„์—์„œ ์–ด๋ ค์›€์„ ๊ฒช์—ˆ์Šต๋‹ˆ๋‹ค. ์ •ํ™•ํ•œ ํƒ€์ด๋ฐ๊ณผ ์ž์—ฐ์Šค๋Ÿฌ์šด ํšจ๊ณผ๋ฅผ ์ฃผ๊ธฐ ์œ„ํ•ด ๋…ธ๋ ฅํ–ˆ์Šต๋‹ˆ๋‹ค.

2. ๋ฐฐ์šด ๋‚ด์šฉ

2.1 Flex์™€ Grid์˜ ํ™œ์šฉ

Flex์™€ Grid๋ฅผ ํšจ๊ณผ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜์—ฌ ๋ณต์žกํ•œ ๋ ˆ์ด์•„์›ƒ์„ ๊ตฌ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค. ํŠนํžˆ, auto-fill๊ณผ auto-fit์„ ์ด์šฉํ•˜์—ฌ ๋ฐ˜์‘ํ˜• ๋””์ž์ธ์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฒ•์„ ์ˆ™์ง€ํ–ˆ์Šต๋‹ˆ๋‹ค.

/* ์˜ˆ์‹œ: Grid ํ™œ์šฉ */
.container {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 20px;
}

.item {
  flex: 1;
  /* ์ถ”๊ฐ€์ ์ธ ์Šคํƒ€์ผ๋ง ... */
}

2.2 Swiper ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ™œ์šฉ

Swiper ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋‹ค์–‘ํ•œ ํ˜•ํƒœ์˜ ์ด๋ฏธ์ง€ ์Šฌ๋ผ์ด๋”๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์Šต๋“ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ž๋™ ์žฌ์ƒ, ๋ฌดํ•œ ๋ฃจํ”„, ๋„ค๋น„๊ฒŒ์ด์…˜ ๋“ฑ ๋‹ค์–‘ํ•œ ์˜ต์…˜๋“ค์„ ํšจ๊ณผ์ ์œผ๋กœ ํ™œ์šฉํ•˜์—ฌ "์˜ค๋Š˜์˜ ์ง‘" ํด๋ก  ์ฝ”๋”ฉ์—์„œ ๋ฐฐ๋„ˆ ์Šค์™€์ดํผ๋ฅผ ๊ตฌํ˜„ํ•œ ์˜ˆ์‹œ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

HTML ๊ตฌ์กฐ

<div class="__rightBanner">
  <div class="swiper-container">
    <div class="swiper-wrapper">
      <!-- ๊ฐ๊ฐ์˜ ์Šฌ๋ผ์ด๋“œ -->
      <div class="swiper-slide">
        <img src="./images/banner_1.jpeg" alt="ํ™ˆํŽ˜์ด์ง€ ์‚ฌ์ด๋“œ ๋ฐฐ๋„ˆ" />
        <a href="javascript:void(0)" class="btn">1/12</a>
      </div>
      <!-- ๋‹ค๋ฅธ ์Šฌ๋ผ์ด๋“œ๋“ค ... -->
    </div>
  </div>
  <!-- ์ด์ „, ๋‹ค์Œ ๋ฒ„ํŠผ -->
  <div class="swiper-prev">
    <span class="material-symbols-outlined">arrow_back</span>
  </div>
  <div class="swiper-next">
    <span class="material-symbols-outlined">arrow_forward</span>
  </div>
</div>

CSS ์Šคํƒ€์ผ๋ง

main .banner .__rightBanner {
  cursor: pointer;
  position: relative;
}

main .banner .__rightBanner:hover img {
  transform: scale(105%);
}

.banner .__rightBanner .swiper-container {
  width: 269px;
  height: 553px;
}

.banner .__rightBanner .swiper-slide {
  position: relative;
  height: 510px;
  position: relative;
  overflow: hidden;
}

.banner .promotion .swiper-slide .btn {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  margin: auto;
}

JavaScript Swiper ๊ตฌํ˜„

new Swiper('.__rightBanner .swiper-container', {
  slidesPerView: 1,
  spaceBetween: 10,
  centeredSlides: true,
  loop: true,
  autoplay: {
    delay: 5000
  },
  navigation: {
    prevEl: '.__rightBanner .swiper-prev',
    nextEl: '.__rightBanner .swiper-next'
  }
});

2.3 CSS์˜ :hover ํ™œ์šฉ

CSS์˜ :hover๋Š” ๋งˆ์šฐ์Šค๊ฐ€ ์š”์†Œ ์œ„์— ์˜ฌ๋ผ๊ฐ€ ์žˆ๋Š” ๋™์•ˆ์˜ ์ƒํƒœ๋ฅผ ์„ ํƒํ•˜๋Š” ๊ฐ€์ƒ ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค. ์ด๋ฅผ ํ™œ์šฉํ•˜์—ฌ "์˜ค๋Š˜์˜ ์ง‘" ํด๋ก  ์ฝ”๋”ฉ์—์„œ์˜ ํŠน์ • ์š”์†Œ์— ๋งˆ์šฐ์Šค๋ฅผ ์˜ฌ๋ฆฌ๋ฉด ๋ฐœ์ƒํ•˜๋Š” ํšจ๊ณผ๋ฅผ ๊ตฌํ˜„ํ•œ ์˜ˆ์‹œ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

/* CSS :hover ์˜ˆ์‹œ */
.banner .__rightBanner:hover img {
  transform: scale(105%);
}

.banner .__rightBanner .swiper-prev,
.banner .__rightBanner .swiper-next {
  /* ๋‹ค๋ฅธ ์Šคํƒ€์ผ ์†์„ฑ๋“ค ... */
  visibility: hidden;
}

.banner .__rightBanner:hover .swiper-prev,
.banner .__rightBanner:hover .swiper-next {
  visibility: visible;
}
  1. ์ด๋ฏธ์ง€ ํ™•๋Œ€ ํšจ๊ณผ: :hover๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐฐ๋„ˆ์˜ ์˜ค๋ฅธ์ชฝ ๋ถ€๋ถ„(.banner .__rightBanner)์— ๋งˆ์šฐ์Šค๋ฅผ ์˜ฌ๋ฆฌ๋ฉด ๊ทธ ์•ˆ์˜ ์ด๋ฏธ์ง€(img)์— transform ์†์„ฑ์„ ์ ์šฉํ•˜์—ฌ 105%๋กœ ํ™•๋Œ€ํ•˜๋Š” ํšจ๊ณผ๋ฅผ ์ค๋‹ˆ๋‹ค. ์ด๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ๋งˆ์šฐ์Šค๋ฅผ ๊ฐ€์ ธ๋‹ค ๋†“์„ ๋•Œ ์ด๋ฏธ์ง€์— ์ž์—ฐ์Šค๋Ÿฌ์šด ํ™•๋Œ€ ํšจ๊ณผ๋ฅผ ์ฃผ์–ด ์‹œ๊ฐ์ ์œผ๋กœ ๋” ํฅ๋ฏธ๋กญ๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

  2. ์ด์ „/๋‹ค์Œ ๋ฒ„ํŠผ ๋‚˜ํƒ€๋‚ด๊ธฐ: .swiper-prev์™€ .swiper-next๋Š” ๋ฐฐ๋„ˆ ์Šค์™€์ดํผ์˜ ์ด์ „๊ณผ ๋‹ค์Œ์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฒ„ํŠผ์ž…๋‹ˆ๋‹ค. ์ดˆ๊ธฐ์—๋Š” visibility: hidden;์œผ๋กœ ์„ค์ •ํ•˜์—ฌ ํ™”๋ฉด์—์„œ ์ˆจ๊ฒจ์ ธ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ .banner .__rightBanner:hover๊ฐ€ ์ ์šฉ๋œ ์ƒํƒœ์—์„œ๋Š” ๋งˆ์šฐ์Šค๋ฅผ ๊ฐ€์ ธ๋‹ค ๋†“์œผ๋ฉด .swiper-prev์™€ .swiper-next์˜ visibility๋ฅผ visible๋กœ ๋ณ€๊ฒฝํ•˜์—ฌ ๋ฒ„ํŠผ์ด ๋‚˜ํƒ€๋‚˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์ด์ฒ˜๋Ÿผ :hover๋ฅผ ํ™œ์šฉํ•˜๋ฉด ์‚ฌ์šฉ์ž์˜ ์ƒํ˜ธ์ž‘์šฉ์— ๋”ฐ๋ผ ๋™์ ์ด๊ณ  ๋ฉ‹์ง„ ํšจ๊ณผ๋ฅผ ๋ถ€์—ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


2.4 ์ด๋ฏธ์ง€ ์œ„์— ์„ค๋ช… ์ถ”๊ฐ€ํ•˜๊ธฐ

position: absolute์™€ ๊ฐ™์€ CSS ์†์„ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฏธ์ง€ ์œ„์— ํ…์ŠคํŠธ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ , ๋ฏธ๋””์–ด ์ฟผ๋ฆฌ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋ฐ˜์‘ํ˜•์œผ๋กœ ๋™์ž‘ํ•˜๋„๋ก ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค.

/* ์˜ˆ์‹œ: ์ด๋ฏธ์ง€ ์œ„์— ํ…์ŠคํŠธ ์ถ”๊ฐ€ */
.image-container {
  position: relative;
}

.image-text {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  /* ์ถ”๊ฐ€์ ์ธ ์Šคํƒ€์ผ๋ง ... */
}

0๊ฐœ์˜ ๋Œ“๊ธ€