[패스트캠퍼스] 프론트엔드 강의 종합반 week 5 스타벅스 클론

청수동햄주먹·2023년 3월 14일
0

목표

강사님의 깃헙페이지
웹페이지를 만들 때 할 것이 너무 많아서 우왕좌왕 할 것 같은데 어디서부터 시작하고 문제를 해결하려는 사고방식 같은 것을 주의하면서 배워보기

시작하기

프로젝트 시작

  • 필요한 이미지 준비 : images 폴더, favicon.ico, favicon.png 다운로드 해서 프로젝트 폴더에 붙여놓기
  • vscode : !+ tap html 구조 자동 완성
  • lang = "ko" 로 바꿔주기
    <html lang="ko">
  • 문자 인코딩 방식 UTF-8
    <meta charset="UTF-8"/>
  • viewport : 장비 너비만큼 1배의 크기로
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
  • title: 우리는 스타벅스 사이트를 만들고 있으니까
    <title>Starbucks Coffee Korea</title>

파비콘

탭 옆의 아이콘 띄우기

<link rel="icon" href="./favicon.png"/>
<img src="https://velog.velcdn.com/images/stel1ight/post/925cf5fd-d26b-4b61-aa59-26285b8c1054/image.png" width=150px/>

이렇게 설정을 해주지 않으면 브라우저는 자동으로 favicon.ico를 찾아 넣는다.

스타일 초기화

  • 브라우저에 따라 스타일 설정이 달라지지 않도록 reset-css설정
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reset-css@5.0.1/reset.min.css"/>
  • css폴더를 만들어서 main.css파일을 만들어서 연결해주기
     <link rel="stylesheet" href="./css/main.css"/>

오픈그래프 Open Graph Protocol

오픈 그래프 : 웹페이지가 공유될 때 우선적으로 활용 되는 메타정보

  • property="og:속성" content=""의 형태로 기술한다
    • og:type 페이지의 유형
      • 웹사이트 일 경우 content="website"
      • 비디오 일 경우 content="video.movie"
    • og:site_name 속한 사이트의 이름
    • og:title 페이지의 이름
    • og:description 페이지의 간단한 설명
    • og:image 페이지의 대표이미지 주소url
    • og:url 페이지의 주소 url
     <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" />
  • 메타 태그는 다양한 정보들을 활용할 수 있게 해준다. 메타 정보
  • 타이틀 태그와 링크태그 사이에 작성해준다
  • SEO 검색 엔진 최적화 Search Engine Optimization
    ./images/starbucks_seo.jpg 웹사이트를 노출할 수 있도록 정보를 최적화하는 작업

Twitter Cards 트위터 카드

  • property="twitter:속성" content=""의 형식으로 사용된다
    • twitter:card 카드의 유형
      • summary
      • player
    • twitter:site 속한 사이트의 이름
    • twitter:title 페이지의 이름(제목)
    • twitter:description 페이지의 간단한 설명
    • twitter:image 페이지의 대표 이미지 주소 url
    • twitter:url 페이지 주소url
     <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" />

Google Fonts

  • 사파리에서는 바탕체계열, 크롬에서는 고딕체 계열이 사용되고 있음! -> 별도의 폰트를 지정해주자
  • google fonts -> nanum 검색 -> nanum gothic 400(기본),700(두꺼움)선택 -> 링크방식 선택
    • html태그복사후 index.html에서 main.css보다 더 먼저 적용 되도록 그 위에 붙여놓기 해준다.
    • css 룰 복사후 main.css의 body부분에 붙여놓기 해준다.
  • 폰트는 사이즈가 크니까 폰트를 남발하면 안됨!

Google Material Icons

이미지나 아이콘들이 필요할 때

  • google material icons 검색 -> getting started -> quick start(CDN)
  • main.css 링크 태그 위에 material-icons 링크태그 붙이기
      <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons"/>
  • 아이콘 사용 방법
    • class="material-icons"
    • 아이콘 이름을 태그 사이에 넣어주면 된다
    <span class="material-icons">login</span>

header

데모의 헤더는 총 네부분으로 구성되어 있다
|로|서브메뉴|
|고|메인메뉴 |
뱃지

