스타벅스 예제 3, 4주차

윤뿔소·2022년 8월 6일
0

FastCampus

목록 보기
1/1
post-thumbnail

스타벅스 예제 시작

  1. 그동안의 복습과 새로운 내용 학습을 클론코딩으로!
  2. 강의 흐름대로 쓰겠음, 중구난방일 수 있음!
  3. CSS나 HTML에 코드 작성할 때 주석 처리 해주기! 보기 편함
  4. HTML로 구조 정하고 CSS 선택자로 모두 정리 후 코드 작성하는 것도 좋은 방법

1. 오픈 그래프 / 트위터 카드

오픈 그래프

웹페이지가 SNS(인스타, 카톡 등)로 공유될 때 우선적으로 활용되는 정보
작성법 : meta property = "og:~~" content="~~"

<meta property="og:type" content="website" />
<meta property="og:site_name" content="Starbucks" />
<meta property="og:title" content="Starbucks Coffee Korea" />
<meta property="og:description" content="스타벅스는 세계에서 가장 큰 다국적 커피 전문점입니다." />
<meta property="og:image" content="./images/starbucks_seo.jpg" />
<meta property="og:url" content="https://starbucks.co.kr" />

og:type : 페이지의 유형(E.g, website, video.movie)
og:site_name : 속한 사이트의 이름
og:title : 사이트 자체가 아닌 페이지의 이름(제목)
og:description : 페이지의 간단한 설명, sns에서 악성 페이지로 감지할 수 있기 때문에 최대한 간단하게 작성
og:image : 페이지의 대표 이미지 주소(URL)
og:url : 페이지 주소(URL)

트위터 카드

오픈그래프랑 비슷한테 트위터에 활용
작성법 : meta property = "twitter:~~" content="~~"

<meta property="twitter:card" content="summary" />
<meta property="twitter:site" content="Starbucks" />
<meta property="twitter:title" content="Starbucks Coffee Korea" />
<meta property="twitter:description" content="스타벅스는 세계에서 가장 큰 다국적 커피 전문점입니다." />
<meta property="twitter:image" content="./images/starbucks_seo.jpg" />
<meta property="twitter:url" content="https://starbucks.co.kr" />

twitter:card : 페이지(카드)의 유형(E.g. summary, player)
twitter:site : 속한 사이트의 이름
twitter:title : 사이트 자체가 아닌 페이지의 이름(제목)
twitter:description : 페이지의 간단한 설명, sns에서 악성 페이지로 감지할 수 있기 때문에 최대한 간단하게 작성
twitter:image : 페이지의 대표 이미지 주소(URL)
twitter:url : 페이지 주소(URL)

※ 보통 외부에서 검색, 접속해 빨리 파악해야하는 특징이 있기에 되도록 head 태그 안 다른 meta, title 다음 최상단에 코드를 작성하기


2. 폰트 설정

기본 : link 태그를 CSS 파일 앞에 두고 CSS 속성을 CSS 파일에 적용해 사용하는 방법

폰트를 찾아 적용시키는 법

  1. google fonts 사이트 접속해서 검색, nanum
  2. 고르고 원하는 굵기를 + 눌러서 추가한 다음 use on the web에서 고르기
  3. link 태그와 import 방식을 골라 코드를 작성
    3-1. CSS 파일에 font-family를 적용해야 하기에 link 태그일 시 css 파일보다 먼저 작성하기
  4. use on~ 그 아래에 CSS Rules에 전용 폰트 속성이 있으니 복사 후 바디태그 안에 작성, 그 하위 요소들 모두 적용
  5. 기본 서체 설정 끝!

※ 폰트 라이센스들을 잘 구별해서 활용하기

기본적인 폰트 설정

  1. color: #333; : 기본 폰트 색상은 완전 검은색인데 디자인적으로 촌스러워서 body 선택자 안 글꼴 위에 color: #333; 작성하면 좀 더 보기좋음
  2. line-height : 행간 높이를 1.4로 잡아 보기에 불편함 없이 설정
  3. font-size: 16px;, font-family: 400; : body 선택자에 명시해줘 상속을 보다 명확하게 받아줌
body { /* 폰트 기본 설정 */
  color: #333;
  font-size: 16px;
  font-weight: 400;
  line-height: 1.4;
  font-family: 'Nanum Gothic', sans-serif;
}

3. 기본적인 아이콘 탐색

해당하는 리소스 이미지를 현업할 때는 디자인 팀이 없거나 있다고 해도 하나 하나 제때 제때 요구할 수 없기 때문에 기본적인 이미지(검색:돋보기, 슬라이드, 상단 이동 등)을 찾을 수 있는 사이트를 매사에 알면 좋다.
※ 강의와 차이점이 있음...

Google Material Icons

벡터 기반 구글의 기본 아이콘을 사용할 수 있다! Google fonts 사이트! div 태그여도 성질만 달라질뿐 쓸 수 있다!

  1. Google fonts 사이트에 들어가 icons 탭에 들어가기
  2. 검색창에 material icons로 검색 카테고리 바꾸고 원하는 걸 검색
  3. icon font link 태그를 복사 위해 instructions 들어가서 복사
  4. head 태그 아래, CSS 파일 위로 link 태그 붙여넣기(폰트사이즈와 동일)
  5. 원하는 아이콘 선택 후 해당 span 태그 복사 후 html에 붙여넣으면 끝
  6. 일반적인 font가 아니기에 직접 style 태그를 달아 수정함

다른 무료 아이콘 사이트들도 많다! 핵심은 알아서 잘 찾아 적용해야한다는 것이다.


4. 헤더 / 검색 메뉴 Section

헤더 태그를 이용한 로고, 메인 메뉴, 서브 메뉴 등 맨 위에 기본적인 구조 및 CSS 작성

참고 : BEM

Block Element Modifier : HTML의 클래스 속성의 작명법! 변수명을 정할 때 스트레스를 덜어주고 직관적이어서 수정할 때 용이

요소__일부분 : 요소의 일부분 표시 - 언더스코어 2개
요소--상태 : 요소의 상태를 표시 - 대시 2개

<!-- 그냥 네이밍: 간단함, 누가 누구껀지 알아보기 힘듬 -->
<div class="container">
  <div class="name"></div>
  <div class="item">
    <div class="name"></div>
  </div>
</div> 
<!-- BEM을 활용해 네이밍: 번거로움, 직관적 -->
<div class="container">
  <div class="container__name"></div>
  <div class="item">
    <div class="item__name"></div>
  </div>
</div>

<!-- 버튼의 일반, 완료됨, 오류 상태: 두 단어가 별개로 보임 -->
<div class="btn primary"></div>
<div class="btn success"></div>
<div class="btn error"></div>
<!-- BEM의 네이밍으로 하면 btn의 상태를 직관적으로 보여줌 -->
<div class="btn btn--primary"></div>
<div class="btn btn--success"></div>
<div class="btn btn--error"></div>

로고 / 헤더 배치 및 스타일

1. HTML

header 태그 사용, div와 비슷하게 기능적 역할은 없지만 header라는 의미를 사람에게 줘서 구별하게 만들어줌, 클래스처럼 쓰임

  <!-- HEADER -->
  <header>
    <div class="inner">

      <a href="/" class="logo">
        <img src="./images/starbucks_logo.png" alt="STARBUCKS">
      </a>

    </div>
  </header>

a href="/" : 도메인, 즉 index.html이 생략, 절대경로이기 때문에 / 하나로 index.html로 이동하겠다 라는 의미

2. CSS

/* COMMON */
img { /* 이미지 블럭화 : baseline */
  display: block;
}

/* HEADER */
header {
  background-color: #f6f5f0;
  border-bottom : 1px soild #c8c8c8;
}
header .inner {
  width: 1100px;
  height: 120px;
  margin: 0 auto; /* 로고 좌우 여백 중간 설정 */
  position: relative; /* 내 자신에 position을 따름*/
}
header .logo {
  height: 75px;
  position: absolute; /* 부모요소에 따름 */
  top: 0;
  bottom: 0;
  left: 0;
  margin: auto;  /* 로고 좌우 여백 중간 설정 */
}

position: relative; 설정하기 전 부모를 잘 보기

2-1. auto의 활용

margin: auto;는 컴퓨터가 계산해 설정하는 외부여백들을 '같은 비율'로 맞춘다. ★margin에 0 생략 가능

  1. position으로 어디에 배치할지 기준 정함
  2. top, bottom, left, right의 기준 잡을 상하좌우에 속성값을 지정해 브라우저가 계산하게끔 재료를 줌
  3. height, width를 명확히 작성해 가운데 배치하는 요소에 정확한 너비, 폭을 줘서 가운데에 배치를 할 수 있다.

걍 가운데 배치 하려는 거에 기준과 맞는 값을 줘 계산하게 만들자
정렬도 있고 다른 배치 방식도 있지만 이런 방식도 있다.
상하좌우, 상하만, 좌우만 다 다르게 설정

header .logo { /* 상하좌우 가운데 정렬 */
  width: 75px
  height: 75px;
  position: absolute; 
  top: 0;
  bottom: 0;
  right: 0;
  left: 0;
  margin: auto;
}

2-2. Baseline

영어 소문자를 쓸 때 꼬리 부분을 쓰려고 남겨두고 기준선을 만든게 baseline임. inline 특성, 글자처럼 취급되는 요소(특히 img)를 다룰 때 베이스라인을 기준으로 아래쪽에 약간의 공간이 있는 현상이 생김! 이해하고 맞는 방법으로 수정하자
수정법 : img {display: block;}로 해서 레이아웃처럼 블럭 취급해버리면 간단


서브 메뉴

로고 옆 sign in, my starbucks 등과 검색 옵션을 넣음

1. HTML

.innera 태그 이후 작성(a 태그와 형제)

<div class="sub-menu">
  <ul class="menu">
    <li>
      <a href="javascript:void(0)">Sign In</a>
    </li>
    <li>
      <a href="javascript:void(0)">My Starbucks</a>
    </li>
    <li>
      <a href="javascript:void(0)">Customer Service & Ideas</a>
    </li>
    <li>
      <a href="javascript:void(0)">Find a Store</a>
    </li>
  </ul>
  <div class="search">
    <input type="text" />
    <div class="material-icons">search</div> <!--구글 아이콘-->
  </div>
</div>
  • 로고 옆 서브 메뉴li와 검색 아이콘, 텍스트박스input 입력
  • html을 작성할 때 a 링크의 사이트가 정해지지 않았다면 임시로 <a href="javascript:void(0)"></a> 로도 입력해서 나중에 js로 제어 가능

