안녕하세요.
이 공간은 제가 프론트엔드를 처음 접하며 배운 것을 주저리주저리 쓰는 공간입니다.
이번 내용은 Starbucks clone coding 1편입니다.

그런데 이걸 일일히 글로 설명하면서 작성하기엔
저같은 코린이는 벅차더라구요.
그래서 결과물 코드를 작성하고,
생각나는 곳에 간단한 설명을 덧붙이는 방식으로 진행하려 합니다.

(지금까지 header영역과 badge정도만 작업을 했어요.)

html

<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Starbucks Coffee Korea</title>

  <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="스타벅스는 세계에서 가장 큰 다국적 커피 전문점으로, 64개국에서 총 23,187개의 매점을 운영하고 있습니다." />
  <meta property="og:image" content="./images/starbucks_seo.jpg" />
  <meta property="og:url" content="https://starbucks.co.kr" />

  <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="스타벅스는 세계에서 가장 큰 다국적 커피 전문점으로, 64개국에서 총 23,187개의 매점을 운영하고 있습니다." />
  <meta property="twitter:image" content="./images/starbucks_seo.jpg" />
  <meta property="twitter:url" content="https://starbucks.co.kr" />

  <link rel="icon" href="./favicon.png" />
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reset-css@5.0.1/reset.min.css" />
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link
    href="https://fonts.googleapis.com/css2?family=Nanum+Gothic:wght@400;700&family=Noto+Sans+KR:wght@100;300;400;500;700;900&display=swap"
    rel="stylesheet">
  <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
  <link rel="stylesheet" href="./css/main.css" />
  
  <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.3/gsap.min.js" integrity="sha512-gmwBmiTVER57N3jYS3LinA9eb8aHrJua5iQD7yqYCKa5x6Jjc7VDVaEA0je0Lu0bP9j7tEjV3+1qUm6loO99Kw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
  <script defer src="./js/main.js"></script>
</head>
<body>

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

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

      <div class="sub-menu">
        <ul class="menu">
          <li>
            <a href="/signin">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>

      <ul class="main-menu"> 
        <li class="item">
          <div class="item__name">COFFEE</div>
          <div class="item__contents">
            <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>
        <li class="item">
          <div class="item__name">MENU</div>
          <div class="item__contents">
            <div class="contents__menu">
              <ul class="inner">
                <li>
                  <h4>음료</h4>
                  <ul>
                    <li>콜드 브루</li>
                    <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>
                    <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>e-Gift 카드</li>
                  </ul>
                </li>
                <li>
                  <h4>메뉴 이야기</h4>
                  <ul>
                    <li>콜드 브루</li>
                    <li>스타벅스 티바나</li>
                  </ul>
                </li>
              </ul>
            </div>
            <div class="contents__texture">
              <div class="inner">
                <h4 class="new">스타벅스 티바나</h4>
                <p>다양한 찻잎과 향신료 등 개성있는 재료로 새로운 맛과 향의 티를 선보입니다.</p>
              </div>
            </div>
          </div>
        </li>
        <li class="item">
          <div class="item__name">STORE</div>
          <div class="item__contents">
            <div class="contents__menu">
              <ul class="inner">
                <li>
                  <h4>매장 찾기</h4>
                  <ul>
                    <li>퀵 검색</li>
                    <li>지역 검색</li>
                    <li>My 매장</li>
                  </ul>
                </li>
                <li>
                  <h4>매장 이야기</h4>
                  <ul>
                    <li>청담스타</li>
                    <li>티바나 인스파이어드 매장</li>
                    <li>파미에파크</li>
                  </ul>
                </li>
              </ul>
            </div>
            <div class="contents__texture">
              <div class="inner">
                <h4>매장 찾기</h4>
                <p>보다 빠르게 매장을 찾아보세요.</p>
                <h4 class="new">청담스타</h4>
                <p>스타벅스 1,000호점인 청담스타점을 만나보세요.</p>
              </div>
            </div>
          </div>
        </li>
        <li class="item">
          <div class="item__name">RESPONSIBILITY</div>
          <div class="item__contents">
            <div class="contents__menu">
              <ul class="inner">
                <li>
                  <h4>지역 사회 참여 활동</h4>
                  <ul>
                    <li>회망배달 캠페인</li>
                    <li>재능기부 카페 소식</li>
                    <li>커뮤니티 스토어</li>
                    <li>청년인재 양성</li>
                    <li>우리 농산물 사랑 캠페인</li>
                    <li>우리 문화 지키기</li>
                  </ul>
                </li>
                <li>
                  <h4>환경보호 활동</h4>
                  <ul>
                    <li>환경 발자국 줄이기</li>
                    <li>일회용 컵 없는 매장</li>
                    <li>커피 원두 재활용</li>
                  </ul>
                </li>
                <li>
                  <h4>윤리 구매</h4>
                  <ul>
                    <li>윤리적 원두 구매</li>
                    <li>공정무역 인증</li>
                    <li>커피 농가 지원 활동</li>
                  </ul>
                </li>
                <li>
                  <h4>글로벌 사회 공헌</h4>
                  <ul>
                    <li>윤리경영 보고서</li>
                    <li>스타벅스 재단</li>
                    <li>지구촌 봉사의 달</li>
                  </ul>
                </li>
              </ul>
            </div>
            <div class="contents__texture">
              <div class="inner">
                <h4>커피원두 재활용</h4>
                <p>스타벅스 커피 원두를 재활용 해보세요.</p>
              </div>
            </div>
          </div>
        </li>
        <li class="item">
          <div class="item__name">MY STARBUCKS REWARDS</div>
          <div class="item__contents">
            <div class="contents__menu">
              <ul class="inner">
                <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>
                    <li>자주하는 질문</li>
                  </ul>
                </li>
                <li>
                  <h4>스타벅스 카드 e-Gift</h4>
                  <ul>
                    <li>스타벅스 카드 e-Gift 소개</li>
                    <li>이용안내</li>
                    <li>선물하기</li>
                    <li>자주하는 질문</li>
                  </ul>
                </li>
              </ul>
            </div>
            <div class="contents__texture">
              <div class="inner">
                <h4>스타벅스 카드 등록하기</h4>
                <p>카드 등록 후 리워드 서비스를 누리고 사용내역도 조회해보세요.</p>
              </div>
            </div>
          </div>
        </li>
        <li class="item">
          <div class="item__name">WHAT'S NEW</div>
          <div class="item__contents">
            <div class="contents__menu">
              <ul class="inner">
                <li>
                  <h4>프로모션 & 이벤트</h4>
                  <ul>
                    <li>전체</li>
                    <li>스타벅스 카드</li>
                    <li>마이 스타벅스 리워드</li>
                    <li>온라인</li>
                    <li>2017 스타벅스 플래너</li>
                  </ul>
                </li>
                <li>
                  <h4>새소식</h4>
                  <ul>
                    <li>전체</li>
                    <li>상품 출시</li>
                    <li>스타벅스의 문화</li>
                    <li>스타벅스 사회공헌</li>
                    <li>스타벅스 카드출시</li>
                  </ul>
                </li>
                <li>
                  <h4>매장별 이벤트</h4>
                  <ul>
                    <li>일반 매장</li>
                    <li>신규 매장</li>
                  </ul>
                </li>
              </ul>
            </div>
            <div class="contents__texture">
              <div class="inner">
                <h4>매장별 이벤트</h4>
                <p>스타벅스의 매장 이벤트 정보를 확인 하실 수 있습니다.</p>
                <h4>소셜 스타벅스</h4>
                <p>다양한 스타벅스 SNS 채널을 통해 스타벅스를 만나보세요!</p>
              </div>
            </div>
          </div>
        </li>
      </ul>

    </div>

    <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>

  </header>