헤더는 스크롤 위치에 상관 없이 항상 위에 다른요소보다 떠있어야 함

  • header {}
    • position: fixed;
    • z-index: 1;

로고

HTML

  • 바디 안에서 위아래 공간을 만들어 주고 <!--HEADER-->주석을 달아 헤더임을 명시
  • div class="header" or <header>태그 만들어주기
  • 헤더 안에 div class="inner"
  • a href="/" class="logo" 로고를 클릭하면 메인 페이지로 이동할 수 있게한다
  • img src="./images/starbucks_logo.png" alt="STARBUCKS"

CSS

  • body
    • line-height: 1.4; 폰트사이즈로 설정한 1.6px 의 1.4배 되는 줄 높이 설정
  • /* HEADER */ 주석 추가로 헤더 css임을 명시. 그
  • header{}
  • header .inner{}
    • width: 1100px; 가로폭 전체를 사용하지 않을 것임
    • margin: 0 auto; 외부여백. 위아래는 여백이 없고 좌우만 자동으로 중앙에 위치시켜주기
      --- 여기까지 왔을 때 로고를 잘 보면 위는 화면 위쪽에 붙어 있는데 아래쪽만 떠있는 것을 확인 할 수 있다
      --- 이유? 이미지 태그는 inline요소임. 글자 처럼 다뤄지는데 글자의 경우 xyz처럼 소문자를 작성할 때 y가 baseline을 넘어서 쓰여지기게 됨. 따라서 로고가 baseline위에 떠있게 된다.
      --- 어떻게 해결할까? block으로 바꿔준다.
  • img{}
    • display:block;
      --- 로고가 헤더의 부분의 위아래에 꽉차게 보여진다.
  • 로고가 헤더영역에서 높이의 가운데에 놓이려면 -> .inner 자체도 높이 값을 가져야 한다
    • header.inner{}
      • height: 120px;
      • position: relative; 로고를 헤더 중간에 위치시키기 위해서 부모요소인 inner의 position 값도 설정해야 한다
    • header .logo{}
      • height: 75px; 이 로고 자체의 높의값 할당
      • position: absolute; 부모요소기준으로 배치하겠다 -> 부모요소(.inner)도 position설정해줘야 한다.
      • top: 0;
      • bottom: 0;
      • left: 0; .inner의 왼쪽 시작 부분에 배치해주기
      • margin: 0 auto; top,bottom 의 0 지점부터 계산해서 위아래 중간에 요소를 위치시킨다. 이 과정에서 높이 값이 필요!

서브메뉴

HTML
.inner 안, .logo 아래에 .sub-menu div를 만들어준다

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

메뉴 클릭시 이동

  • a를 이용해서 링크를 걸어준다.
  • href="javascript:void(0)" 아직 링크를 걸 주소페이지를 만들지 않았으므로 클릭 해도 아무런 효과를 만들어내지 않게 한다
    • "#" 을 해도 됨

서브메뉴 제위치로 이동시키기

.inner 안의 오른쪽 상단에 위치해야 한다

  • header .sub-menu {}
  • header .sub-menu ul.menu {}
    • display: flex; 수직으로 쌓여 있었던 메뉴 요소들을 수평으로 만들어 주기
    • font-family: Arial, sans-serif; 메뉴에는 고딕체가 예쁘지 않으므로 브라우저에 arial체가 있으면 적용시켜주고 아니면 sans-serif체중 하나로 적용해주기
  • header .sub-menu ul.menu li {}
  • header .sub-menu ul.menu li a{}
    • padding: 11px 16px; 사용자가 클릭할수 있는 영역을 확보해주기
    • display: block; 위의 padding을 적용 시키려면 글자요소가 아닌 블록요소가 되어야 한다.
  • a {} 에이태그 전체에 적용해주고 싶음
    • text-decoration: none; 밑줄 없애주기
  • header .sub-menu ul.menu li a:hover {}
    클릭할 수 있는 요소라는 것을 더욱 표시해주기