2. CSS

header .sub-menu {}
header .sub-menu ul.menu { /* ul.menu는 정말 흔함, 앞 부모요소 작성 必 */
  font-family: Arial, sans-serif;
  display: flex;
}
header .sub-menu ul.menu li {
  position: relative;
}
header .sub-menu ul.menu li::before { /* 가상요소선택자 복습 */
  content: ""; /* 인라인 요소 */
  display: block; /* 명시해도 되고 안해도 되고 */ 
  width: 1px;
  height: 12px;
  background-color: #e5e5e5;
  position: absolute; /* 이 속성으로 블럭 요소로 바뀌었음 */
  top: 0;
  bottom: 0;
  margin: auto 0;
}
header .sub-menu ul.menu li:first-child::before {
  display: none; 
}
header .sub-menu ul.menu li a { /* UX */
  font-size: 12px;
  padding: 11px 16px;
  display: block;
  color: #656565;
}
header .sub-menu ul.menu li a:hover {
  color: #000;
}
header .sub-menu .search {} 
header .sub-menu .search input {}
header .sub-menu .search .material-icons {}
/* 이렇게 미리 작성해서 HTML 구조에 따라 코드를 더하는 방법도 좋다 */
  • before 가상요소선택자로 서브메뉴 사이 창살을 만들었음 block요소로 만들어 줄로 표현했음 제일 신기했음 게다가 before 특성상 맨 앞줄에도 창살이 있는데 first-childnone으로 없애서 입이 쩍
  • 메뉴를 설정하는 거라 강사님이 UX를 강조하셨음 예를 들어 ~li a 선택자의 클릭 폭을 글자보다 늘려 쉽게 클릭하게 만드는 방법에서 나타남

검색 박스 스타일 / 애니메이션

검색 박스의 형태와 위치를 지정, 주의할 점은 배치를 잘 했어도 완성본처럼 구글의 아이콘이 없어지지 않거나 아이콘이 텍스트 박스 앞에 나와있어 클릭하기 어려움, 여기서부터 JS가 나옴!!! ㅠㅠ

1. CSS

header .sub-menu { /* 서브메뉴, 검색창 한 줄 배치 및 왼쪽 상단 정렬 */
  position: absolute;
  top: 10px;
  right: 0;
  display: flex;
}
header .sub-menu .search {
  height: 34px;
  position: relative;
}
header .sub-menu .search input {
  width: 36px;
  height: 34px;
  padding: 4px 10px;
  border: 1px soild #ccc;
  box-sizing: border-box;
  border-radius: 5px;
  outline: none; /* 파란색 선이 나타나는데 수정하기 어려워 쓰지 않게 */
  background-color: #fff;
  color: #777;
  font-size: 12px;
  transition: width .4s;
}
header .sub-menu .search input:focus { /* 눌렀을 때 변화 */
  width: 190px;
  border-color: #669900;
}
header .sub-menu .search .material-icons {
  height: 24px; /* 구글의 머터리얼 아이콘 크기와 같음 */
  position: absolute;
  top: 0;
  bottom: 0;
  right: 5px;
  margin: auto;
  transition: .4s; /* js 코드 추가 이후 추가 코드 */
}
header .sub-menu .search.focused .material-icons {
  opacity: 0;
} /* js로 focused를 붙히면 아이콘 없어지는 코드! */

2. JS

코딩 작성 전 HTML에 연결 必

// HTML 코드 작성 : <script defer src="./js/main.js"></script> <!--defer 필수!-->
// 검색창 요소(.search) 찾기.
const searchEl = document.querySelector('.search');// search 클래스 데려오기
const searchInputEl = searchEl.querySelector('input');

searchEl.addEventListener('click', function () { 
  searchInputEl.focus();
}); 
// 1. .search의 요소 클릭 2. 포커스됨 3. input 요소도 같이 포커스됨 

searchInputEl.addEventListener('focus', function () { 
  searchEl.classList.add('focused'); // focused 클래스 추가
  searchInputEl.setAttribute('placeholder', '통합검색');
}); 
// 1. input 포커스되면 2. focused 붙힘 3. input 요소에 통합검색 붙힘

searchInputEl.addEventListener('blur', function () { 
  searchEl.classList.remove('focused'); // 클래스 없애기
  searchInputEl.setAttribute('placeholder', ''); // placeholder 없애기
}); 
// 1. input 블러되면 2. 지움 3. 없앰
  • document, 즉 HTML에서 안찾고 효율적으로 작성하기 위해 searchEl이라는 변수를 둬 그 안 input 태그 선택자로만 찾게 작성
  • 변수.focus() : JS를 통해 input 같이 포커스가 가능한 요소와 함께 강제로 포커스하게 만듬
  • .setAttribute('속성', '속성값') : 그 태그 안에 속성과 속성값을 집어 넣음, 위 코드는 focus 되면 '통합검색'이 나오도록 설정했음
  • .focused를 추가해 CSS에 추가적인 설정 가능 : .search.focused
  • focus의 반댓말은 blur임, 포커스가 빠지면 블러된다!

핸들러 복습 : 'click / focus...' 되면 함수 실행


5. 메인 / 드롭다운 메뉴 Section

대표적인 메뉴들과 마우스를 갖다 댔을 때 드롭다운 메뉴가 나오도록 설정.
2개의 줄이 나오고 위의 로고부터 검색창까지의 영역을 메인메뉴도 똑같이 쓰고 있음.

메인메뉴

1. HTML

.sub-menu 아래 형제 클래스로 위치해서 코드 작성

<ul class="main-menu"> <!--메인메뉴 및 드롭다운 메뉴 클래스, 이름, 내용 설정-->
  <li class="item">
    <div class="item__name">COFFEE</div>
    <div class="item__contents"> <!--언더바 2개 이유가 있음-->
      <div class="contents__menu">
        <ul class="inner">
          <li>
            <h4>커피</h4>
            <ul>
              <li>스타벅스 원두</li>
              <li>스타벅스 비아</li>
              <li>스타벅스 오리가미</li>
            </ul>
          </li>
          <li>
            <h4>에스프레소 음료</h4>
            <ul>
              <li>도피오</li>
              <li>에스프레소 마키아또</li>
              <li>아메리카노</li>
              <li>마키아또</li>
              <li>카푸치노</li>
              <li>라떼</li>
              <li>모카</li>
              <li>리스트레또 비안코</li>
            </ul>
          </li>
          <li>
            <h4>커피 이야기</h4>
            <ul>
              <li>스타벅스 로스트 스팩트럼</li>
              <li>최상의 아라비카 원두</li>
              <li>한 잔의 커피가 완성되기까지</li>
              <li>클로버® 커피 추출 시스템</li>
            </ul>
          </li>
          <li>
            <h4>최상의 커피를 즐기는 법</h4>
            <ul>
              <li>커피 프레스</li>
              <li>푸어 오버</li>
              <li>아이스 푸어 오버</li>
              <li>커피 메이커</li>
              <li>리저브를 매장에서 다양하게 즐기는 법</li>
            </ul>
          </li>
        </ul>
      </div>
      <div class="contents__texture">
        <div class="inner">
          <h4>나와 어울리는 커피 찾기</h4>
          <p>스타벅스가 여러분에게 어울리는 커피를 찾아드립니다.</p>
          <h4>최상의 커피를 즐기는 법</h4>
          <p>여러가지 방법을 통해 다양한 풍미의 커피를 즐겨보세요.</p>
        </div>
      </div>
    </div>
  </li>
  • COFFEE - 커피 - 스타벅스 ~ 구조로 작성
  • 위 코드는 일단 메인메뉴의 'COFFEE' 탭의 코드이고, 나머지 메인메뉴도 같은 구조임, 다 쓰기엔 양이 너무 많아서 구조만 보면 될듯 - class, 부모, 자식, ul, li 잘 보기
  • p로 쓴 것이 있는데 div로 써도 무방, 그저 문장으로 쓴다고 명확하게 지정한 것뿐
  • 메인메뉴의 드롭메뉴에는 이동할 수 있는 페이지는 각 메뉴마다 할당해줘야한다. a 태그로!

2. CSS

/* COMMON */
/* INNER */
.inner {
  width: 1100px;
  margin: 0 auto; /* auto를 써 브라우저가 계산, 좌우 */
  position: relative;
}

/* HEADER */
header > .inner { 
  height: 120px;
}/* 로고와 서브메뉴의 높이가 120px */
header .main-menu {
  position: absolute;
  bottom: 0;
  right: 0;
  z-index: 1; /* 배너나 배경보다 제일 앞에 나오도록 */
  display: flex;
}
header .main-menu .item .item__name {
  padding: 10px 20px 34px 20px;
  font-family: Arial, sans-serif;
  font-size: 13px;
}
header .main-menu .item:hover .item__name { 
  background-color: #2c2a29;
  color: #669900;
  border-radius: 6px 6px 0 0;
} /* contents, name 둘다 나와야해서 item에 hover를 줌 */
header .main-menu .item .item__contents {
  width: 100%;
  position: fixed;
  left: 0;
  display: none;
} /* 배치를 뷰포트 기준으로 해서 화면 양옆 끝까지 가게끔 + 기준을 왼쪽 0으로 */
header .main-menu .item:hover .item__contents {
  display: block;
}
header .main-menu .item .item__contents .contents__menu {
  background-color: #2c2a29;
}
header .main-menu .item .item__contents .contents__menu > ul {
  display: flex; /* inner가 수평정렬 할 수 있도록 */
  padding: 20px 0;
} /* ul안 ul안 ul.. 이 될 수 있어서 제대로 지정(inner)해야함 */
header .main-menu .item .item__contents .contents__menu > ul > li {
  width: 220px;
} /* 커피 */
header .main-menu .item .item__contents .contents__menu > ul > li h4 {
  padding: 3px 0 12px 0;
  font-size: 14px;
  color: #fff;
} /* 스타벅스~ */
header .main-menu .item .item__contents .contents__menu > ul > li ul li {
  padding: 5px 0;
  font-size: 12px;
  color: #999;
  cursor: pointer; /* 커서가 위로 올라왔을때 클릭 버튼으로 되는 속성 */
}
header .main-menu .item .item__contents .contents__menu > ul > li ul li:hover {
  color: #669900;
}
header .main-menu .item .item__contents .contents__texture {
  padding: 26px 0;
  font-size: 12px;
  background-image: url("../images/main_menu_pattern.jpg");
} /* 배경 이미지 패턴은 작지만 기본값인 이미지 반복으로 설정돼있음 */
header .main-menu .item .item__contents .contents__texture h4 {
  color: #999;
  font-weight: 700;
}
header .main-menu .item .item__contents .contents__texture p {
  color: #669900;
  margin: 4px 0 14px;
}
  • 그동안 썼던 header .inner 부분을 헤더나 메인메뉴 등 많이 쓰일거기에 공통 코드 부분으로 옮김, 높이만 다르게 설정할 수 있어야하기에 height만 빼고 적음
  • 옮긴 header .inner 부분에 height: 120px;만 남겨두고 공통 코드로 철수, 특히 ul, li 태그 활용할 때 구조가 ul 안 또다른 ul이 있을 확률이 크기 때문에 많이 쓴다 ★ 다른 header의 inner에게 영향 주지 않기 위해 자식 선택자 >를 활용
  • hover 선택자를 중간 .item에 넣는 경우는 속성 남용x, .item에 hover를 줘 다른 속성이 쓸때 그 설정을 계승시켜 편하게 쓰기 위함이 있다.
  • 상대 경로 중 ../ 을 하면 CSS 파일이 위치한 파일 위치의 밖의 폴더부터 시작! 복습하자

