[TIL #3] 클론코딩 - 메뉴(서브, 메인)

Yejin Yang·2022년 4월 10일
0

[TIL]

목록 보기
3/67
post-thumbnail

스타벅스 랜딩 페이지 예제

출처: starbucks-vanilla-app

서브 메뉴 구현

4개의 선택 메뉴와 검색 영역

HTML

<body>
  <body>
    <header>
      <div class="inner">
        <a href="/" class="logo">
          <img src="./images/starbucks_logo.png" alt="STARBUCKS">
        </a>
      </div>
      <div class="sub-menu">
        <ul class="menu">
          <li>
           <a href="#">sign In</a>
          </li>
          <li>
           <a href="#">My Starbucks</a>
          </li>
          <li>
           <a href="#">Customer Service & Ideas</a>
          </li>
          <li>
           <a href="#">Find a Store</a>
          </li>
        </ul>
        <div class="search">
          <input type="text">
          <div class="material-icons">search</div>
        </div>
      </div>

새로 배운 부분

  1. a태그 href 부분에 걸어야할 주소가 완성되지 않았는데 값을 비워두기 좀 그렇다면 # 해시를 넣던가, javascript:void(0) 를 입력한다.
    슬래시 입력은 앞에 도메인이 생략된 것. 결국 우리프로젝트의 메인 페이지로 이동하겠다는 뜻. 현재의 index.html파일로 가겠다는 의미

javascript:void(0)
자바스크립트를 통해 기능을 동작 시킬건데, 아직 그 동작이 비어있다는 뜻. 즉 링크가 아직 준비되지 않았을 때 임시적으로 관리할 수 있는 방법임

강의는 javascript:void(0) 를 추천, 이건 정말 아무런 동작도 일어나지 않는 것에 반해 #기호는 약간 변화가 있을 수 있음

  1. ul태그와 li태그는 세트이고 하나씩 쓸 수 없다.

  2. Google Material icons은 link태그로 연결한 뒤, 사용시 구글에서 아이콘 이름만 가져와도 된다.(꼭 span태그 아니여도 됨)


CSS

/* COMMON */
body {
  color: #333;
  font-size: 16px;
  font-weight: 400;
  line-height: 1.4;
  font-family: 'Nanum Gothic', sans-serif;
}
img {
  display: block;
}
a {
  text-decoration: none;
}

/* HEADER  */
header {
  background-color: #f6f5f0;
  border-bottom: 1px solid #c8c8c8;
}
header .inner {
  width: 1000px;
  height: 120px;
  margin: 0 auto;
  position: relative;
}
header .logo {
  height: 75px;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  margin: auto;
}
header .sub-menu {
  position: absolute;
  top: 10px;
  right: 0;
  display: flex;
}
header .sub-menu ul.menu {
  font-family: Arial, Helvetica, sans-serif;
  display: flex;
}
header .sub-menu ul.menu li {
  position: relative;
}
header .sub-menu ul.menu li::before {
  content: "";
  width: 1px;
  height: 12px;
  background-color: #e5e5e5;
  position: absolute;
  top: 0;
  bottom: 0;
  margin: auto;
}
header .sub-menu ul.menu li:first-child:before {
  display: none;
}
header .sub-menu ul.menu li a {
  font-size: 12px;
  padding: 11px 16px;
  display: block;
  color: #656565;
}
header .sub-menu ul.menu li a:hover {
  color: #000;
}

/* 검색창 */
header .sub-menu .search {
  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: #fff;
  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;
}

/* focus상태가 아닐 때 돋보기 아이콘 지우기 */
header .sub-menu .search.focused .material-icons { 
  opacity: 0;
}

새로 배운 부분

  1. CSS에서 우리 프로젝트 전체에 공통적으로 영향을 미치고 있는 내용들은 COMMON(공통)에 입력한다.

  2. 대부분 브라우저는 따로 명시하지않아도 font-size: 16px 부터 시작한다. font-weight: 400, 통상적으로 행간 1.4 으로 함(글꼴에 따라 최적의 줄높이가 다르다.)

  3. 메뉴 이름(a tag)에 padding 값을 넣어 사용자가 서브메뉴 선택하는 영역을 키워준다. 영역이 너무 작으면 사용자가 잘못 선택할 위험이 있기 때문이다.

  4. a 태그는 인라인요소이므로 display: block; 으로 블록요소로 바꿔준다.


JS로 아이콘에 포커스 추가하기

const searchEl = document.querySelector('.search');
const searchInputEl = document.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', '');
});
  1. HTML에서 JS 연결할 때 'defer' 속성 추가하면 HTML구조가 모두 해석이되고 난 후 main.js가 동작하도록 설정할 수 있다.
    <script defer src="./js/main.js"></script>

  2. querySelector 를 통해 document(html)상에서 특정 클래스를 찾을 수 있다.

  3. 자바스크립트 이벤트, 핸들러를 통해 HTML상에서 class를 추가할 수도(add), 삭제(remove)할 수도 있다.

  4. focus(); 자바스크립트를 통해서 포커스가 가능한 대표적인 input 요소에다가 강제로 포커스를 적용해주는 명령