수직 구분선

  • header .sub-menu ul.menu li {}
    • position: relative; before가상 선택자의 위치조정을 위해 속성지정
  • header .sub-menu ul.menu li::before {}
    • content: ""; 내용이 없어도 꼭 있어야 하는 요소. 이 콘텐트 값이 없으면 가상요소는 적용될 수 없다.
    • display: block; 가로 세로 값을 가질수 있게 됨
    • width: 1px;
    • height: 12px;
    • background-color: black; 가로사이즈가 1px, 높이가 12px인 검은색 구분선들이 생긴 것을 볼수 있는데 화면 위쪽에 붙어 있음
    • postion: absolute; 부모요소(li) 기준으로 배치를 할수 있도록 해준다. 자동으로 인라인요소를 블록요소로 바꿔주기 때문에 display속성을 지워도 된다.
    • top: 0;
    • bottom: 0;
    • margin: auto 0; 위아래 중간, 좌우는 조절해주지 않음(0 생략 가능)
  • header .sub-menu ul.menu li:first-child::before {}
    가상요소의 첫번째 자식선택. 맨 앞의 구분선을 지워주기 위함이다.
    • display: none;

검색: 포커스 효과

CSS

  • header .sub-menu .search {}
    • position: relative; 자식요소 배치를 위해서
  • header .sub-menu .search input {}
    • width: 36px;
    • height: 34px;
    • padding: 4px 10px; 위아래 4, 좌우 10 내부여백
    • border: 1px solid #ccc; 1px #cccccc 실선
    • box-sizing: bprder-box; 가로 36, 34를 유지하면서 내부여백, 실선 추가
    • border-radius: 5px; 모서리를 둥글게
    • outline:none; 아웃라인(파란 네모선)은 조절하기 어려우므로 해제
    • transition: width .4s; 포커스 됐을 때 너비가 자연스럽게 늘고 준다.
  • header .sub-menu .search input:focus {}
    • width: 190px; 포커스 됐을 땐 늘려주기
    • border-color: #669900; 스타벅스 초록색으로 경계선칠해주기
  • header .sub-menu .search .material-icons {}
    • height: 24px; 배치를 해주려면 너비값이 있어야 한다. 매테리얼 아이콘 폰트크기 할당
    • position: absolute; 부모요소(.search) 중심으로 배치를 하겠다
    • top: 0;
    • bottom: 0;
    • right: 5px; .search의 오른쪽 맨 끝에서 5px 떨어진데에 배치
    • margin: auto; .search의 위아래 중간에 배치

JS
돋보기 아이콘을 인풋 안에 놓긴 했지만 돋보기가 아닌 인풋 테두리를 클릭해야 효과가 나타나는 상황!
돋보기를 클릭했을 때도 그 효과가 나타나도록 해주자.

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','');
});
  • js 폴더를 만들고 main.js 파일을 만든다
  • html에 main.js를 연결해주자
    • defer 속성 잊지 않도록!
      defer : html을 컴파일 한 후 js를 읽을 수 있게 한다
    <script defer src="./js/main.js"> </script>
  • const searchEl = document.querySelector('.search'); searchEl .search 요소 선택
  • const searchInputEl = searchEl.querySelector('input'); searchInputEl searchEl의 .input 요소 선택
  • searchEl.addEventListener('focus',function(){}); searchInputEl를 클릭focus하면 어떠한 익명 함수function()을 실행할 것임
    • searchEl.focus(); 그 함수의 내용은 인풋요소 또한 포커스를 하라는 것
  • searchInputEl.addEventListener('focus',function(){}); 이벤트 핸들러
    • searchEl.classList.add('focused'); .search에 focused 클래스추가
    • searchInputEl.setAttribute('placeholder','통합검색'); 인풋 요소에 입력할 힌트. 그런데 한번 포커스 되면 계속 힌트가 남아 있게 된다. 따라서.. 아래의 이벤트 핸들러 작성
  • searchInputEl.addEventListener('blur',function(){}); blur(포커스 해제)되면, 익명의 함수 실행
    • searchEl.classList.remove('focused'); focused 클래스 해제
    • searchInputEl.setAttribute('placeholder','');
      }); 힌트를 비워준다

CSS
인풋이 포커스 되었을 때는 돋보기를 숨겨주기

header .sub-menu .search.focused .material-icons {
  opacity: 0;
}