HTML 구조를 세울때 클래스 이름을 잘 정해서 어떤 구조가 반복될지 먼저 생각하고 CSS 코드를 작성하기!
잘 작성하면 HTML에 무슨 내용을 추가하든 다 같은 디자인으로 나옴

전역 배지(GSAP) / 광고배지

헤더 아래 부분 나오는 배너를 뜻함, 드롭다운 메뉴가 나올 때 배지가 가려져야하므로 비쥬얼 섹션에 있지만 드롭다운 메뉴하면서 같이 신경쓰며 만들자.

1. HTML

<div class="badges">
  <div class="badge">
    <img src="./images/badge1.jpg" alt="Badge" />
  </div>
  <div class="badge">
    <img src="./images/badge2.jpg" alt="Badge" />
  </div>
</div>

배너가 2개이니 .badges 아래 .badge 2개의 구조를 가짐

2. CSS

header {
  width: 100%;
  /* position: relative; */
  background-color: #f6f5f0;
  border-bottom : 1px soild #c8c8c8;
  position: fixed;
  top: 0;
}
 header .badges {
  position: absolute;
  top: 132px;
  right: 12px;
}
header .badges .badge {
  border-radius: 10px;
  overflow: hidden; /* 넘치지 않게 */
  margin-bottom: 12px;
  box-shadow: 4px 4px 10px rgba(0,0,0,.15);
  cursor: pointer;
}

.headerposition 기준이 없어서 코드 추가 후 .header에 메인메뉴가 위에 고정되게 배치를 fixed하는데 기본값 auto를 쓰면 메뉴들이 축소되기때문에 100%를 써줌

3. JS

const badgeEl = document.querySelector('header .badges');
// lodash 라이브러리를 통해 등록 후 여기서 사용
window.addEventListener('scroll', _.throttle(function () { 
  console.log(window.scrollY);
  if (window.scrollY > 500) { 
    // 배지 숨기기
    // gsap.to(요소, 지속시간, 옵션-객체데이터);
    gsap.to(badgeEl, .6, {
      opacity: 0,
      display: 'none'
    });
  } else {
    // 배지 보이기
    gsap.to(badgeEl, .6, {
      opacity: 1
      display: 'block'
    });
  }
}, 300)); // 300 ms라는 뜻, 0.3초마다 실행되게!
// _.throttle(함수() {}, 시간)

※window: 윈도우 객체, 윈도우 창을 뜻함, 우리가 보는 화면 자체

  • addEventListenerscroll을 그냥 추가해 사용하면 스크롤 할때마다 함수가 실행돼서 부담이 커짐 - lodash 라이브러리 활용해 제어해야함, scroll에 이벤트 추가할 때 권장사항임
    + lodash 적용법: lodash cdn 구글링 - 최신 버전 script tag 복사 - JS 파일 script 코드 바로 위에 작성
  • scrollY : 스크롤 될 때마다 윈도우의 객체 부분의 속성 Y의 값이(스크롤의 위치 몇픽셀) 갱신되는 걸 알려줌
  • lodash를 적용하며 뱃지가 안나오게 됐음, 하지만 부자연스럽게 없어지기때문에 애니를 적용하기위해 gsap 라이브러리 적용
    + lodash랑 똑같이 적용하여 script 추가
  • gsap.to(요소, 지속시간, 옵션); : gsap에서 제공하는 애니메이션 처리 방법 중 to라는 기능을 사용
    + gsap.to(badgeEl, .6, {객체데이터} : badgeEl을 0.6초동안 바뀌도록 설정함
  • opacity: 0으로 처리해 투명하게 하면서 display: 'none'을 사용해 클릭조차 안되게 만듦
  • display값만 사용하면 중간값이 없기에 자연스러운 전환 효과 사용이 어려움. 그래서 같이 써주면 자연스러우면서도 아예 없애기 가능
  • JS를 입력 중 숫자는 그냥 입력해도 되지만 js에선 변수값이 문자면 따옴표 필수! CSS에서 쓰듯이 쓰면 안됨!

6. 순차적 효과 / 비쥬얼 Section

그동안 Header를 작성했다. 그 다음은 Header의 아래 음료가 순차적으로 나오는 이미지와 비쥬얼의 Section을 구현하자!

비쥬얼 섹션 / 전역 버튼 스타일

1. HTML

<!-- VISUAL -->
  <section class="visual">
    <div class="inner">

      <div class="title">
        <img src="./images/visual_title.png" alt="STARBUCKS DELIGHTFUL START TO THE YEAR" />
        <a href="javascript:void(0)" class="btn btn--brown">자세히 보기</a>
      </div>
      <img src="./images/visual_cup1.png" alt="new OATMEAL LATTE" class="cup1 image" />
      <img src="./images/visual_cup1_text.png" alt="오트밀 라떼" class="cup1 text" />
      <img src="./images/visual_cup2.png" alt="new STARBUCKS CARAMEL CRUMBLE MOCHA" class="cup2 image" />
      <img src="./images/visual_cup2_text.png" alt="스타벅스 카라멜 크럼블 모카" class="cup2 text" />
      <img src="./images/visual_spoon.png" alt="Spoon" class="spoon" />

    </div>
  </section>
  • section태그는 divheader같이 의미는 없지만 영역 설정과 프로그래머가 따로 보기 쉽게 작성하는 태그임.
  • javascript:void(0) 서브메뉴에서 했듯이 임시로 넣는 주소.
  • 따로 Section 설정하기에 Header와 형제임, visual Section에 들어갈 이미지와 링크를 걸어두고 각 클래스를 설정했음.
  • '자세히 보기'는 '버튼'-btn으로 따로 만들어야함, BEM 방식으로 btn--XXX로 다양한 스타일 적용 가능

2. CSS

/* COMMON, 전역 */
/* BUTTON */
.btn {
  width: 130px;
  padding: 10px;
  border: 2px solid #333;
  border-radius: 4px;
  color: #333;
  font-size: 16px;
  font-weight: 700;
  text-align: center;
  cursor: pointer;
  box-sizing: border-box;
  display: block;
  transition: .4s;
} /* 우선순위 점수 : 10점 */
.btn:hover {
  background-color: #333;
  color: #FFF;
} /* btn이 reverse 되면 #333 색이 된다. 이렇게 상태를 설정해줘 우선순위 점수 20점을 얻어 나중에 따로 덮어써서 수정할 수 있음 */
.btn.btn--reverse {
  background-color: #333;
  color: #FFF;
}
.btn.btn--reverse:hover {
  background-color: transparent;
  color: #333;
}
.btn.btn--brown {
  color: #592B18;
  border-color: #592B18;
}
.btn.btn--brown:hover {
  color: #FFF;
  background-color: #592B18;
}
.btn.btn--gold {
  color: #D9AA8A;
  border-color: #D9AA8A;
}
.btn.btn--gold:hover {
  color: #FFF;
  background-color: #D9AA8A;
}
.btn.btn--white {
  color: #FFF;
  border-color: #FFF;
}
.btn.btn--white:hover {
  color: #333;
  background-color: #FFF;
}

/* VISUAL */
.visual {
  margin-top: 120px; /* 헤더 부분 아래에 위치하도록 설정 */
  background-image: url("../images/visual_bg.jpg");
  background-position: center;
}
.visual .inner {
  height: 646px;
} /* inner의 공통 속성 적용돼서 따로 코드 작성 X */
.visual .title {
  position: absolute;
  top: 88px;
  left: -10px;
}
.visual .title .btn {
  position: absolute;
  top: 259px;
  left: 173px;
} /* title에 btn 클래스를 붙여 title의 이미지와 버튼이 함께 움직이도록 설정 */
.visual .cup1.image {
  position: absolute;
  bottom: 0;
  right: -47px;
} /* 일치선택자 */
.visual .cup1.text {
  position: absolute;
  top: 38px;
  right: 162px;
}
.visual .cup2.image {
  position: absolute;
  bottom: 0;
  right: 162px;
}
.visual .cup2.text {
  position: absolute;
  top: 321px;
  right: 416px;
}
.visual .spoon {
  position: absolute;
  bottom: 0;
  left: 275px;
}
  • '자세히 보기'라는 버튼을 만들어야하기에 '공통 적용 코드' 아래 'BUTTON'부분을 만들어 버튼의 클래스인 .btn을 작성
  • 버튼의 여러 가지의 색을 만들어야 하기에 미리 BEM의 상태 작성법에 근거해 --XXX로 작명하고 각각의 색을 지정했음, 적용하고 싶다면 HTML 코드에 class= "btn btn--XXX"하고 작성하면 됨
  • 헤더 부분에선 선택자에 구조를 나타내려고 중복되는 선택자도 다 같이 써줬는데 보통은 생략해도 괜찮음. 해당하는 선택자가 한개 정도라면 오케이!
    ex1)header .main-menu .item .item__contents .contents__texture : 모든 구조를 나타낸 선택자
    ex2).visual (.inner .title) .cup1.image : inner를 다 안써주고 .title만 써준 선택자
  • 선택자를 붙여서 쓴 경우는? 일치 선택자 : 2가지 동시에 만족하는 요소 선택
  • 아직 position의 top, bottom, left, right 설정이 와닿지 않음. 추가 설명 필요
    위 이미지는 .btn의 코드를 설명한 것임, position: absolute;로 설정돼있어서 그 부모인 title에 기준하여 그 위치에서 top: 259px;, left: 173px; 즉! 위에서 259px 만큼 아래, 왼쪽에서 173px 만큼 와서 위치한다! 라는 뜻, 이미지 보면서 직관적으로 이해하기!

