๐ LG U+ ํํ์ด์ง ํด๋ก ์ฝ๋ฉ
ํจ์คํธ์บ ํผ์คX์ผ๋์ ์ฒซ ๋ฒ์งธ ํ๋ก์ ํธ
2023-07-24~2023-07-28
๋ ํผ๋ฐ์ค ์ฌ์ดํธ & ๋ฐ๋ชจ ์ฌ์ดํธ
๋ ํผ๋ฐ์ค : https://www.lguplus.com/
๋ฐ๋ชจ : https://glowing-chebakia-807feb.netlify.app/
ํ๋ก์ ํธ ์ค๋ช ๋ฐ ์ ์ ์ด์
์ฒซ ํด๋ก ์ฝ๋ฉ ํ๋ก์ ํธ์ธ ๋งํผ ๋ด๊ฐ ๋ฐฐ์ ๋ ๊ฑธ ์จ๋จน์ด ๋ณด๊ณ ์ถ์๋ค
๊ทธ๋์ ๋ด ์์ค(?)์์ ๊ตฌ์กฐ์ ์ผ๋ก๋ ๊ธฐ๋ฅ์ ์ผ๋ก ๊ตฌํํ ์ ์๋ ์น ์ฌ์ดํธ๋ฅผ ์ ์ ํ๋ค
๊ตฌํ ๋ด์ฉ
1. fixed๋ ํค๋๋ฉ๋ด
position: fixed; ์์ฑ์ ์ด์ฉํด ์คํฌ๋กค ์์๋ ํค๋ ์ ์ง
2. ์ฌ๋ผ์ด๋์ ์ ๋๋ฉ์ด์ ์ ํํจ๊ณผ
swiper ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ scrollMagic ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํตํด ์ฌ๋ผ์ด๋์ ์ ๋๋ฉ์ด์ ๊ธฐ๋ฅ ์ถ๊ฐ
3. ๋๋กญ๋ค์ด ๋ฉ๋ด
CSS์ display ์์ฑ์ JS์์ ์ ์ดํ๋๋ก ํจ
์๋ฌ๋ฐ์ ๋ฐ ๋ฌธ์ ํด๊ฒฐ
1. header์ posititon: sticky; ๊ฐ ์ ์ฉ๋์ง ์์
์คํฌ๋กค์ ๋ฐ๋ผ์ค๋ header๋ฅผ ๊ธฐ๋ํ๋๋ฐ, position: sticky; ๊ฐ ์ ์ฉ๋์ง ์๊ณ ์๋ค.
sticky ์์ฑ์ ๊ฐ๋ ์์๋, ์์ ์ ๋ฐ๋ก ์์ ๋ถ๋ชจ์์ ์์์๋ง ์ ์ฉ๋๋ค.
// ๊ธฐ์กด์ฝ๋
.header {
position: sticky;
top: 0;
left: 0;
z-index: 99;
width: 100%;
background: #000;
}
์ฝ๋๋ฆฌ๋ทฐ ๋ฐ ๋ฆฌํฉํ ๋ง
๋ฉํ ๋์ ์ฝ๋๋ฆฌ๋ทฐ๋ฅผ ์ฐธ๊ณ ํด์ ๊ฐ์ ํ ์ฌํญ๊ณผ ํด๊ฒฐ๋ ๋ถ๋ถ์ ์ถ๊ฐํ๊ฒ ๋ค ๐
1. ๋ฐ์ํ
๋ด ๋๋ฐ์ด์ค ๊ธฐ์ค์ ๋ง์ถฐ์ px ๊ฐ์ ์ฌ์ฉํ๋ค ๋ณด๋ ๋ค๋ฅธ ๋๋ฐ์ด์ค์์ ์งค๋ ค ๋ณด์ผ ๊ฑธ ์์ํ์ง ๋ชปํ๋ค.
๋ฏธ๋์ด ์ฟผ๋ฆฌ๋ฅผ ์ด์ฉํ๋ ๋ฐฉ๋ฒ์ด๋ px๋์ vw์ ๊ฐ์ ์ ๋์ ์ธ ๋จ์๋ฅผ ์ฐ๋๋ก.
2. ์๋งจํฑ ํ๊ทธ ํ์ฉ
<hedaer> ํ๊ทธ์ ์์์ <heading>์ ์ฐ๋ ๊ฒ์ด ๋ง๋ค.
3. .toggle ํ์ฉ
// ๊ธฐ์กด์ฝ๋
let onToggle = false
chatbotEl.addEventListener('click', () => {
onToggle = !onToggle
if (onToggle) {
subMenu.classList.add('show')
chatbotEl.classList.add('show')
} else {
subMenu.classList.remove('show')
chatbotEl.classList.remove('show')
}
})
classList.toggle()
์ ์ฌ์ฉํ๋ฉด ๋ช
์์ ์ผ๋ก ์ฝ๋๋ฅผ ์ค์ผ ์ ์๋ค.
toggle()์ className์ด ์กด์ฌํ๋์ง ํ์ธํ๊ณ ์กด์ฌํ๋ค๋ฉด className์ ์ญ์ ํ๋ค. ์กด์ฌํ์ง ์์ผ๋ฉด ์ถ๊ฐํ๋ค.
// ์์ ์ฝ๋
chatbotEl.addEventListener('click', () => {
subMenu.classList.toggle('show')
chatbotEl.classList.toggle('show')
})
๊ตณ์ด ๋ณ์๋ก ํ์ฌ์ํ ์ ๋ฌด๋ฅผ ์ฒดํฌํ์ง ์์๋ toggle๋ก ๊ฐ๋จํ๊ฒ ํด๋์ค๋ฅผ ์ถ๊ฐํ๊ณ ์ ๊ฑฐํ ์ ์๋ค.
4. ์ฃผ์์ฌ์ฉ๋ณด๋จ ๋ค์ด๋ฐ์ ์ํ์
// ๊ธฐ์กด ์ฝ๋
const swiper = new Swiper('.visual .swiper-container', {
autoplay: {
delay: 5000, // 5์ด๋ง๋ค ์ฌ๋ผ์ด๋ ๋ฐ๋
const SECONDS_TO_MS = 1000 ์ ๊ฐ์ด ์์๋ฅผ ๋จผ์ ์ ์ธํ๊ณ ,
delay: 5 * SECONDS_TO_MS ์ฒ๋ผ ์ฌ์ฉํ๋ฉด ์ฃผ์์์ด๋ ์ฝ๋๋ฅผ ์ฝ๊ฒ ํ์
ํ ์ ์๋ค.
5. ์๋๊ฒฝ๋ก ๋ณด๋จ ์ ๋๊ฒฝ๋ก๋ฅผ ์ฌ์ฉํ์
"./css/common.css" ๐ "/css/common.css"
์ด๋ค subpath์์๋ ๋ฌธ์ ์๋๋ก ์ ๋๊ฒฝ๋ก ์ฌ์ฉ์ ์ต๊ดํํ๋ ๊ฒ์ด ์ข๋ค
6. script ํ๊ทธ๋ ๊ฐ๋ฅํ </body> ์์ ์์น์ํค๋ ๊ฒ์ด ์ข๋ค
defer ๋ฅผ ์ฌ์ฉํ๋ฉด ์คํฌ๋ฆฝํธ๊ฐ ํ์ด์ง์ ๋ค๋ฅธ ๋ด์ฉ์ ํ์ฑํ๋ ๋์ ์คํ๋์ง ์๊ณ , ํ์ฑ์ด ์๋ฃ๋ ํ์ ์คํ๋๋ค.
๋ํ </body> ํ๊ทธ ์์ ์์น์ํค๋ฉด, ์คํฌ๋ฆฝํธ๊ฐ ํ์ด์ง์ ๋๋จธ์ง ๋ด์ฉ์ ๋ฐฉํดํ์ง ์๊ณ ๋ก๋ฉ๋ ์ ์๋ค.
7. id๋ class์์ dash(-)๋ฅผ ๊ตฌ๋ถ์๋ก ์ฌ์ฉํ๋ ๊ฒ์ด ์ข๋ค
camelCase๋ snake_case๋ฅผ ์ฌ์ฉํ์ง ์๊ณ dash(-)๋ฅผ ๊ตฌ๋ถ์๋ก ์ฌ์ฉํ๋ ๊ฒ ์ผ๋ฐ์ ์ด๋ค.
8. input checkbox๋ cheked๋ฅผ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ์ค์ ํ ์ ์๋ค
๊ธฐ๋ณธ๊ฐ์ผ๋ก checked๋๊ฒ ํ๋ ค๋ฉด, checked ์์ฑ์ ์ฌ์ฉํ๋ฉด ๋๋ค.
https://developer.mozilla.org/ko/docs/Web/HTML/Element/input/checkbox
<input type="checkbox"> - HTML: Hypertext Markup Language | MDN
๊ณต๋ฌธ์์์ ๋ณผ ๋ฒํ checkbox ์ ํ์ <input> ์์๋ ๊ธฐ๋ณธ์ ์ผ๋ก ํ์ฑํ๋ ์์ ์ฒดํฌ๋๋ ๋ฐ์ค๋ก ๋ ๋๋ง ๋ฉ๋๋ค. ๋ฐ์ค์ ์ ํํ ์ธํ์ ๋ธ๋ผ์ฐ์ ๊ฐ ์คํ ์ค์ธ ์ด์์ฒด์ ์ ์์คํ ๊ตฌ์ฑ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง
developer.mozilla.org
9. Block ๊ตฌ์กฐ์ ๋ํ ๊ณ ๋ฏผ
// ๊ธฐ์กด์ฝ๋
<div class="header-wrap__container">
<div class="inner">
<div class="header-navi">
<nav class="header-navi-menu">
<ul class="header-nav-lst">
<li class="item">
<a href="javascript:void(0)" class="item__name">๋ชจ๋ฐ์ผ ๊ธฐ๊ธฐ</a>
<div class="item__wrap">
๐ค ๋ฉํ ๋: ์กฐ๊ธ ๋ block์ ๊ตฌ์กฐ์ ๋ํด ๊ณ ๋ฏผํด๋ณด์๋ ๊ฒ๋ ์ข์ ๋ณด์ ๋๋ค!
์ฌ๊ธฐ์ 'block์ ๊ตฌ์กฐ'๋ ๋ง์ ์๋ฏธ๋ฅผ ์ ํํ๋ ๋ชจ๋ฅด๊ฒ ์ง๋ง
๊ธฐ์กด์ฝ๋์ ๊ตฌ์กฐ๋ ๋ค์ด๋ฐ์ด ๋ถํ์ํ๊ณ ๋ถ๋ช ํํ ์ ์ด ์์ด์ ๊ทธ ์ ์ ์์ ํ๋ ค๊ณ ํ๋ค.
- ์๋ฏธ ์๋ ํด๋์ค ์ด๋ฆ ์ฌ์ฉ
- ์๋งจํฑํ HTML ์ฌ์ฉ
//์์ ์ฝ๋
<header class="header">
<div class="header__container">
<nav class="header__nav">
<!-- Main Menu -->
<ul class="main-menu">
<li class="main-menu__item">
<div class="main-menu__sub">
</div>
</li>
</ul>
<!-- Sub Menu -->
<ul class="sub-menu">
</ul>
</nav>
</div>
</header>
- ์๋ฏธ ์๋ ํด๋์ค ์ด๋ฆ ์ฌ์ฉ
.header-wrap__container, .header-navi ๋์ ๊ณ์ธต์ ์ผ๋ก ๊ตฌ๋ถํ ์ ์๊ฒ bem ๊ท์น์ ์ฌ์ฉํ๋ค. - ์๋งจํฑํ HTML ์ฌ์ฉ
header์ nav ํ๊ทธ๋ฅผ ์ฌ์ฉํด์ ์ข ๋ ์๋งจํฑํ๊ฒ ๊ตฌ์ฑํ๋ค.
์ข ๋ ๋ช ํํ๊ณ ๊ฐ๊ฒฐํ๊ฒ ์ค์ผ ์ ์์ ๊ฒ ๊ฐ์๋ฐ.. ๊ณ ๋ฏผ์ ๋ ํด๋ด์ผ๊ฒ ๋ค ๐ค
10. heading level์ ๊ตฌ์กฐ์ ์ผ๋ก ๋๋์
// ๊ธฐ์กด์ฝ๋
<div class="item__wrap">
<ul class="inner">
<li>
<h4 class="title"><a href="javascript:void(0)">5Gํด๋ํฐ</a></h4>
๊ธฐ์กด ์ฝ๋๋ ํ ์คํธ์ ์ฌ์ด์ฆ์ ๋ง๊ฒ h4 ์์ค์ ์ฌ์ฉํ๋ค
// ์์ ์ฝ๋
<h2 class="main-menu__sub-title">
h4 ๋์ h2๋ก ๋ ๋ฒจ ์์ค์ ๋ฌ๋ฆฌ ํ๋ค.
11. target="_blank" ์ฌ์ฉ ์์ Tabnabbing ๊ณต๊ฒฉ ๋ฐฉ์ง๋ฅผ ํด์ผํ๋ค
Tab nabbing ๊ณต๊ฒฉ์ด๋?
์ ์ฐฝ์ด๋ ์ ํญ์ ๋์ฐ๋ฉด์ ๋์์ ๋งํฌ๊ฐ ํฌํจ๋์ด์๋ ๋ถ๋ชจ์ฐฝ์ ๋ฌธ์๋ฅผ ํผ์ฑ์ฌ์ดํธ๋ก ๋ฐ๊ฟ์น๊ธฐํ๋ ์๋ฒ
rel="noopener noreferrer"
์์ฑ์ ๋ณด์ ๋ฐ ๊ฐ์ธ ์ ๋ณด ๋ณดํธ๋ฅผ ๊ฐํํ๋ ์ค์ํ ์กฐ์น๋ค.
12. '์ค๋ ํ๋ฃจ ๊ทธ๋ง๋ณด๊ธฐ' ๊ธฐ๋ฅ ๊ตฌํ
๊ธฐ์กด์ ๋ฐฐ๋์์๋ฅผ ๋ซ๋ ์ฝ๋์ ์ฟ ํค๋ฅผ ์ฌ์ฉํด์ '์ค๋ ํ๋ฃจ ๊ทธ๋ง๋ณด๊ธฐ' ๊ธฐ๋ฅ์ ๊ตฌํํ๋ค.
// ๋ฐฐ๋ ๋ซ๊ธฐ ํด๋ฆญ ์ด๋ฒคํธ
function closeBn() {
const bnEl = document.querySelector('.header-banner')
const clsBtn = document.getElementById('closeBtn')
const onTodayCls = document.getElementById('text-chkbox')
if (!bnEl || !clsBtn || !onTodayCls) {
return // ์์๊ฐ ์กด์ฌํ์ง ์์ผ๋ฉด ํจ์ ์ข
๋ฃ
}
const cookieName = 'bannerClosedForToday'
// ์ฟ ํค ์์ฑ ๋ฐ ์ ํจ๊ธฐ๊ฐ ์ง์
function handleBannerClose() {
bnEl.remove()
const expirationDays = 1 // ์ฟ ํค ์ ํจ ๊ธฐ๊ฐ์ ํ๋ฃจ๋ก ์ค์
const expires = new Date()
expires.setDate(expires.getDate() + expirationDays)
document.cookie = `${cookieName}=true; expires=${expires.toUTCString()}; path=/`
}
clsBtn.addEventListener('click', handleBannerClose)
onTodayCls.addEventListener('click', handleBannerClose)
- ๋ฐฐ๋์ .closebtn๊ณผ .text-chkbox๋ฅผ ํด๋ฆญํ๋ฉด ํธ๋ค๋ฌ ํจ์๊ฐ ํธ์ถ
- ์ฟ ํค์ ์ฃผ์ด์ง ๋ ์ง์ '์ผ(date)' ๊ธฐ์ค์ผ๋ก ์ ํจ๊ธฐ๊ฐ ์ค์
.setDate(dayValue)Date ๊ฐ์ฒด์ ์ผ(day)์ ์ค์ ํ๋ ์ญํ ..getDateDate ๊ฐ์ฒด์์ ์ผ(day) ๊ฐ์ ๋ฐํ..toUTCString()๋ ์ง๋ฅผ ๋ฌธ์์ด๋ก ๋ณํํ์ฌ UTC ์๊ฐ๋๋ก ํด์
// ์ฟ ํค ๋ถ๋ฌ์ค๊ธฐ
// ์ฟ ํค ๋ถ๋ฌ์ค๊ธฐ
function getCookie(name) {
const cookies = document.cookie.split('; ')
for (const cookie of cookies) {
const [cookieName, cookieValue] = cookie.split('=')
if (cookieName === name) {
return cookieValue
}
}
return null
}
- ์ฟ ํค์ ์ ์ฅ๋์ด ์๋ ๋ฐ์ดํฐ ๋ถ๋ฌ์ค๊ธฐ
const cookies = document.cookie.split('; ')์ฟ ๊ธฐ ๋ฐ์ดํฐ๋ค์ '; ' ๊ตฌ๋ถ์๋ก ๊ตฌ๋ถํ์ฌ ๋ฐฐ์ด๋ก ์ ์ฅ- if (cookieName === name) {} ์กฐ๊ฑด๋ฌธ์ ํตํด ๋ถ๋ฌ์จ ์ฟ ํค๋ฐ์ดํฐ ์ด๋ฆ์ด cookieName๊ณผ ์ผ์น ์ value๊ฐ ๋ฐํ, ์ด๋ฆ์ด ์ผ์นํ์ง ์์ผ๋ฉด null ๋ฐํ
// ์ฟ ํค ์ํํ์ธ (ํจ์ ํธ์ถ๋ถ)
if (getCookie(cookieName) === 'true') {
bnEl.remove()
}
- ์ฟ ํค๊ฐ ์ ์ฅ๋์ด ์๋์ง ํ์ธ
- cookieValue === 'true' ์ผ์ ์ฟ ํค๊ฐ ์ ์ฅ๋์ด ์์ -> ๋ฐฐ๋๋ฅผ ์ ๊ฑฐํ๋ค
๐ ๋ง๋ฌด๋ฆฌ
๋๋ฆ ์ฒซ ํด๋ก ์ฝ๋ฉ์ ์ฒซ ํ๋ก์ ํธ์๋๋ฐ ๊ธฐ์กด ์ฌ์ดํธ์ ๊ธฐ๋ฅ์ ์์ ํ ๊ฐ์ ธ์ค์ง ๋ชปํ ์ ์ด ์์ฝ๊ฒ ๋๊ปด์ง๋ค.
๊ทธ๋๋ HTML๋ฅผ ๊ตฌ์กฐ์ ์ผ๋ก ์์ฑํ๋ ๋ฐฉ์์ ๋ฐฐ์ฐ๊ณ , CSS flex์ transition ์ ๋๋ฉ์ด์ ์ ์ฌ์ฉํด๋ณธ ์ ์ ๋ฟ๋ฏํ๋ค.
์์ผ๋ก ๋์ฑ ๋ฐฐ์ฐ๊ณ ์จ๋จน์ด๋ด์ผ๊ฒ ๋ค ๐
ํ๊ณ ๋ฅผ ์์ฑํ๋ฉด์ ๋๋์ ์ ์๋ฌํด๊ฒฐํ๋ ๊ณผ์ ์ ๊ธฐ๋กํ๋ ๊ฒ์ด ์ค์ํ๋ค๋ ๊ฒ์ด๋ ๐ฑ ๋ฉฐ์น ์ ์ด๋ผ๊ณ ๋ฒ์จ๋ถํฐ ๊ธฐ์ต์ด ๋์ง ์๋๋ค..
๋ค์ ํ๋ก์ ํธ ์์๋ ๊ผญ! ์๋ฌ์ํฉ๊ณผ ๋ฌธ์ ํด๊ฒฐ ๊ณผ์ ์ ๊ธฐ๋กํด๋ฌ์ผ๊ฒ ๋ค ๐ค