JS에서 생성된 focused 클래스는 .search와 함께 사용되는 것이므로 바로 붙여서 명시한다 (.search.focused)

  • header .sub-menu .search .material-icons {}
    • transition: .4s;
      돋보기가 사라지고 나타날 때 부드러운 전환 효과 주기

서브메뉴+검색 배치

다른 줄에 배치 되어있던 검색창과 서브메뉴를 양 옆으로 배치되도록 해주기

  • header .sub-menu {}
    • position: absolute; 부모요소 .inner을 기준으로 배치할게
    • top: 10px; 위에서 부터 10 px부터
    • right: 0; 오른쪽 상단으로 배치해줘
    • display: flex; .sub-menu 자식들: ul.menu, .search 가 가로로 나란히 배치된다

ul class="main-menu"


메인메뉴
↳ 드롭다운 메뉴 li class="item":hover COFFEE
↳ class="item__name" 커피
↳ class="item__contents" 원두 비아 오리가미
↳ class="contents__texture" 어울리는 커피, 최상의 커피

BEM 클래스 이름 짓기

html 구조를 확인하지 않아도 구조를 파악할 수 있다
언더바 두번: 상위 요소의 일부분
대쉬 두번: 동위 요소의 다른 버젼. 상태

HTML

<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>
          </ul>
        </div>
        <div class="contents__texture">
           <div class="inner">
              <h4>나와 어울리는 커피 찾기</h4>
              <p>스타벅스가 여러분에게 어울리는 커피를 찾아드립니다.</p>
              <h4>최상의 커피를 즐기는 법</h4>
              <p>여러가지 방법을 통해 다양한 풍미의 커피를 즐겨보세요.</p>
           </div>
         </div>

CSS

header .main-menu {}
header .main-menu .item {}

/* item__name */
header .main-menu .item .item__name{}
header .main-menu .item:hover .item__name {}

/* item__contents */
header .main-menu .item .item__contents {}
header .main-menu .item:hover .item__contents {}
header .main-menu .item .item__contents .contents__menu {}
header .main-menu .item .item__contents .contents__menu > ul {}
header .main-menu .item .item__contents .contents__menu > ul > li {}
header .main-menu .item .item__contents .contents__menu > ul > li h4 {}
header .main-menu .item .item__contents .contents__menu > ul > li ul li {}
header .main-menu .item .item__contents .contents__menu > ul > li ul li:hover {}
header .main-menu .item .item__contents {}

/* item__texture */
.contents__texture {}
header .main-menu .item .item__contents .contents__texture h4 {}
header .main-menu .item .item__contents .contents__texture p {}
  • 메인메뉴 아이템 수직에서 수평으로 바꾸기
    • header .main-menu
      • display: flex;
  • 메뉴 아이템 사이에 적당한 간격 두기
    • header .main-menu .item .item__name
      • padding: 10px 20px 34px 20px; 내부여백 위 우 아래 좌
  • 드롭다운 메뉴영역은 고정적이지만 호버시에만 보이기
    • header .main-menu .item .item__contents
      • width: 100%;
      • position: fixed; top이나 bottom 속성을 사용하지 않아 수직 위치 값이 없다면 요소의 원래위치를 그대로 사용한다. 만약 absolute를 사용한다면 위치상 부모요소를 기준으로 하므로 화면의 뷰포트 좌우 끝까지 늘어날 수 없게 된다.
      • left: 0;
      • display: none; 호버 하지 않으면 화면에 보이지 않게
    • header .main-menu .item:hover .item__contents
      • display:block; 호버하면 그 때 컨텐츠가 블록으로 바뀌며 보이게 된다
  • 화면의 중앙으로 컨텐츠를 보여주기
    • 클래스에 inner를 추가해준다 class=
      "inner"
      - width: 1100px; 영역한정
      - margin: 0 auto; 중간으로 정렬
      - position: relative; 위치상 부모가 될 수 있다
  • 호버시 .item__name 드롭다운 메뉴를 내리고 .item__contents 드롭다운 메뉴를 보여준다

    • header .main-menu
      • position: absolute; 부모요소 기준 배치
      • bottom: 0;
      • right: 0;
      • z-index: 1; 드롭다운 메뉴가 다른 요소들 위에 있어야함
    • header .main-menu .item:hover .item__name
      • 배경색을 바꿔주고 위 양옆의 모서리 둥글게
      • background-color: #2c2a29;
      • color: #669900;
      • border-radius: 6px 6px 0 0 ;
    • header .main-menu .item:hover
    • header .main-menu .item .item__contents .contents__menu > ul > li ul li:hover
      • color: #669900; 서브리스트 아이템 색 바꾸기
  • contents__menu의 여러 서브메뉴 정렬하기

    • header .main-menu .item .item__contents .contents__menu > ul
      • display: flex; 가로로 나열
    • header .main-menu .item .item__contents .contents__menu > ul > li
      • width: 220px; 서브메뉴 가로 크기 정해주기
    • header .main-menu .item .itemcontents .contentsmenu > ul > li ul li
      • cursor: pointer; 커서가 변하면서 클릭할 수 있는 요소임을 알려준다