------------------------------------------여기서부터 4주차------------------------------------------

순차적으로 나오도록 제어 : 코드 수정

음료 이미지들이 순차적으로 나오도록 환경 설정한다. 지금까지 그냥 나오도록 설정 및 배치한 코드라면 이제부터는 각 요소마다 fade in, out 되도록, 순차적으로 나오도록 작성하자

1. HTML

<div class="title fade-in">
  <img src="./images/visual_title.png" alt="STARBUCKS DELIGHTFUL START TO THE YEAR" />
  <a href="javascript:void(0)" class="btn btn--brown">자세히 보기</a>
</div>
<div class="fade-in">
  <img src="./images/visual_cup1.png" alt="new OATMEAL LATTE" class="cup1 image" />
  <img src="./images/visual_cup1_text.png" alt="오트밀 라떼" class="cup1 text" />
</div>
<div class="fade-in">
  <img src="./images/visual_cup2.png" alt="new STARBUCKS CARAMEL CRUMBLE MOCHA" class="cup2 image" />
  <img src="./images/visual_cup2_text.png" alt="스타벅스 카라멜 크럼블 모카" class="cup2 text" />
</div>
<div class="fade-in">
  <img src="./images/visual_spoon.png" alt="Spoon" class="spoon" />
</div>
  • 이렇게 원래 코드에 .fade-in이라는 클래스 작성 및 수정 해줌

2. CSS

.visual .fade-in {
  opacity: 0;
}
  • CSS로 가서 .fade-in에 투명도 0을 넣어줘 fade-in이 되면 투명하게 보이게 설정

3. JS

// 나타날 요소들(.fade-in) 찾기.
const fadeEls = document.querySelectorAll('.visual .fade-in')
// 나타날 요소들을 하나씩 반복해서 처리!
fadeEls.forEach(function (fadeEl, index) { // 반복 사용, 순서 정의
  // 각 요소들을 순서대로(delay) 보여지게 함!
  gsap.to(fadeEl, 1, {
    delay: (index + 1) * .7,
    opacity: 1
  })
})
  • index로 0부터 반복하는 함수를 만듦(Zero-based Numbering)
  • delay 함수 해석 : index에 1을 더해 첫번째 요소(fadeEl)에는 0.7초 후에 투명도(opacity)가 1이 되고 두번째 요소는 1.4초 후에, 세번째는 2.1초 후에 ... 하고 반복됨! index가 0부터 시작하므로 1을 더하는 디테일 잘 봐야함!
  • HTML에서 구조를 잘 잡아야 순서도 제대로 나오는 JS 코드임. HTML 코드와 비교하여 요소가 fade-out이 되는 순서를 예상해보자!

반복을 몰랐다면 0.7, 1.4 ... 이렇게 일일이 설정해야한다 이런 건 피해야한다! 다양한 구조 처리를 미리 알자!


7. 슬라이드 Section

그 다음 Section으로 공지사항 및 프로모션 등등을 만들 것

공지사항

Swiper 라이브러리를 활용해 수직 슬라이드를 만들어 보자

Swiper JS : 슬라이드를 만들수 있는 라이브러리
기본 구조 : .swiper-container => .swiper-wrapper => .swiper-slide => .a등의 태그나 내용 작성

1. HTML

<!--NOTICE-->
  <section class="notice">

    <!--NOTICE LINE-->
    <div class="notice-line">
      <div class="bg-left"></div>
      <div class="bg-right"></div>
      <div class="inner">
        
        <div class="inner__left">
          <h2>공지사항</h2>
          <div class="swiper-container">
            <div class="swiper-wrapper">
              <div class="swiper-slide">
                <a href="javascript:void(0)">크리스마스 & 연말연시 스타벅스 매장 영업시간 변경 안내</a>
              </div>
              <div class="swiper-slide">
                <a href="javascript:void(0)">[당첨자 발표] 2021 스타벅스 플래너 영수증 이벤트</a>
              </div>
              <div class="swiper-slide">
                <a href="javascript:void(0)">스타벅스커피 코리아 애플리케이션 버전 업데이트 안내</a>
              </div>
              <div class="swiper-slide">
                <a href="javascript:void(0)">[당첨자 발표] 뉴이어 전자영수증 이벤트</a>
              </div>
            </div>
          </div>
          <a href="javascript:void(0)" class="notice-line__more">
            <div class="material-icons">add_circle</div>
          </a>
        </div>

        <div class="inner__right">
          <h2>스타벅스 프로모션</h2>
          <div class="toggle-promotion">
            <div class="material-icons">upload</div>
          </div>
        </div>

      </div>
    </div>

  </section>
  • CDN 복사 후 JS 파일 경로 코드 전에 작성
  • Swiper 구조를 이용해 작성 : slide 총 4개

2. CSS

/*NOTICE*/
/*NOTICE LINE*/
.notice .notice-line {
  position: relative;
}
.notice .notice-line .bg-left {
  position: absolute;
  top: 0;
  left: 0;
  width: 50%;
  height: 100%;
  background-color: #333;
} /* bg-left, right는 width가 브라우저 끝까지 가게 만드는 선택자 */
.notice .notice-line .bg-right {
  position: absolute;
  top: 0;
  right: 0;
  width: 50%;
  height: 100%; /* 설정된 높이 100% */
  background-color: #f6f5ef;
}
.notice .notice-line .inner {
  height: 62px;
  z-index: 1;
  display: flex;
} 
.notice .notice-line .inner__left {
  width: 60%;
  height: 100%;
  background-color: #333;
  display: flex;
  align-items: center;
}
.notice .notice-line .inner__left h2 {
  color: #fff;
  font-size: 17px;
  font-weight: 700;
  margin-right: 20px;
}
.notice .notice-line .inner__left .swiper-container {
  flex-grow: 1; 
  height: 62px;
} /* 얘만 grow가 1이여서 형제가 갖고 있는 크기를 빼고 설정된 크기만큼 stretch됨 */
/* Swiper 라이브러리 추가 이후 추가 작성 */
.notice .notice-line .inner__left .swiper-slide { 
  height: 62px;
  display: flex;
  align-items: center;
}
.notice .notice-line .inner__left .swiper-slide a {
  color: #fff;
}
.notice .notice-line .inner__left .notice-line__more {
  width: 62px;
  height: 62px;
  display: flex; /* 가운데 정렬을 위함 */
  justify-content: center; /* 수평 가운데 정렬 */
  align-items: center; /* 수직 가운데 정렬 */
}
.notice .notice-line .inner__left .notice-line__more .material-icons {
  color: #fff;
  font-size: 30px;
} /* 아이콘의 기본 크기는 24px */
.notice .notice-line .inner__right {
  width: 40%;
  height: 100%;
  display: flex;
  justify-content: flex-end; /* 아이템들을 끝점으로 정렬 */
  align-items: center;
}
.notice .notice-line .inner__right h2 {
  font-size: 17px;
  font-weight: 700;
}
.notice .notice-line .inner__right .toggle-promotion {
  width: 62px;
  height: 62px;
  cursor: pointer;
  display: flex; /* 가운데 정렬을 위함 */
  justify-content: center; /* 수평 가운데 정렬 */
  align-items: center; /* 수직 가운데 정렬 */
}
.notice .notice-line .inner__right .toggle-promotion .material-icons {
  font-size: 30px;
}
  • .notice-line이 부모지만 width, height 값이 따로 없어 형제인 .inner(COMMON의 스타일도 포함)로 높이가 제어됨, 즉 .inner 하나로 일일이 각각의 선택자에 높이를 입력 안해도 됨
    +편한 방법! 하지만 이 방법을 활용하기위한 구조로 작성 必
  • flex-grow 복습: 부모에 플렉스를 부여했을때 숫자 등을 지정해 비율을 정하는 것, 설정된 비율만큼 좌우, 높이 다 최대한 stretch됨
  • flex에서 쓰이는 정렬법 복습: flex-end, justify, align 등등

3. JS

/* 슬라이드 요소 관리 */
// new Swiper('선택자', {옵션}); Swiper라는 기능을 추가한다.
new Swiper('.notice-line .swiper-container', {
  direction: 'vertical', // 수직 슬라이드
  autoplay: true, // 자동 재생 여부: 불린 데이터로 결정
  loop: true // 반복 재생 여부: 불린 데이터로 결정
});
  • new는 JS에서 생성자(클래스)를 뜻함, 위 코드에 new는 Swiper라는 함수를 실행한다~ 하고 선언으로 쓰임

프로모션

이벤트나 광고 등을 넣을 수 있는 수평 슬라이드를 만들자!
자세히 보기, 이미지를 확대·축소시켜도 정 가운데 유지

1. HTML

<!--PROMOTION-->
<div class="promotion">

  <div class="swiper-container">
    <div class="swiper-wrapper">
      <div class="swiper-slide">
        <img src="./images/promotion_slide1.jpg" alt="2021 뉴이어, 스타벅스와 함께 즐겁고 활기차게 시작하세요!" />
        <a href="javascript:void(0)" class="btn">자세히 보기</a>
      </div>
      <div class="swiper-slide">
        <img src="./images/promotion_slide2.jpg" alt="기간 내 스타벅스 카드 e-Gift를 3만원 이상 선물 시, 아메리카노 e-쿠폰을 드립니다." />
        <a href="javascript:void(0)" class="btn">자세히 보기</a>
      </div>
      <div class="swiper-slide">
        <img src="./images/promotion_slide3.jpg" alt="뉴이어 푸드와 제조 음료를 세트로 구매 시, 뉴이어 음료 BOGO(1+1) 쿠폰을 드립니다." />
        <a href="javascript:void(0)" class="btn">자세히 보기</a>
      </div>
      <div class="swiper-slide">
        <img src="./images/promotion_slide4.jpg" alt="신년 MD 상품 포함 3만원 이상 구매 고객께 아메리카노(톨사이즈) 쿠폰을 드립니다." />
        <a href="javascript:void(0)" class="btn">자세히 보기</a>
      </div>
      <div class="swiper-slide">
        <img src="./images/promotion_slide5.jpg" alt="2017 DIGITAL LUCKY DRAW 100% 당첨의 행운을 드립니다!" />
        <a href="javascript:void(0)" class="btn">자세히 보기</a>
      </div>
    </div>
  </div>
  <div class="swiper-pagination"></div>

  <div class="swiper-prev">
    <span class="material-icons">arrow_back</span>
  </div>
  <div class="swiper-next">
    <span class="material-icons">arrow_forward</span>
  </div>

  </div>