</body>

</html>

og..?
twitter?!
오픈그래프와 트위터 카드라는게 있다는 걸 처음 알았습니다.

open grahp와 twitter card를 처음 접했습니다.
누군가에게 이 사이트를 보여줄 때 보여줄 정보를 우리가 직접 입력하는건데요.
제일 상단쪽에 meta tag를 이용해 선언합니다.
그래야 최적화에 유리하니까요.


그리고 BEM방식을 이용해서 class명을 부여해줬어요.

<div class="container">
  <div class="name"><div>
  <div class="item"></div>
    <div class="name"></div>
  </div>
</div>

위 예시처럼 정신이 혼미해지는 class명을 지어주면 답 없습니다.
css부터 거하게 말아먹을 수 있거든요.





어떻게 아냐구요?






.....뭐 어쨋던 이제는 아래처럼 BEM방식을 통해 class명을 명칭해주려고 합니다.

<div class="container">
  <div class="container__name"><div>
  <div class="item"></div>
    <div class="item__name"></div>
  </div>
</div>

하나 더 있어요.

<div class="btn primary"></div>
<div class="btn success"></div>
<div class="btn error"></div>

위 예시의 class를 보면 btn과 primary, success, error는 별개의 class같아 보입니다.
그래서 --로 상태를 나태내줄 수 있습니다.

<div class="btn btn--primary"></div>
<div class="btn btn--success"></div>
<div class="btn btn--error"></div>

btn--primary는 btn인데 상태가 primary, 즉 일반 버튼이라는 얘기입니다.
btn--success는 역시 상태가 success, 완료나 전송 버튼이다,
btn--error는 삭제 버튼이라는 상태를 명시해준거죠.
__는 앞의 요소의 일부분, --는 그 요소의 상태라고 생각하면 됩니다.


css

/* COMMON */
body {
  color: #333;
  font-size: 16px;
  font-weight: 400;
  line-height: 1.4 ;
  font-family: 'Nanum Gothic', sans-serif;
  height: 3000px;
}
img {
  display: block;
}
a {
  text-decoration: none;
}
.inner {
  width: 1100px;
  margin: 0 auto;
  position: relative;
}