뱃지

사진 두개로 구성되고 화면 아래로 가면 사라지는 효과

<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 .badges {}

    • position: absolute; header{}에 position: fixed;를 추가해준다
    • 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); 그림자 효과주기. rgb로 검정색을 0.15투명도 만큼 추가해서 그림자 효과를 준다
    • cursor: pointer; 클릭할 수 있는 요소임을 표시

JS
아래로 스크롤 되면 사라지게 하기

    const badgeEl= document.querySelector('header .badges');
window.addEventListener('scroll',_.throttle(function(){  
  // _.throttle(함수, 시간)
  if (window.scrollY > 500) { //스크롤 위치에 따라서
    // 배지 숨기기
    // gsap.to(요소, 지속시간, 옵션)
    gsap.to(badgeEl, .6, {
      opacity: 0, // 시각적으로 없애주기
      display: 'none' // 실제로 없애주기
    });
  } else {
    // 배지 보이기
    gsap.to(badgeEl, .6, {
      opacity: 1,
      display: 'block'
    });
  }
},300));
    
  • throttle(함수,300) 0.3초마다 함수를 실행 해서 과부하 예방
    • lodash cdn 검색
    • lodash라는 라이브러리를 추가해서 이용
  • gsap.to(요소, 지속시간, 옵션)
    • gsap cdn 검색
    • gsap.min.js 라이브러리 추가
  • 안보이게 하고 사라져도 뱃지부분을 클릭할 수 있는것을 해결하기
    • opacity: 0, 시각적으로 자연스럽게 없애주기
    • display: 'none' 시각적으로 사라지면 실제로 없애주기

section class="visual"

사진 배치 + 버튼 추가 + 요소들이 순차적으로 등장하게 하기

  • visual {}
    • margin-top: 120px; 120px는 헤더의 높이값. 헤더 아래에 오도록 한다.
  • visual .inner {}
    • height: 646px; 높이값을 명시하므로써 배경화면이 뜨게 된다

여러가지 버튼 만들기

  • .btn {} 버튼의 공통적인 속성
    • display: block; 버튼 안에 인라인 요소가 있더라도 버튼은 블록요소
    • text-align: center; 버튼 안의 텍스트는 가운데에 온다
    • cursor: pointer; 클릭할 수 있는 요소임을 알려주기
    • box-sizing: border-box; 보더를 포함해서 주어진 높이,너비에 맞추기
    • transition: .4s; 버튼 속성이 바뀌면 자연스럽게 바뀌도록하기
  • .btn--brown, .btn--white 색상이 다른 버튼들
  • .btn:hover .btn--brown:hover, .btn--white:hover 호버가 되면 반전된 상태를 만들어줄수 있게 하기
  • class="btn btn--brown" 이런식으로 적용해 주게 된다

시간차 애니메이션

.visual .fade-in {
  opacity: 0;
}

fade-in이라는 class를 추가해준다

const fadeEls = document.querySelectorAll('.visual .fade-in');
fadeEls.forEach(function(fadeEl, index){
  gsap.to(fadeEl, 1, {
    delay: (index + 1) * .7,
    opacity: 1
  });
});
  • fade-in 클래스를 가진 요소들을 0.7초 씩마다 지연해서 하나씩 보여준다
  • (index + 1) index는 0으로 시작하기 때문에 1을 미리 더해줌
profile
코딩과 사별까지

0개의 댓글