</div>
  • NOTICE와 형제
  • Swiper의 container-wrapper-slide 구조 제작
  • Swiper의 Pagination 활용해서 좌우 화살표, 페이지네이션 만들기

2. CSS

slide의 광고, 이벤트 이미지와 '자세히보기' 배치 및 꾸미기, 페이지네이션 불렛, 애로우 배치와 꾸미기

.notice .promotion {
  height: 693px;
  background-color: #f6f5ef;
  position: relative;
}
.notice .promotion .swiper-container {
  width: calc(819px * 3 + 20px);
  height: 553px;
  position: absolute;
  top: 40px;
  right: 50%;
  margin-right: calc((819px * 3 + 20px) / -2);
} /* width의 크기 절반을 기준으로 삼은 다음 margin-XX로 땡겨오기 */
.notice .promotion .swiper-slide {
  opacity: .5;
  transition: opacity 1s;
  position: relative;
}
.notice .promotion .swiper-slide-active {
  opacity: 1;
}
.notice .promotion .swiper-slide .btn {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  margin: auto;
} /* 버튼의 배치 */
.notice .promotion .swiper-pagination {
  bottom: 40px;
  left: 0;
  right: 0;
} /* 라이브러리에 포지션 값이 이미 할당돼있어서 이렇게 작성, 브라우저로 검사 눌러서 확인해보기! */
.notice .promotion .swiper-pagination .swiper-pagination-bullet {
  background-color: transparent; /* 투명으로 채움, 기본은 파란색으로 채워짐 */
  background-image: url("../images/promotion_slide_pager.png");
  width: 13px;
  height: 12px;
  margin-right: 6px;
  outline: none; /* 파란색 테두리 선 출력 X */
} /* 페이지 번호의 불렛들을 디자인 */
.notice .promotion .swiper-pagination .swiper-pagination-bullet:last-child {
  margin-right: 0;
} /* 불렛의 margin-right에 6px을 적어 여백을 줬는데 마지막 불렛에는 필요없어서 가상 클래스를 이용해 없앰 */
.notice .promotion .swiper-pagination .swiper-pagination-bullet-active {
  background-image: url("../images/promotion_slide_pager_on.png");
} /* 활성화된 불렛은 active가 붙는다. 그걸 이용해 이미지 삽입으로 하이라이트! */
.notice .promotion .swiper-prev, /* 다중 선택자, 쉼표로 선택자 2개 해당되게 */
.notice .promotion .swiper-next { /* 줄바꿈 해주기! 직관적으로 보기 위해 */
  width: 42px;
  height: 42px;
  border: 2px solid #333;
  border-radius: 50%; /* 원 */
  position: absolute;
  /* Swiper Container 높이의 절반만큼 끌어올림 */
  /* 버튼 높이의 절반만큼 추가로 끌어올림 */
  top: 300px;
  z-index: 1;
  cursor: pointer;
  outline: none;
  display: flex; /* 화살표가 정 가운데로 가도록 만들기 */
  justify-content: center; /* 수평 */
  align-items: center; /* 수직 */
  transition: .4s;
}
.notice .promotion .swiper-prev {
  left: 50%;
  margin-left: -480px;
} /* 항상 가운데 슬라이드 양옆으로 배치되게 만들기 */
.notice .promotion .swiper-next {
  right: 50%;
  margin-right: -480px;
}
.notice .promotion .swiper-prev:hover,
.notice .promotion .swiper-next:hover {
  background-color: #333;
  color: #fff;
}
  • .swiper-container는 프로모션이 나타나는 크기를 먼저 정해야함. XXpx로 지정하기엔 틀릴 수도 있고, 나중에 수정으로 변했을 때 일일이 수정해야함. 그럴때 속성: calc() 함수를 씀!!
    +calc()의 예 : XXpx * X + XXpx / 100% - 50px(자주!)
  • 확대·축소할 때 요소가 중간에 위치해야함 - 브라우저가 중간으로 계산을 하게 만들면 됨! 사진은 left 기준으로 했음, 코드는 right 기준!
    이렇게 %를 쓰고 되돌려서 브라우저가 50%에 위치하도록 계산하게 만들어서 중간에 위치하게됨! left 말고 right를 써도 어느 부분(left를 right로)에서 뺄건지만 차이를 두고 나머진 같음!
  • 이미지의 상세정보를 보면 픽셀 크기가 보임. 이걸로 너비와 높이를 정하면 됨!
  • 페이지 번호의 불렛들은 이미 포지션값이 할당돼 있어서 방향 지시 속성만 써주면 됨! f12 눌러서 확인해보기

3. JS

/**
 * 슬라이드 요소 관리
 */
// new Swiper('선택자', {옵션}); Swiper라는 기능을 추가한다.
new Swiper('.notice-line .swiper-container', {
  direction: 'vertical', // 수직 슬라이드
  autoplay: true, // 자동 재생 여부: 불린 데이터로 결정
  loop: true // 반복 재생 여부: 불린 데이터로 결정
});
new Swiper('.promotion .swiper-container', {
  // direction: 'horizontal', // 수평 슬라이드
  autoplay: { // 자동 재생 여부
    delay: 5000 // 5초마다 슬라이드 바뀜
  },
  loop: true, // 반복 재생 여부
  slidesPerView: 3, // 한 번에 3개 보여줌!
  spaceBetween: 10, // 슬라이드 사이 여백
  centeredSlides: true, // 1번 슬라이드가 가운데 보이기
  pagination: { // 페이지 번호 사용 여부
    el: '.promotion .swiper-pagination', // 페이지 번호 요소 선택자
    clickable: true // 사용자의 페이지 번호 요소 제어 가능 여부
  },
  navigation: { // 슬라이드 이전/다음 버튼 사용 여부
    prevEl: '.promotion .swiper-prev', // 이전 버튼 선택자
    nextEl: '.promotion .swiper-next' // 다음 버튼 선택자
  }
});
  • Swiper는 direction: 'horizontal'이 기본값이라 수평 슬라이드할 땐 따로 안적어줘도 됨!
  • Swiper로 생기는 클래스 값인 .swiper-slide-active을 이용해 메인으로 보여지는 슬라이드 빼고 반투명하게 만듦! 사용자가 가운데만 집중이 되게!
  • 페이지를 넘어가게 만드는 화살표 2개와 페이지 번호를 만들어 이동하게 만듦! HTML로 요소를 만들고, CSS로 배치, JS로 눌렀을때 넘어가게 만듦!

슬라이드 토글 만들기

'스타벅스 프로모션'의 슬라이드 버튼을 누르면 프로모션 슬라이드가 닫히고 열리는 걸 만들어본다!

1. HTML

HTML은 이미 promotion할 때 만들어 놨음!

<div class="toggle-promotion">
  <div class="material-icons">upload</div>
</div>

2. CSS

.notice .promotion {
  transition: height .4s;
  overflow: hidden;
}
.notice .promotion.hide {
  height: 0;
}
  • JS로 만들어지는 클래스 hide를 가지고 활용
  • height: 0;으로 설정해 수직적으로 수축되게 만듬
  • .notice .promotion에 매끄럽게 변화를 만들기 위해 .4s를 붙이고 height가 0이 된다면 그 전에 있던 promotion 요소들이 그대로 흘러넘치기 때문에 overflow: hidden;로 설정

3. JS

/**
 * Promotion 슬라이드 토글 기능, CSS에 활용할 클래스 만들기
 */
// 슬라이드 영역 요소 검색 및 변수 할당
const promotionEl = document.querySelector('.promotion');
// 슬라이드 영역를 토글하는 버튼 검색 및 변수에 할당
const promotionToggleBtn = document.querySelector('.toggle-promotion');
// 슬라이드 영역 숨김 여부 기본값을 false로 할당
let isHidePromotion = false;
// 토글 버튼을 클릭하면,
promotionToggleBtn.addEventListener('click', function () { // 이벤트 핸들러
  // 슬라이드 영역 숨김 여부를 느낌표를 써 반댓값으로 할당!
  isHidePromotion = !isHidePromotion
  // 요소를 숨겨야 하면,
  if (isHidePromotion) {
    promotionEl.classList.add('hide')
  // 요소가 보여야 하면,
  } else {
    promotionEl.classList.remove('hide')
  }
});
  • 페이지에 들어오고 기본적인 상태는 슬라이드 버튼을 누르지 않은 상태로 선언
  • click 이벤트 핸들러를 활용해 불린데이터를 반댓값으로 가게 만들고 클래스 .hide를 추가 및 제거

8. 리워즈 Section

이제부터 리워즈 Section 시작! 유튜브 영상을 감쌀 버튼과 이미지를 배치한다!

1. HTML

<!--REWARDS-->
<section class="rewards">
  <div class="bg-left"></div>
  <div class="bg-right"></div>

  <div class="inner">
    <div class="btn-group">
      <div class="btn btn--reverse sign-up">회원가입</div>
      <div class="btn sign-in">로그인</div>
      <div class="btn gift">e-Gift 선물하기</div>
    </div>
  </div>
</section>
  • .bg-XX로 영역 전개, .inner로 버튼을 취합하여 정렬, .btn을 활용한 디자인 구조를 만듦!

2. CSS

/*REWARDS*/
.rewards {
  position: relative;
}
.rewards .bg-left,
.rewards .bg-right{
  width: 50%;
  height: 100%;
  position: absolute;
  top: 0;
}
.rewards .bg-left {
  background-color: #272727;
  left: 0;
}
.rewards .bg-right {
  background-color: #d5c798;
  right: 0;
}
.rewards .inner {
  background-image: url("../images/rewards.jpg");
  height: 241px;
}
.rewards .btn-group {
  position: absolute; /* COMMON의 inner에 relative 들어가있음 */
  right: 0;
  bottom: 24px;
  width: 250px;
  display: flex;
  flex-wrap: wrap;
}
.rewards .btn-group .btn.sign-up {
  /*width: 130px;*/
  margin-right: 10px;
}
.rewards .btn-group .btn.sign-in {
  width: 110px;
}
.rewards .btn-group .btn.gift {
  margin-top: 10px;
  flex: 1; /* 최대한의 너비를 사용하라 */
}
  • 리워드의 이미지 배치 및 확대 축소 했을 시 중간에 위치, 배경색이 비율에 맞게 제한없이 쭉 가는 걸 설정
  • 버튼 배치를 정렬하기위해 inner와 flex-wrap: wrap;을 이용해 만듦