/* HEADER */
header {
  /* position: relative; */
  width: 100%;
  background-color: #f6f5f0;
  border-bottom: 1px solid #c8c8c8;
  position: fixed;
  top: 0;
}
header > .inner {
  /* width: 1100px; */
  height: 120px;
  /* margin: 0 auto; */
  /* background-color: orange; */
  /* position: relative; */
}
header .logo {
  height: 75px;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  margin: auto 0;
  /* display: none; */
}
header .sub-menu {
  position: absolute;
  top: 10;
  right: 0;
  display: flex;
}
header .sub-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: "";
  position: absolute;
  width: 1px;
  height: 12px;
  background-color: #e5e5e5;
  display: block;
  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{
  display: block;
  font-size: 12px;
  padding: 11px 16px;
  color: #656565;
}
header .sub-menu ul.menu li a:hover {
  color: #000;
}
header .sub-menu .search {
  /* background-color: red; */
  height: 34px;
  position: relative;
}
header .sub-menu .search input {
  width: 36px;
  height: 34px;
  padding: 4px 10px;
  border: 1px solid #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;
}
header .sub-menu .search.focused .material-icons {
  opacity: 0;
}

header .main-menu {
  display: flex;
  position: absolute;
  bottom: 0;
  right: 0;
  z-index: 1;
}
header .main-menu .item {
  
}
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;
}
header .main-menu .item .item__contents {
  width: 100%;
  position: fixed;
  left: 0;
  display: none;
}
header .main-menu .item:hover .item__contents {
  display: block;
}
header .main-menu .item .item__contents .contents__menu {
  background-color: #2c2a29;
  /* height: 200px; */
}
header .main-menu .item .item__contents .contents__menu > ul{
  display: flex;
  padding: 20px 0;
}
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 {

} */
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 {
  /* background-color: orange;
  height: 100px; */
  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;
  /* font-size: 12px; */
}
header .main-menu .item .item__contents .contents__texture p {
  color: #669900;
  margin: 4px 0 14px;
  /* font-size: 12px; */
}
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;
}

주석처리 된 곳들은 대부분 영역을 확인하기 위해 작성했던 코드들이에요.
다만, 포지션의 값들은 변하는 부분들이 생기면서 없어지기도 했네요.
inner를 하위선택자가 아닌 자식선택자로 바꿔주었구요.

전 언제 저런 코드가 바로 튀어나올까요?
에휴

javascript

const searchEl = document.querySelector('.search');
const searchInputEl = searchEl.querySelector('input');

searchEl.addEventListener('click', function () {
  searchInputEl.focus();
});

searchInputEl.addEventListener('focus', function () {
  searchEl.classList.add('focused');
  searchInputEl.setAttribute('placeholder', '통합검색');
});

searchInputEl.addEventListener('blur', function () {
  searchEl.classList.remove('focused');
  searchInputEl.setAttribute('placeholder', '');
});


const badgeEl = document.querySelector('header .badges')

window.addEventListener('scroll', _.throttle(function () {
  console.log(window.scrollY);
  if (window.scrollY > 500) {
    gsap.to(badgeEl, .6, {
      opacity: 0,
      display: 'none'
     });
  } else {
    gsap.to(badgeEl, .6, {
      opacity: 1,
      display: 'block'
    });
  }
}, 300));

gsap이 등장했어요.
애니메이션처리를 위해 쓰이고, 기본적인 문법이에요.
gsap.to(요소, 지속시간, {옵션}));
옵션은 {}로 객체데이터로 사용합니다.
지속시간은 millisecond가 아닌 일반 초단위를 사용하면 되구요.
외부링크를 hrml에서 script로 연결해서 사용합니다.

근데 저는 gsap.을 입력하면 자꾸 뭐가 자동완성되버려요.
그래서 gsap .to 이렇게 써놓고 .to를 한 칸 들여서 사용했습니다.
해결방법 아시는분...?


그리고 opacity속성처럼 값을 숫자로 입력하는 속성은
전환효과(transition 혹은 gsap)를 통해 요소 전후상태를 중간 숫자의 값으로 자연스러운 전환효과가 가능합니다.
하지만, display 속성처럼 값이 숫자가 아닌 속성은 전후상태 중간값이 없으므로, 자연스러운 전환효과가 어려워요.


그리고 css에서 badge를 달아줬는데요.
addEvenetListener에 '_.throttle()'를 사용했습니다.

window.addEventListener('scroll', function () {
  console.log('scroll!');
});

이렇게 작성하면 스크롤을 끝까지 한 번 내렸을 뿐인데 350개의 'scroll!'이 찍히는 걸 볼 수 있습니다.
나중에 점점 더 커다란 프로젝트를 진행할 때 이러면 골치가 아프겠죠.
그래서 아래 함수로 바꿔줍니다.

window.addEventListener('scroll', _.throttle(function () {
  console.log('scroll!');
}, 300));

throttle을 사용하고 맨 아래에 300이 붙었어요.
이는 300millisecond, 0.3초 간격으로 부하를 줘서 우르르 실행되는 걸 막아줍니다.
아래는 throttle의 기본 사용 문법입니다.

_.throttle(함수, 시간(milly second. 300=0.3초))
profile
수제 에러코드 전문점 / 불량코드 원조 맛집

0개의 댓글