메인 메뉴, 드롭다운 구현

목표

  • 메인 메뉴 만들기
  • 드롭다운 화면 구현(2줄의 드롭다운, 내용 가운데 정렬)

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>
          </div>
        </li>


위 코드는 이미지의 빨간 박스 부분을 위한 HTML 구조이다. 다른 메뉴 & 하위메뉴들이 많으니 생략한다.

CSS

header .main-menu {
  position: absolute;
  display: flex;
  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, Helvetica, 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
}
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 {
  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; 
}
  • 중간에 > ul 이런식으로 자식선택자를 명시한 부분이 있는데, 이렇게 같은 태그가 사용되는 부분에서 자식선택자를 명시하지 않으면 .contents__menu 내부에 있는 모든 ul태그가 영향받게 된다. 바로 자식만 지정해주기위해 자식선택자 사용한다.



BEM (Block Element Modifier)

HTML 클래스 속성의 작명법

요소__일부분
: 메인메뉴 구현 시 class 이름에서 contents__menu 같이 언더바 두개 붙인 이유는 요소의 일부분이라는 것을 나타냄.
CSS 선택자를 만들어낼 때, HTML 구조를 확인하지 않아도 어느부분의 일부분이라는 것을 쉽게 알 수있는 장점이 있음.


요소--상태

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

위 코드는 버튼의 에러 상태를 나타내는데, btn error가 두 단어로 이루어져있으니까 종속되지 않고 별개의 단어처럼 느껴진다.

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

하지만 이렇게 단어 사이에 하이픈 두개 기호를 이용하면 정확하게 상태를 매칭할 수 있다.
클래스 이름만 보고도 클래스가 어떠한 역할인지 유추가 가능하다.



회고

클론코딩 예제 초반 부분인데 여러모로 헷갈리는 부분이 많았다. 강의를 보며 따라하는 것은 어렵지 않으나 혼자 하게 되면 너무나도 부족하다. 그리고 돋보기 아이콘을 누르면 검색창이 활성화 되고, 반대로 누르지 않으면 돋보기 아이콘만 나오는 과정을 자바스크립트로 구현했는데 신기하고 재밌다.
확실히 메인 메뉴는 하위 메뉴들이 많아지니까 코드가 길어지는게 어지럽다.(마치 구불구불 뱀..🐍)
html에서는 시작태그와 종료태그를 잘 확인해야하고, css에서는 태그가 많아지니까 선택자 입력에 유의해야한다!(a태그로 페이지 이동하면 얼마나 길어질지..) 그래도 메뉴들이 만들어지는게 눈에 보여지니까 재밌다. BEM 작명법도 처음 알았는데 유용하게 사용할 것 같다.

profile
Frontend developer

0개의 댓글