9. Youtube, 부유 요소 Section

  • 유튜브의 영상 API를 가져오는 법과 화면 비율을 맞추는 법을 배우자!
  • 아이콘을 부유하듯이 둥둥 띄우고, 그에 맞는 애니메이션을 삽입하자!

유튜브 영상 삽입

영상 비율 맞추는 법!
이런 식으로 padding-top 속성을 이용한다면 자연스럽게 화면 비율을 자동으로 계산해줘 편하다! 위는 16:9 비율로 작성됐다!

1. HTML

<script defer src="./js/youtube.js"></script>

  <!--YOUTUBE VIDEO-->
  <section class="youtube">
    <div class="youtube__area">
      <!-- Youtube iframe API 생성 id div -->
      <div id="player"></div>
    </div>
    <div class="youtube__cover"></div>

  </section>
  • Youtube iframe API : 유튜브 영상을 사이트에 삽입 하는 법에 대해서 알려줌, 구글링 해서 참조 문서를 보며 복습하기
  • 유튜브 전용 JS 파일을 따로 작성함
  • youtube - youtube__area - id="player" 구조로 건설하고 cover를 따로 작성

2. CSS

/*YOUTUBE VIDEO*/
.youtube {
  position: relative;
  height: 700px;
  background-color: #333;
  overflow: hidden;
}
.youtube .youtube__area {
  width: 1920px;
  position: absolute;
  /* 16비율, 가로 */
  left: 50%; /* 50% 위치 후 끌어오게 만드는 배치 방법 복습 */
  margin-left: calc(1920px / -2);
  /* 9비율, 세로 */
  top: 50%;
  margin-top: calc(1920px * 9 / 16 / -2); /* 폭 나누기 16:9 비율 나누기 중간에 위치토록 -2 */
}
.youtube .youtube__area::before {
  content: "";
  display: block;
  /* 16:9 영상 비율로 요소 크기 만들기! */
  width: 100%;
  height: 0;
  padding-top: 56.25%;
}
.youtube .youtube__cover {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0,0,0,.3);
  background-image: url("../images/video_cover_pattern.png");
} /* 유튜브 주변 커버 덮기 */
#player {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
}
  • 중요한 개념 : 정해진 비율로 요소크기 만들기, 수직·수평 끌어와 가운데 정렬 배치법
  • 위 코드에선 가상 요소 선택자를 활용해 만듦, lefttop으로 가운데 위치, 특히 top은 1080px이지만 calc() 함수를 이용해서 * 9 / 16으로 세로비율을 맞췄음

3. JS

/* youtube.js 라는 파일을 따로 만들기
 * 2. Youtube IFrame API를 비동기로 로드합니다. 
 */
var tag = document.createElement('script');

tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

/* onYouTubePlayerAPIReady 함수 이름은,
 * Youtube IFrame Player API에서 사용하는 이름이기 때문에,
 * 다르게 지정하면 동작하지 않습니다!
 * 그리고 함수는 전역(Global) 등록해야 합니다! 
 */
function onYouTubeIframeAPIReady() {
  // <div id="player"></div>
  new YT.Player('player', {
    videoId: 'An6LvWQuj_8', // 최초 유튜브 영상 ID, 주소창에 v= 이후 부분
    playerVars: {
      autoplay: true, // 자동 재생 유무
      loop: true, // 반복 재생 유무
      playlist: 'An6LvWQuj_8' // 반복 재생할 유튜브 영상 ID 목록
    },
    events: {
      // 영상이 준비되었을 때,
      onReady: function (event) {
        event.target.mute() // 음소거!
      }
    }
  });
}
  • Youtube iframe API : 유튜브 영상을 사이트에 삽입 하는 법에 대해서 알려줌, 구글링 해서 참조 문서를 보며 복습하기

유튜브 영상 위 아이콘을 띄우기

요소들을 띄우고 각 요소가 따로 부유하는 듯한 느낌을 주기 위해서 랜덤 함수를 사용!

1. HTML

<div class="youtube__cover"></div>
<div class="inner">

  <img src="./images/floating1.png" alt="Icon" class="floating floating1" />
  <img src="./images/floating2.png" alt="Icon" class="floating floating2" />
  <img src="./images/floating3.png" alt="Icon" class="floating floating3" />
</div>
  • .youtube의 자식으로 입력

2. CSS

.youtube .inner {
  height: 700px;
} /* 임시로 배치 */
.youtube .floating1 {
  position: absolute;
  top: 50px;
  left: 0;
}
.youtube .floating2 {
  position: absolute;
  top: 350px;
  left: 150px;
}
.youtube .floating3 {
  position: absolute;
  bottom: -200px;
  right: 0;
}
  • 부유하는 요소들 배치! 근데 .floating3가 잘려서 그다음 섹션에서 고쳐야함! 그래서 .inner에 임의로 입력됐음

3. JS

// 범위 랜덤 함수, min이상 max이하 숫자 랜덤
function random(min, max) {
  return parseFloat((Math.random() * (max - min) + min).toFixed(2))
}

function floatingObject(selector, delay, size) { // 딜레이, 사이즈 작성은 명확히 하기 위함
  // gsap.to(요소, 시간, {옵션});
  gsap.to(
    selector, // 요소: 선택자
    random(1.5, 2.5), // 동작 시간
    {
      delay: random(0, delay), // 시작 지연 시간을 설정, 단위: s
      y: size, // `transform: translateY(수치);`와 같음. 수직으로 얼마나 움직일지 설정
      repeat: -1, // `-1`은 무한 반복
      yoyo: true, // 한번 재생된 애니메이션을 다시 뒤로 재생
      ease: Power1.easeInOut // Easing In Out 함수 적용
    }
  )
}
floatingObject('.floating1', 1, 15);
floatingObject('.floating2', .5, 15);
floatingObject('.floating3', 1.5, 20); // 실행
// 숫자들은 위에 각각 delay, size로 들어간다!
  • 부유 애니메이션 제작 : gsab - easing 함수 사용! 구글링하기 파워를 골라 굴곡짐을 고르고, Type부분을 눌러 속도를 정함! 아래 TweenMax.to(=gsap.to)(요소명, 시간, {ease: Power1.easeOut}); 이런식으로 적용하면 됨!
  • 랜덤 숫자 생성 함수 사용!! 이런 식으로 사용
// 범위 랜덤 함수(소수점 2자리까지)
function random(min, max) {
  // `.toFixed()`를 통해 반환된 문자 데이터를,
  // `parseFloat()`을 통해 소수점을 가지는 숫자 데이터로 변환
  return parseFloat((Math.random() * (max - min) + min).toFixed(2))
}

https://greensock.com/docs/v3/GSAP/gsap.to() 사이트에 들어가서 객체데이터에 들어가는 gsap.to()만의 옵션들을 보고 입력하고 공부하기! 좋은 라이브러리임


10. 고정 이미지 배경 Section

유튜브 섹션 아래 또다른 이미지 섹션 3개 제작

  1. SEASON PRODUCT : 이 섹션에 .floating3가 짤리기에 같이 수정 必
  2. RESERVE COFFEE
  3. PICK YOUR FAVORITE

1. HTML

<!--SEASON PRODUCT-->
<section class="season-product">
  <div class="inner">

    <img src="./images/floating3.png" alt="Icon" class="floating floating3" />
    <img src="./images/season_product_image.png" alt="아이스 커피 블렌드" class="product" />

    <div class="text-group">
      <img src="./images/season_product_text1.png" alt="상쾌하게 여름을 반겨줄 시즌 원두 아이스 커피 블렌드" class="title" />
      <img src="./images/season_product_text2.png" alt="아프리카와 라틴 아메리카 커피의 브렌드로 시트러스함과 은은한 캐러멜 향을 동시에 느낄 수 있으며, 차갑게 즐길 때 풍미가 더욱 깊어지는 원두입니다." class="description" />
      <div class="more">
        <a href="javascript:void(0)" class="btn">자세히 보기</a>
      </div>
    </div>

  </div>
</section>


<!--RESERVE COFFEE-->
<section class="reserve-coffee">
  <div class="inner">

    <img src="./images/reserve_logo.png" alt="" class="reserve-logo" />
    <div class="text-group">
      <img src="./images/reserve_text.png" alt="" class="description" />
      <div class="more">
        <a href="javascript:void(0)" class="btn btn--gold">자세히 보기</a>
      </div> <!--버튼이 잘 안보여 btn--gold로-->
    </div>
    <img src="./images/reserve_image.png" alt="" class="product" />

  </div>
</section>


<!--PICK YOUR FAVORITE-->
<section class="pick-your-favorite">
  <div class="inner">

    <div class="text-group">
      <img src="./images/favorite_text1.png" alt="PICK YOUR FAVORITE" class="title" />
      <img src="./images/favorite_text2.png" alt="다양한 메뉴를 스타벅스에서 즐겨보세요." class="description" />
      <div class="more">
        <a href="javascript:void(0)" class="btn btn--white">자세히 보기</a>
      </div>
    </div>

  </div>
</section>
  • 'SEASON PRODUCT', 'RESERVE COFFEE', 'PICK YOUR FAVORITE' 다 같은 구조로 작성
  • 'SEASON PRODUCT'에 .floating3를 그대로 복사해서.inner에 붙임

2. CSS

/*SEASON PRODUCT*/
.season-product {
  background-image: url("../images/season_product_bg.jpg");
}
.season-product .inner {
  height: 400px;
}
.season-product .floating3 { /* 수정 必 */
  position: absolute;
  top: -200px; /* 배치 기준이 바뀌었기에 top로 수정 */
  right: 0;
}
.season-product .text-group {
  position: absolute; /* inner에 relative 할당 */
  top: 110px;
  right: 100px;
}
.season-product .text-group .title {
  margin-bottom: 10px;
}
.season-product .text-group .description {
  margin-bottom: 15px;
}

/*RESERVE COFFEE*/
.reserve-coffee {
  background-image: url("../images/reserve_bg.jpg");
}
.reserve-coffee .inner {
  height: 400px;
}
.reserve-coffee .reserve-logo {
  position: absolute;
  top: 110px;
  left: 0;
}
.reserve-coffee .text-group {
  position: absolute;
  top: 124px;
  left: 208px;
}
.reserve-coffee .product {
  position: absolute;
  top: 0;
  right: 0;
}

