3️⃣ 헤더와 드롭메뉴 - 검색
Input이 blur될 경우 스타일링 하기
box-sizing: border-box;
를 통해 테두리를 기준으로 크기를 정한다.width: 36px;
로 설정해서 blur되었을 때 input의 크기를 최소화한다.transition
의width
값만 변경되었을 경우 0.4초로 default easing function인ease
로 애니메이션 처리를한다.
transition - CSS: Cascading Style Sheets | MDN
The transition CSS property is a shorthand property for transition-property, transition-duration, transition-timing-function, transition-delay, and transition-behavior.
developer.mozilla.org
Input이 focus될 경우 스타일링 하기
header .sub-menu .search {
position: relative;
height: 34px;
}
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;
transition: width 0.4s;
}
header .sub-menu .search input:focus {
width: 190px;
border-color: #669900;
}
header .sub-menu .search .material-symbols-outlined {
height: 24px;
position: absolute;
top: 0;
bottom: 0;
right: 5px;
margin: auto;
}
width: 190px;
로 설정하여 focus될 때 너비가 넓어지도록 한다.- border-color가 변경되도록 한다.
자바스크립트로 Search Icon 클릭 시 이벤트 적용하기
input 영역을 focus하면 애니메이션이 적용되지만 Search Icon을 클릭하면 동작되지 않는 것을 확인할 수 있다.
이를 위해 자바스크립트를 통해 Search Icon을 클릭하면 Input에 focus되도록 구현해야한다.
추가로 focus될 경우 Search Icon은 보이지 않아야 되기 때문에 focus되거나 blur될때 투명도를 주는 .focus
클래스를 추가하고 삭제되도록 구현해야한다.
<script src="./js/main.js" defer></script>
- 외부 자바스크립트를
defer
속성을 통해 html구조가 모두 해석된 이후 js를 불러오도록 한다. - 기본적으로
script
태그를 만나면 DOM 생성을 멈추고script
를 실행하기 때문에 가져오는 시간이 오래 걸릴 수 있다.
때문에 DOM 생성과 동시에 script를 병렬적으로 내려받을 수 있도록defer
혹은async
속성을 사용해야한다.
✅ script의 async, defer 속성의 차이
1. async
- HTML을 parsing하는 동시에 js를 fetching하는 병렬적 구조이다.
하지만 다수의 js파일을 다운받고 다운이 완료된 js를 무작위로 실행하므로 순서에 의존적인 페이지라면 유의해야한다.
2. defer
- parsing중에 js파일을 모두 다운로드 받아 놓고 parsing이 끝나는 순서대로 js를 실행하므로 원하는 순서대로 스크립트를 실행할 수 있다.
const searchEl = document.querySelector(".search");
const searchInputEl = searchEl.querySelector("input");
searchEl.addEventListener("click", () => {
searchInputEl.focus();
});
.search
요소 내부에input
태그를serchInputEl
로 할당하고 search 요소를 클릭하면 input이 focus되도록 한다.
searchInputEl.addEventListener("focus", () => {
searchEl.classList.add("focused");
searchInputEl.setAttribute("placeholder", "통합검색");
});
input
요소가 focus되면 검색 아이콘을 삭제하는 스타일링이 정의된.focused
클래스가 추가되도록한다.
추가로placeholder
를 "통합검색" 으로 설정한다.
searchInputEl.addEventListener("blur", () => {
searchEl.classList.remove("focused");
searchInputEl.setAttribute("placeholder", "");
});
- search클래스 요소 내부에있는
input
요소가 blur되면.focused
클래스가 삭제하도록한다.
추가로placeholder
는 빈값으로 설정한다.
즉, 자바스크립트는 DOM요소를 선택하고 특정 이벤트에 원하는 스타일링에 해당하는 클래스를 추가하거나 삭제하면서 요소를 동적으로 처리할 수 있도록 해준다.
결과
4️⃣ 헤더와 드롭메뉴 - 메인 메뉴
특정 부분만 border-rardius 설정하기
header .main-menu .item:hover .item__name {
background-color: #2c2a29;
color: #669900;
border-radius: 6px 6px 0 0;
}
- 좌상단을 시작으로 우측 순으로
border-radius
를 설정할 수 있다. - 좌상단 우상단만
border-radius
를 각각 6px씩 설정한다.
레이어 최상단으로 끌어올리기
header .main-menu {
display: flex;
position: absolute;
bottom: 0;
right: 0;
z-index: 1;
}
- 메인 메뉴를
header
에 우측하단에 배치하고z-index: 1
로 설정하여 레이어를 끌어올려 다른 요소들을 보다 최상단에 위치할 수 있도록 설정한다.
inner 클래스 분리하기
/* COMMON */
.inner {
width: 1100px;
margin: 0 auto;
position: relative;
}
/* HEADER */
header > .inner {
height: 120px;
}
.inner
클래스는 여러 요소에서 사용되므로 공통 스타일로 정의하여 분리한다.- 각 요소들의
height
값은 다른 요소에 따라 다르게 설정되고 자식 요소로 사용하기 때문에>
를 통해.inner
를 선택자로 가지게 한다.
CSS 이미지 불러오기
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;
}
- texture 요소에 패턴을 부여하기 위해 images 폴더에 있는 main_menu_patter.jpg를
background-image
속성의url
로 가져와 이미지를 적용할 수 있다.
결과
✍️ BEM 방법론(Block Element Modifier)
- HTML 클래스 속성의 작명법이다.
요소__일부분
: Underscore(_) 기호로 요소의 일부분을 표시할 수 있다.요소—-상태
: Dash(-) 기호로 요소의 상태를 표시할 수 있다.
예시
위는 요소 일부분에 대한 예시이다.
클래스 명을 .name
처럼 단순하게 작명할 경우 중복될 가능성이 있다.
이를 Underscore를 사용하여 요소의 일부분을 나타낼 수 있다면, 해당 name이 container와 item요소 중 어떤 요소의 일부분인지를 클래스만 보고 빠르게 파악할 수 있게 된다.
위는 요소 상태에 관한 예시이다.
위와 같이 버튼의 세가지 상태가 버튼에 종속되어져 있다는 것을 사용자가 파악하기 어렵다.
이처럼, primary
success
error
가 버튼에 종속되어져 있다는 것을 dash를 사용해서 나타낼 수 있다.
위와 같이, BEM방법론을 사용하게 되면 HTML의 구조를 확인하지 않고 클래스만 봐도 어떤 구조로 이루어져 있는지를 빠르게 파악할 수 있게 된다.
5️⃣ 헤더와 드롭메뉴 - 전역 배지(GSAP)
배지 스타일링 및 위치 설정하기
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, 0, 0.15);
cursor: pointer;
}
border-radius
를 통해 배지들의 모서리를 둥글게 설정한다.border-radius
를 설정해도 안에 있는 이미지들은 외부 영역을 침범하기 때문에overflow: hidden
으로 침범을 막아준다.box-shadow
를 통해 x축과 y축으로 4px로 위치시키고 blur를 10px로 부여한다. 색은 rgba로 검정색으로 설정하고 투명도는 0.15로 설정하였다.- badge를 header를 기준으로 위치시킬 것이기 때문에 header의
position
을relative
로 설정하고 badges의position
을absolute
로 설정한다.
브라우저 상단에 고정시키기
header {
position: fixed;
top: 0;
background-color: #f6f5f0;
border-bottom: 1px solid #c8c8c8;
}
페이지 스크롤시 header를 브라우저 상단에 고정시키려면 position: fixed
로 설정한다.
하지만 fixed로 설정하면 다음과 같이 width값이 최소한으로 잡혀진다.
그 이유는, position을 fixed나 absolute로 설정하게 되면 자동으로 width: auto
로 설정되기 때문에, 가로 넓이를 최소한으로 잡으려고 한다.
이러한 문제를 해결하려면 width: 100%
로 하여 부모 요소(body
)의 width값으로 설정해야한다.
header {
position: fixed;
top: 0;
**width: 100%;**
background-color: #f6f5f0;
border-bottom: 1px solid #c8c8c8;
}
부모의 너비 만큼 header의 너비가 잡힌 것을 확인할 수 있다.
스크롤 시 배지 숨기기
스크롤값이 특정값을 넘어가게 될 경우 배지가 숨겨지도록 javasript를 통해 구현해야할 필요가 있다.
lodash.js
window
에 scroll 이벤트를 주고 로직을 작성하면, 스크롤 할때 마다 함수가 연속적으로 호출된다.
그러나, 위처럼 구현하게 되면 사이트에 들어가는 컨텐츠가 많아 질수록 버벅이는 현상으로 이어질 수 있다.
이러한 방식을 해결해줄 수 있는 외부 라이브러리가 loadash.js이다.
lodash.js - Libraries - cdnjs - The #1 free and open source CDN built to make life easier for developers
A utility library delivering consistency, customization, performance, & extras. - Simple. Fast. Reliable. Content delivery at its finest. cdnjs is a free and open-source CDN service trusted by over 12.5% of all websites, serving over 200 billion requests e
cdnjs.com
위 링크를 통해 lodash.js 라이브러리 사이트의 CDN 페이지로 이동한다.
가장 많이 사용하는 첫번째 CDN을 복사해서 head
태그 내부에 추가하고 다음과 같이 작성한다.
const badgeEl = document.querySelector("header .badges");
window.addEventListener(
"scroll",
_.throttle(() => {
if (window.scrollY > 500) {
badgeEl.style.display = "none";
} else {
badgeEl.style.display = "block";
}
}, 300)
);
window
객체에 접근하여addEventListener()
를 통해 scroll 이벤트를 부여한다.- lodash 라이브러리에서 제공하는
_.throttle()
의 첫번째 인자로 함수를 전달한다. - 두번째 인자로는 해당 함수가 몇초에 한번 함수를 호출할 것인지를 ms단위로 입력한다.
- 위 코드는 0.3초 단위로 부하를 주어서 함수가 연속적으로 호출되는 것을 방지하도록 설정한다.
window
객체의scrollY
를 통해 브라우저 상단을 기점으로 스크롤한 위치가 몇 px인지 확인할 수 있다. 이를 통해 500px를 넘으면 배지를 숨기게하고 그렇지 않을 경우 보이게 끔 작성한다.
GSAP
배지를 숨기고 보여지는 애니메이션 과정에서 이질감이 있다.
자연스러운 애니메이션 효과를 주기위해 GSAP 라이브러리를 사용할 수 있다.
gsap - Libraries - cdnjs - The #1 free and open source CDN built to make life easier for developers
GSAP is a JavaScript library for building high-performance animations that work in **every** major browser. Animate CSS, SVG, canvas, React, Vue, WebGL, colors, strings, motion paths, generic objects...anything JavaScript can touch! No other library delive
cdnjs.com
위 링크를 통해 GSAP 라이브러리 사이트의 CDN 페이지로 이동한다.
가장 많이 사용하는 첫번째 CDN을 복사해서 head
태그 내부에 추가하고 다음과 같이 작성한다.
window.addEventListener(
"scroll",
_.throttle(() => {
if (window.scrollY > 500) {
gsap.to(badgeEl, 0.6, {
opacity: 0,
});
} else {
gsap.to(badgeEl, 0.6, {
opacity: 1,
});
}
}, 300)
);
- gsap 객체의
to()
메소드를 통해 요소와, 지속시간, 옵션을 인자로 넘긴다. - 옵션에
opacity
속성을 넣어 숨길경우 0으로 보일 경우 1로 설정한다.
하지만 opacity
값으로만 애니메이션을 처리하면, 요소는 그대로 남고 보이지 않는 형태가 되기 때문에 사용자가 해당 영역을 클릭하면 배지를 클릭하게되는 문제가 발생한다.
때문에 opacity
뿐만 아니라 display
를 none
과 block
으로 옵션을 주어 요소를 완전히 제거할 수 있도록 설정해야한다.
window.addEventListener(
"scroll",
_.throttle(() => {
if (window.scrollY > 500) {
gsap.to(badgeEl, 0.6, {
opacity: 0,
display: "none",
});
} else {
gsap.to(badgeEl, 0.6, {
opacity: 1,
display: "block",
});
}
}, 300)
);
결과
✍️ 소감
이번 주차는 loadash와 gsap 같은 오픈소스를 처음 접해보았는데, 처음에는 매우 생소하게 느껴졌다.
lodash를 사용하여 스크롤할 때 특정 주기를 설정하여 함수가 연속적으로 트리거되지 않도록 하는 방법을 배웠다.
뿐만 아니라 lodash에서 제공하는 객체와 배열 등의 데이터 구조는 일부 메서드에서 기존의 ES6보다 뛰어난 성능과 함수의 확장성을 제공한다는 것을 알게 되었다.
또한, gsap에서 제공하는 gsap.to()
, gsap.from()
, gsap.fromTo()
를 사용하여 애니메이션을 보다 간단하게 설정할 수 있다는 점도 배울 수 있었다.
'🍪 카카오 테크 캠퍼스 2기' 카테고리의 다른 글
[카카오 테크 캠퍼스 2기] 1단계 4주차 WIL - JavaScript 핵심 (0) | 2024.05.06 |
---|---|
[카카오 테크 캠퍼스 2기] 1단계 4주차 WIL - 스타벅스 예제 클론하기(4) (0) | 2024.05.03 |
[카카오 테크 캠퍼스 2기] 1단계 3주차 WIL - 스타벅스 예제 클론하기(3) (0) | 2024.05.03 |
[카카오 테크 캠퍼스 2기] 1단계 1주차 WIL - 스타벅스 예제 클론하기(1) (0) | 2024.04.15 |
[카카오 테크 캠퍼스 2기] 프론트엔드 최종 합격 후기 (2) | 2024.04.07 |