/*PICK YOUR FAVORITE*/
.pick-your-favorite {
  background-image: url("../images/favorite_bg.jpg");
  background-repeat: no-repeat;
  background-position: center;
  background-attachment: fixed; 
  background-size: cover; /* 폭이 1920px로 늘어남 */
}
.pick-your-favorite .inner {
  padding: 110px 0; /* 글 위아래 여백 */
}
.pick-your-favorite .text-group {
  width: 362px; /* 제한 */
  margin-left: 100px; /* 위치조정 */
  display: flex;
  justify-content: flex-end; /* 우측으로 끝맞춤 */
  flex-wrap: wrap; /* 줄바꿈 가능 */
}
.pick-your-favorite .text-group .title {
  margin-bottom: 40px;
}
.pick-your-favorite .text-group .description {
  margin-bottom: 40px;
}
  • SEASON PRODUCT : .floating3 수정 必, 기준이 바뀌니 top, bottom 구별 꼭!
  • RESERVE COFFEE : 'SEASON PRODUCT'와 비슷
  • PICK YOUR FAVORITE : background-attachment: fixed;를 활용해 배경을 뷰포트에 고정시켜 스크롤해도 배경이 안움직이는 간단한 패럴랙스 효과 구현

※ 위코드의 패럴랙스 효과 구현 해설
1. 배경 이미지 삽입
2. 배경 이미지 반복 x
3. 배경 이미지를 센터로 정렬
4. 배경 이미지를 뷰포트 기준으로 출력해 스크롤해도 움직이지 않게 고정
5. 배경 이미지가 왜곡이 일어나지 않는 한도 내까지 늘어나게 만들기


11. 3D 애니메이션 Section

  • 10번에서 배운 패럴랙스 효과 구현
  • hover되면 3D로 돌아가는 애니메이션 제작

1. HTML

<!--RESERVE STORE-->
<section class="reserve-store">
  <div class="inner">

    <div class="medal">
      <div class="front">
        <img src="./images/reserve_store_medal_front.png" alt="R">
      </div>
      <div class="back">
        <img src="./images/reserve_store_medal_back.png" alt="스타벅스 리저브 매장">
        <a href="javascript:void(0)" class="btn">
          매장안내
        </a>
      </div>
    </div>

  </div>
</section>
  • 메달에 프론트와 백을 따로 두어 앞면, 뒷면 이미지 따로 설정 가능한 구조로 작성

2. CSS

/*RESERVE STORE*/
.reserve-store { /* 패럴랙스 */
  background-image: url("../images/reserve_store_bg.jpg");
  background-repeat: no-repeat;
  background-position: center;
  background-attachment: fixed;
  background-size: cover;
}
.reserve-store .inner {
  height: 600px;
  display: flex;
  justify-content: center;
  align-items: center;
}
.reserve-store .medal {
  width: 334px;
  height: 334px;
  perspective: 600px; /* 자연스런 회전을 위해 원근감 부여 */
}
.reserve-store .medal .front,
.reserve-store .medal .back {
  width: 334px;
  height: 334px;
  position: absolute;
  transition: 1s;
  backface-visibility: hidden; /* 뒷면은 화면 표시 x */
}
.reserve-store .medal .front {
  transform: rotateY(0deg);
}
.reserve-store .medal:hover .front {
  transform: rotateY(180deg);
}
.reserve-store .medal .back {
  transform: rotateY(-180deg); /* 회전 방향을 설정위해 -를 붙임 */
}
.reserve-store .medal:hover .back {
  transform: rotateY(0deg);
}
.reserve-store .medal .back .btn {
  position: absolute;
  top: 230px;
  left: 0;
  right: 0;
  margin: auto;
}
  • :hover, perspective, transform: rotateY(+-180, 0deg);, backface-visibility: hidden;, transition 활용
  • transform: rotateY(0deg);은 안써줘도 되지만 명확히 표시 및 구형의 브라우저에서도 시작점을 명확히 알려 돌아가게끔 만들어줌
  • .front에서 0 - 180 .back에서 180 - 0 방향을 자연스럽게 줘야하기에 .back에서 -180도에서 출발

12. 스크롤 위치 계산 애니메이션

  • 추가적인 이미지 섹션 'FIND STORE' 요소 추가
  • 스크롤 하면 섹션에 추가했던 요소들에 순차적으로 나오는 애니메이션을 추가

FIND STORE 요소 추가

1. HTML

<!--FIND THE STORE-->
<section class="find-store">
  <div class="inner">

    <img src="./images/find_store_texture1.png" alt="" class="texture1" />
    <img src="./images/find_store_texture2.png" alt="" class="texture2" />
    <img src="./images/find_store_picture1.jpg" alt="" class="picture1" />
    <img src="./images/find_store_picture2.jpg" alt="" class="picture2" />
    <div class="text-group">
      <img src="./images/find_store_text1.png" alt="스타벅스를 가까이에서 경험해보세요." class="title" />
      <img src="./images/find_store_text2.png" alt="고객님과 가장 가까이 있는 매장을 찾아보세요!" class="description" />
      <div class="more">
        <a href="javascript:void(0)" class="btn">매장찾기</a>
      </div>
    </div>

  </div>
</section>

2. CSS

/*FIND STORE*/
.find-store {
  background-image: url("../images/find_store_bg.jpg");
}
.find-store .inner {
  height: 400px;
}
.find-store .texture1 {
  position: absolute;
  top: 0;
  left: 400px;
}
.find-store .texture2 {
  position: absolute;
  bottom: 0;
  right: 0;
}
.find-store .picture {
  border-radius: 50%; /* 원만들기 */
  box-shadow: 2px 2px 8px 0 rgba(0,0,0,.5);
  position: absolute;
}
.find-store .picture1 {
  top: -60px;
  left: 0;
}
.find-store .picture2 {
  top: 150px;
  left: 250px;
}
.find-store .text-group {
  position: absolute;
  top: 120px;
  left: 550px;
}
.find-store .text-group .title {
  margin-bottom: 20px; /* 제목 - 설명 여백 */
}
.find-store .text-group .description {
  margin-bottom: 20px; /* 설명 - 버튼 여백 */
}

스크롤 위치 계산 애니메이션 추가

ScrollMagic JS 라이브러리 학습, 이런 것도 있구나~

1. HTML

  • ScrollMagic.min cdn 추가
  • 'SEASON PRODUCT', 'RESERVE COFFEE', 'PICK YOUR FAVORITE', 'FIND STORE' 이미지들에 각각 맞는 애니메이션 클래스 부여

2. CSS

/* COMMON */
/*BACK TO POSITION*/
.back-to-position {
  opacity: 0;
  transition: 1s;
}
.back-to-position.to-right {
  transform: translateX(-150px);
}
.back-to-position.to-left {
  transform: translateX(150px);
}
.show .back-to-position {
  opacity: 1;
  transform: translateX(0);
}
.show .back-to-position.delay-0 {
  transition-delay: 0s;
}
.show .back-to-position.delay-1 {
  transition-delay: .3s;
}
.show .back-to-position.delay-2 {
  transition-delay: .6s;
}
.show .back-to-position.delay-3 {
  transition-delay: .9s;
}
  • 전역 COMMON 속성에 작성

    애니메이션 스타일 클래스 해설

    • .back-to-position : 투명하게, 애니 1초
    • .to-right / to-left : 각각 -150px, 150px에서 출발점
    • .show .back-to-position : JS로 .show가 붙으면 원점(0)으로 이동하면서 불투명하게 변화
    • .delay-N : 애니 시작 딜레이를 줘 더욱 스타일리쉬한 효과 추가

3. JS

/**
 * 요소가 화면에 보여짐 여부에 따른 요소 관리
 */
// 관리할 요소들 검색!
const spyEls = document.querySelectorAll('section.scroll-spy');
// 요소들 반복 처리!
spyEls.forEach(function (spyEl) {
  new ScrollMagic // 여기 생성자는 .XXXX = 메소드로 제어 중, 메소드가 길어지니 줄바꿈
    .Scene({ // Scene(특정한 요소를 감시할 장면)을 추가
      triggerElement: spyEl, // 보여짐 여부를 감시할 요소를 지정
      triggerHook: .8 // 실행될 애니를 지금 보는 화면 0.8, 80% 지점에서 실행!
    })
    .setClassToggle(spyEl, 'show') // 토글: 넣다뺐다, 요소가 화면에 보이면 show 클래스 추가
    .addTo(new ScrollMagic.Controller()); // 컨트롤러에 장면을 할당(필수!)
});
  • ScrollMagic JS 라이브러리 : 각각의 지정된 클래스들을 지속적으로 감시하다가 지정해놓은 지점이 지나면 .show 클래스를 추가함!
  • JS로 이제 클래스 추가, 제거 토글을 만들었으니 그 클래스 가지고 CSS로 애니메이션 처리 하면 됨!

13. 다중 요소 슬라이드

Awards 수평 슬라이드 만들기! Promotion 섹션 만들 때랑 비슷하다!
위에서 했던 수평 슬라이드를 만들고, 아이콘도 삽입하기

1. HTML

<!--AWARDS-->
<section class="awards">
  <div class="inner">

    <div class="swiper-container">
      <div class="swiper-wrapper">
        <div class="swiper-slide">
          <img src="./images/awards_slide1.jpg" alt="대통령 표창" />
        </div>
        <div class="swiper-slide">
          <img src="./images/awards_slide2.jpg" alt="대통령 표창 (3년 연속)" />
        </div>
        <div class="swiper-slide">
          <img src="./images/awards_slide3.jpg" alt="우수사업주 인증" />
        </div>
        <div class="swiper-slide">
          <img src="./images/awards_slide4.jpg" alt="경연대회 대상" />
        </div>
        <div class="swiper-slide">
          <img src="./images/awards_slide5.jpg" alt="대한상의회장상" />
        </div>
        <div class="swiper-slide">
          <img src="./images/awards_slide6.jpg" alt="기업사회공헌 활동 부문" />
        </div>
        <div class="swiper-slide">
          <img src="./images/awards_slide7.jpg" alt="KSI 1위 (5년 연속)" />
        </div>
        <div class="swiper-slide">
          <img src="./images/awards_slide8.jpg" alt="KS-SQI 1위 (5년 연속)" />
        </div>
        <div class="swiper-slide">
          <img src="./images/awards_slide9.jpg" alt="커피전문점 부문 (4년 연속)" />
        </div>
        <div class="swiper-slide">
          <img src="./images/awards_slide10.jpg" alt="동반성장 부문 (4년 연속)" />
        </div>
      </div>
    </div>

    <div class="swiper-prev">
      <span class="material-icons">arrow_back</span>
    </div>
    <div class="swiper-next">
      <span class="material-icons">arrow_forward</span>
    </div>

  </div>
</section>
  • Promotion 섹션에서 만든 구조와 같이 작성
  • 지시할 아이콘을 만들어야하니 Promotion처럼 .swiper-prev·next를 만들기

2. CSS

/*AWARDS*/
.awards {
  background-color: #272727;
}
.awards .inner {
  padding: 40px 0;
}
.awards .swiper-container {
  width: 100%;
  height: 40px;
}
.awards .swiper-prev,
.awards .swiper-next {
  width: 42px;
  height: 42px;
  outline: none;
  border: 2px solid #fff;
  border-radius: 50%;
  color: #fff;
  position: absolute;
  top: 0;
  bottom: 0;
  margin: auto;
  opacity: .3;
  cursor: pointer;
  display: flex;
  justify-content: center;
  align-items: center;
  transition: .4s;
}
.awards .swiper-prev {
  left: -100px;
}
.awards .swiper-next {
  right: -100px;
}
.awards .swiper-prev:hover,
.awards .swiper-next:hover {
  background-color: #fff;
  color: #333;
}
  • 이미지와 통일성있게 배경을 똑같이 하고 배치 및 width: 100%;, 높이 디자인
  • .swiper-prev·next 디자인과 .inner의 위치 기준의 -100px로 배치

3. JS

new Swiper('.awards .swiper-container', {
  // direction: 'horizontal', // 수평 슬라이드
  autoplay: true, // 자동 재생 여부
  loop: true, // 반복 재생 여부
  spaceBetween: 30, // 슬라이드 사이 여백
  slidesPerView: 5, // 한 번에 보여줄 슬라이드 개수
  // slidesPerGroup: 5, // 한 번에 슬라이드 할 개수(전체 개수로 나뉘어야 함)
  navigation: { // 슬라이드 이전/다음 버튼 사용 여부
    prevEl: '.awards .swiper-prev', // 이전 버튼 선택자
    nextEl: '.awards .swiper-next' // 다음 버튼 선택자
  }
})
  • Promotion와 같게 생성자를 써서 슬라이드 되게 만듦
  • navigation:{prevEl·nextEl: '요소'}를 통해 이전/다음 버튼 사용

14. Footer Section

  • 사이트 맨 아래 방침, 약관과 사업자 번호, 대표, 전화번호 등 회사의 정보를 기입하는 섹션을 만들어보자!
  • 날짜가 들어가는 영역이 있으면 연이나 달이 바뀌면 일일이 바꿔줘야 하지만 JS로 자동으로 수정될 수 있게 만들자!
  • 맨 위쪽으로 올라가는 아이콘을 삽입해 일정 이상 스크롤을 내리면 아이콘이 나오고 맨 위에서는 삭제되는 동작 삽입!

푸터

1. HTML

&XXX; : HTML Entity 구글링, HTML에서 특수기호를 손으로 직접 치면 안나오는 경우가 있기 때문에(<,>,= 등등) XXX에 그 특수기호 이름이나 숫자를 써 특정한 코드를 작성해 그대로 화면에 출력되게 만드는 걸 배우자!

<!--FOOTER-->
<footer>
  <div class="inner">


    <ul class="menu">
      <li><a href="javascript:void(0)" class="green">개인정보처리방침</a></li>
      <li><a href="javascript:void(0)">영상정보처리기기 운영관리 방침</a></li>
      <li><a href="javascript:void(0)">홈페이지 이용약관</a></li>
      <li><a href="javascript:void(0)">위치정보 이용약관</a></li>
      <li><a href="javascript:void(0)">스타벅스 카드 이용약관</a></li>
      <li><a href="javascript:void(0)">윤리경영 핫라인</a></li>
    </ul>

    <div class="btn-group">
      <a href="javascript:void(0)" class="btn btn--white">찾아오시는 길</a>
      <a href="javascript:void(0)" class="btn btn--white">신규입점제의</a>
      <a href="javascript:void(0)" class="btn btn--white">사이트 맵</a>
    </div>

    <div class="info">
      <span>사업자등록번호 201-81-21515</span>
      <span>(주)스타벅스 코리아 대표이사 이석구</span>
      <span>TEL : 02) 3015-1100 / FAX : 02) 3015-1106</span>
      <span>개인정보 책임자 : 강기원</span>
    </div>

    <p class="copyright">
      &copy; <span class="this-year"></span> Starbucks Coffee Company. All Rights Reserved.
    </p>
    <img src="./images/starbucks_logo_only_text.png" alt="STAR BUCKS" class="logo" />


  </div>
</footer>
  • footer 태그로 시작!
  • &copy; : 엠퍼센드으로 시작돼 세미콜론이 사용된 copy라는 HTML의 특수 기호, 해당하는 내용의 문자가 화면으로 출력됨! - ©
  • .this-year는 비어있지만 나중에 JS로 제어해서 연도를 나타낼거임!

2. CSS

/*FOOTER*/
footer {
  background-color: #272727;
  border-top: 1px solid #333;
}
footer .inner {
  padding: 40px 0 60px 0;
}
footer .menu {
  display: flex;
  justify-content: center;
} /* 메뉴 수평 정렬 */
footer .menu li {
  position: relative;
}
footer .menu li::before { /* 가상요소선택자를 만들어 HTML에 각각 입력 안해도 됨! */
  content: ""; /* 필수 */
  width: 3px;
  height: 3px;
  background-color: #555;
  position: absolute; /* block으로 바뀜 */
  top: 0;
  bottom: 0;
  right: -1px;
  margin: auto;
} /* 사이사이 점들 만들기 */
footer .menu li:last-child::before {
  display: none;
} /* 끝에는 필요 없기에 :last-child라는 가상 선택자를 이용해 마지막껀 없앰 */
footer .menu li a {
  display: block;  /* 사용자가 클릭할 수 있는 영역을 더 넓혀주려고 block */
  color: #CCC;
  font-size: 12px;
  font-weight: 700;
  padding: 15px;
}
footer .menu li a.green {
  color: #669900;
}
footer .btn-group {
  margin-top: 20px;
  display: flex;
  justify-content: center;
}
footer .btn-group .btn {
  font-size: 12px;
  margin-right: 10px;
}
footer .btn-group .btn:last-child {
  margin-right: 0;
}
footer .info {
  margin-top: 30px;
  text-align: center; /* 문자 가운데 정렬 */
}
footer .info span {
  margin-right: 20px;
  color: #999;
  font-size: 12px;
}
footer .info span:last-child {
  margin-right: 0;
} /* 우측 여백 삭제 */
footer .copyright {
  color: #999;
  font-size: 12px;
  text-align: center; /* 텍스트는 text-align: center로 가운데 정렬 */
  margin-top: 12px;
}
footer .logo {
  margin: 30px auto 0; /* 이미지는 margin: auto로 가운데 정렬 */
}
  • 각각 .menu, .btn, .copyright, .logo 요소들 배치

3. JS

/**
 * 올해가 몇 년도인지 계산
 */
const thisYear = document.querySelector('.this-year')
thisYear.textContent = new Date().getFullYear() 
  • Date객체를 생성자 함수로 날짜 계산, getFullYear()라는 메소드는 현재 날짜를 숫자 데이터로 반환

ScrollTo

ScrollTo는 기본 GSAB cdn에 없다. 왜냐하면 한 파일에 잡다한 기능까지 다 있으면 파일이 무거워져 렌더링하는데 로딩이 오래 걸린다. 그래서 필수 기능만 담고 나머지는 따로 불러와야하는데 대표적인게 ScrollTo다.

1. HTML

<!--TO TOP BUTTON-->
<div id="to-top">
  <div class="material-icons">arrow_upward</div>
</div>
  • ScrollTo Plugin cdn 작성
  • 상단으로 올라갈 아이콘 작성

2. CSS

/*SCROLL TO TOP*/
#to-top {
  position: fixed;
  bottom: 30px;
  right: 30px;
  z-index: 9;
  width: 42px;
  height: 42px;
  background-color: #333;
  color: #fff;
  border: 2px solid #fff;
  border-radius: 10px;
  cursor: pointer;
  display: flex;
  justify-content: center;
  align-items: center;
}
  • 뷰포트로 고정해 스크롤을 내리든 말든 보이게
  • z-index 값도 9로 설정에 맨 앞으로 배치
  • 아이콘 가운데 정렬!

3. JS

const toTopEl = document.querySelector('#to-top')
// window: 윈도우 객체, 윈도우 창을 뜻함, 우리가 보는 화면 자체
window.addEventListener('scroll', _.throttle(function () { // lodash 라이브러리를 통해 등록 후 여기서 사용
  console.log(window.scrollY);
  if (window.scrollY > 500) { // 스크롤 될 때마다 윈도우의 객체 부분의 속성 Y의 값이(스크롤의 위치 몇픽셀) 갱신되는 걸 알려줌
    
    // 상단으로 스크롤 버튼 보이기!
    gsap.to(toTopEl, .2, {
      x: 0
    });
    
  } else {
    // 상단으로 스크롤 버튼 숨기기!
    gsap.to(toTopEl, .2, {
      x: 100
    });
  }
}, 300)); // 300 ms라는 뜻, 스크롤을 굴려도 0.3초마다 실행되게!
// _.throttle(함수() {}, 시간)

// 상단으로 스크롤 버튼을 클릭하면,
toTopEl.addEventListener('click', function () {
  // 페이지 위치를 최상단으로 부드럽게(0.7초 동안) 이동.
  gsap.to(window, .7, {
    scrollTo: 0
  })
});
  • 스크롤에 영향 받는 뱃지를 기준으로 뱃지가 나오면 오른쪽으로 숨고, 뱃지가 사라지면 원 위치하는 동작 구현
    x축으로 100px로 이동하게 만듦
  • 아이콘을 배치했으니 상단으로 스크롤 버튼을 클릭하면 올라가는 동작 구현, 클릭 이벤트 추가
    window가 0.7초 동안 위치가 0으로 부드럽게 올라가게!

사이트 구현은 모두 끝났다!! 이제 node.js로 가서 모듈 일치, 서버 구현 등 백엔드 지식을 쌓아보자!

🦏

profile
코뿔소처럼 저돌적으로

0개의 댓글