처음에는 반응형으로 만들어서 모든 디바이스에 대응하도록 하고 싶었지만, 시간이 부족할 것 같습니다. 여건이 되는대로 개선하는 것을 목표로 해보겠습니다 ㅠㅠ
개발자 도구로 네비게이션 메뉴들에 대해 확인하던 중 "여기서 line-height
를 적용한다고?"라고 생각되는 부분이 있었습니다. 이와 관련해서 생각해본 결과 "사용자의 편의성을 위해 li 요소의 글자가 아닌 상하좌우 영역을 클릭하더라도 링크가 동작할 수 있도록 하고자 한다. 그리고, 가운데로 정렬하여 디자인적인 요소를 스타일링한다" 라는 결론을 내리게 되었습니다. 실제 카카오 사이트의 네비게이션 메뉴글씨 상하단 영역으로 마우스를 올리더라도 클릭시 해당 링크로 이동할 수 있으며 글자는 li의 가운데 정렬 되있습니다.
일종의 css trick
이라고 생각이 되며,
작업 중간에 flex
로 개선할 수도 있지만, line-height
를 적용해서 진행해보겠습니다.
당차게 navigation 영역을 작성하다가 첫번째 난관에 부딪혔습니다.
hover시 어떻게 처리할 것인가에 대한 문제이며 아래와 같은 고민을 하였습니다.
가능한 css만으로 구현하고 싶어서 생각해보았고, 그 결과 구현을 할 수 있었습니다.
제가 구현한 방법은 아래와 같습니다.
if(kakao) 2022
은 id를 부여해서 우선순위를 더 높게 준 뒤, 해당 item만이 가져야 되는 스타일을 정의해준다.if(kakao) 2022
를 제외한 모든 item의 글자색을 원하는 색으로 지정한다(#888
)/* gnb(nav) */
.gnb {
&_list {
display: flex;
align-items: center;
font-family: sans-serif;
color: $fontColor;
margin-left: 74px;
&:hover > li > a:not(#link_if_kakao) {
color: #888;
}
}
.list_sub {
position: absolute;
top: 60px;
left: 4px;
}
&_item {
position: relative;
color: $fontColor;
.link_menu {
display: block;
color: $fontColor;
flex-shrink: 0;
font-weight: 700;
padding: 0 28px;
line-height: 72px;
&:hover:not(#link_if_kakao) {
color: inherit;
}
}
#link_if_kakao {
height: 42px;
line-height: 42px;
padding: 0 20px;
color: #fff;
background-color: #000;
border-radius: 21px;
position: relative;
&::after {
content: "";
position: absolute;
top: 0;
right: -6px;
width: 6px;
height: 6px;
background-color: #ff4024;
border-radius: 50%;
}
}
}
}
결과
클릭할 때의 구현을 위해서는 js를 이용해야 될 것 같다는 생각이 들었습니다. css 가상 선택자 중에 클릭했을 때의 요소에 대한 것은 없다고 알고 있기 때문입니다. focus가 대안이 될수는 있겠지만 완벽한 대안이라고 하기에는 말하기 어려울 것 같습니다.
js를 활용해 구현하기 위해 생각한 방법은 아래와 같습니다.
.on
클래스를 활용한 스타일을 적용position:absolute
로 배치하기 위해서).on
클래스를 토글하여 스타일을 적용.on
클래스 제거결과
기한 내 제출이 어려울 수도 있기 때문에 먼저는 생략하고 진행하지만, 만약 시간적 여유가 있다면 작업해보는 것으로 하겠습니다 ㅠㅠ
단, button에 대해 focus 가능하도록 하기 위해 요소에 tabindex를 설정해주고, focus시 outline이 생기도록 css 스타일링 하겠습니다.
NotoSansKR
(sans-serif
, 고딕체 계열) 구글 웹폰트를 사용했습니다.sub_menu_list
의 width
가 미세하게 증가해서 화면에 출력됨 max-width:352px
로 설정하여 미세하게 width가 증가하지 않도록 함<!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" />
<meta property="og:type" content="website" />
<meta property="og:site_name" content="kakaocorp.com" />
<meta property="og:url" content="https://www.kakaocorp.com/page/" />
<meta property="og:title" content="Kakao" />
<meta
property="og:image"
content="https://t1.kakaocdn.net/kakaocorp/corp_thumbnail/Kakao.png"
/>
<meta
property="og:description"
content="기술과 사람으로 더 나은 세상을 만듭니다"
/>
<meta
name="description"
content="기술과 사람으로 더 나은 세상을 만듭니다"
/>
<title>카카오</title>
<link rel="shortcut icon" href="/favicon.ico" />
<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=Noto+Sans+KR:wght@400;500;700&display=swap"
rel="stylesheet"
/>
<link rel="stylesheet" href="./styles/main.scss" />
<script defer src="./src/index.js"></script>
</head>
<body>
<header class="landing_header">
<div class="landing_header__wrapper">
<!-- logo -->
<a class="logo_link" href="https://www.kakaocorp.com/page/">
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 75 25"
class="ico_logo"
>
<defs>
<path
data-v-37d948ec=""
id="os5cgsl0ta"
d="M0.011 0.205L11.948 0.205 11.948 22.203 0.011 22.203z"
></path>
<path
data-v-37d948ec=""
id="oanpyfjipc"
d="M0.264 0.004L13.566 0.004 13.566 15.487 0.264 15.487z"
></path>
</defs>
<g fill="#000" fill-rule="evenodd">
<g>
<path
d="M18.91 20.05c.344 0 .7-.046 1.071-.137.371-.09.742-.209 1.113-.354.371-.146.72-.323 1.045-.532.327-.21.616-.432.87-.668V14.87h-2.607c-1.32 0-2.284.227-2.89.681-.606.455-.91 1.173-.91 2.154 0 1.562.769 2.344 2.308 2.344m-4.706-2.235c0-1.508.503-2.658 1.513-3.448 1.008-.79 2.476-1.186 4.401-1.186h2.89v-.954c0-2.308-1.018-3.461-3.053-3.461-.653 0-1.34.09-2.057.272-.719.182-1.377.409-1.977.681l-.736-1.771c.745-.418 1.55-.74 2.413-.968.862-.227 1.704-.341 2.52-.341 3.526 0 5.288 1.88 5.288 5.642v9.54h-1.852l-.3-1.635c-.745.6-1.54 1.063-2.385 1.39-.845.328-1.649.49-2.414.49-1.325 0-2.365-.376-3.12-1.13-.754-.754-1.131-1.794-1.131-3.12"
transform="translate(-151 -168) translate(79.5 145) translate(72 24) translate(.956 .112)"
class="path"
></path>
<g
transform="translate(-151 -168) translate(79.5 145) translate(72 24) translate(.956 .112) translate(29.859)"
>
<mask id="5ym1s98mqb" fill="#fff">
<use xlink:href="#os5cgsl0ta"></use>
</mask>
<path
d="M9.222 6.53l1.963 1.416-4.823 6.052 5.586 6.705-1.934 1.5-6.596-8.07L9.222 6.53zM2.518 21.82H.011V.75L2.518.206V21.82z"
mask="url(#5ym1s98mqb)"
class="path"
></path>
</g>
<path
d="M48.735 20.05c.343 0 .701-.046 1.072-.137.371-.09.742-.209 1.113-.354.37-.146.718-.323 1.045-.532.324-.21.614-.432.868-.668V14.87h-2.606c-1.322 0-2.285.227-2.89.681-.607.455-.909 1.173-.909 2.154 0 1.562.768 2.344 2.307 2.344m-4.706-2.235c0-1.508.504-2.658 1.512-3.448 1.01-.79 2.475-1.186 4.403-1.186h2.889v-.954c0-2.308-1.017-3.461-3.053-3.461-.655 0-1.34.09-2.058.272-.719.182-1.377.409-1.975.681l-.737-1.771c.746-.418 1.55-.74 2.412-.968.862-.227 1.703-.341 2.522-.341 3.524 0 5.288 1.88 5.288 5.642v9.54h-1.855l-.3-1.635c-.745.6-1.538 1.063-2.385 1.39-.844.328-1.648.49-2.411.49-1.327 0-2.368-.376-3.121-1.13-.755-.754-1.131-1.794-1.131-3.12"
transform="translate(-151 -168) translate(79.5 145) translate(72 24) translate(.956 .112)"
class="path"
></path>
<g
transform="translate(-151 -168) translate(79.5 145) translate(72 24) translate(.956 .112) translate(58.405 6.66)"
>
<mask id="e5668wah2d" fill="#fff">
<use xlink:href="#oanpyfjipc"></use>
</mask>
<path
d="M6.915 2.021c-1.308 0-2.312.491-3.011 1.472-.701.982-1.05 2.417-1.05 4.307 0 1.872.349 3.285 1.05 4.239.699.954 1.703 1.431 3.011 1.431 1.326 0 2.34-.477 3.04-1.431.7-.954 1.049-2.367 1.049-4.239 0-1.89-.35-3.325-1.049-4.307-.7-.981-1.714-1.472-3.04-1.472m0-2.017c2.071 0 3.699.673 4.878 2.017 1.182 1.346 1.773 3.272 1.773 5.78 0 2.47-.585 4.37-1.758 5.697-1.172 1.325-2.804 1.989-4.893 1.989-2.07 0-3.698-.664-4.878-1.99C.855 12.172.264 10.272.264 7.8c0-2.507.594-4.433 1.785-5.779C3.24.677 4.862.004 6.915.004"
mask="url(#e5668wah2d)"
class="path"
></path>
</g>
<path
d="M2.552.205L.044.75v21.07h2.508V.204zm.9 13.929l6.595 8.069 1.937-1.5-5.589-6.705 4.825-6.051-1.962-1.418-5.807 7.605z"
transform="translate(-151 -168) translate(79.5 145) translate(72 24) translate(.956 .112)"
class="path"
></path>
</g>
</g>
</svg>
</a>
<!-- nav -->
<nav class="gnb">
<ul class="gnb_list">
<li class="gnb_item flex-container--not-shrink">
<a class="menu_link" href="javascript:void(0)">카카오</a>
<ul class="gnb_sub_list">
<li class="gnb_sub_list_item flex-container--not-shrink">
<a
class="sub_menu_link"
href="https://www.kakaocorp.com/page/kakao/kakaoCulture"
>카카오문화</a
>
</li>
<li class="gnb_sub_list_item flex-container--not-shrink">
<a
class="sub_menu_link"
href="https://www.kakaocorp.com/page/kakao/subsidiaryCompany"
>공동체</a
>
</li>
<li class="gnb_sub_list_item flex-container--not-shrink">
<a
class="sub_menu_link"
href="https://www.kakaocorp.com/page/kakao/history"
>히스토리</a
>
</li>
</ul>
</li>
<li class="gnb_item flex-container--not-shrink">
<a class="menu_link" href="https://www.kakaocorp.com/page/news"
>뉴스</a
>
</li>
<li class="gnb_item flex-container--not-shrink">
<a class="menu_link" href="javascript:void(0)">기술과 서비스</a>
<ul class="gnb_sub_list">
<li class="gnb_sub_list_item flex-container--not-shrink">
<a
class="sub_menu_link"
href="https://www.kakaocorp.com/page/service/tech"
>기술</a
>
</li>
<li class="gnb_sub_list_item flex-container--not-shrink">
<a
class="sub_menu_link"
href="https://www.kakaocorp.com/page/service/service"
>서비스</a
>
</li>
</ul>
</li>
<li class="gnb_item flex-container--not-shrink">
<a class="menu_link" href="javascript:void(0)">약속과 책임</a>
<ul class="gnb_sub_list">
<li class="gnb_sub_list_item flex-container--not-shrink">
<a
class="sub_menu_link"
href="https://www.kakaocorp.com/page/responsible/esg"
>ESG</a
>
</li>
<li class="gnb_sub_list_item flex-container--not-shrink">
<a
class="sub_menu_link"
href="https://www.kakaocorp.com/page/responsible/social"
>소셜임팩트</a
>
</li>
<li class="gnb_sub_list_item flex-container--not-shrink">
<a
class="sub_menu_link"
href="https://www.kakaocorp.com/page/responsible/digital"
>디지털 권리</a
>
</li>
<li class="gnb_sub_list_item flex-container--not-shrink">
<a
class="sub_menu_link"
href="https://www.kakaocorp.com/page/responsible/aiEthics"
>AI 윤리</a
>
</li>
</ul>
</li>
<li class="gnb_item flex-container--not-shrink">
<a
class="menu_link"
id="link_if_kakao"
href="https://if.kakao.com/"
target="_blank"
>if(Kakao) 2022</a
>
</li>
</ul>
</nav>
<!-- util-area -->
<div class="area-util flex-container--not-shrink">
<!-- search-button -->
<button class="btn btn_search" tabindex="0">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 28 28"
class="ico ico_search"
>
<g fill="none" fill-rule="evenodd">
<g stroke-width="1.6">
<g transform="translate(-308 -16) translate(312 20)">
<circle cx="8.944" cy="8.944" r="8.944"></circle>
<path d="M14.987 14.987L21.017 21.017"></path>
</g>
</g>
</g>
</svg>
</button>
<!-- language-button -->
<button class="btn btn_language" tabindex="0">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
class="ico ico_language"
>
<g fill="none" fill-rule="evenodd">
<g stroke-width="1.35">
<path
d="M19.353 9.914c0 5.213-4.226 9.438-9.438 9.438-5.213 0-9.438-4.225-9.438-9.438C.477 4.702 4.702.477 9.915.477c5.212 0 9.438 4.225 9.438 9.437z"
transform="translate(-1402 -23) translate(1358 23) translate(44) translate(2 2)"
></path>
<path
stroke-linejoin="round"
d="M13.662 9.914c0 5.213-3.748 9.438-3.748 9.438s-3.747-4.225-3.747-9.438c0-5.212 3.747-9.437 3.747-9.437s3.748 4.225 3.748 9.437z"
transform="translate(-1402 -23) translate(1358 23) translate(44) translate(2 2)"
></path>
<path
d="M.876 7.018L18.952 7.018M.876 12.811L18.952 12.811"
transform="translate(-1402 -23) translate(1358 23) translate(44) translate(2 2)"
></path>
</g>
</g>
</svg>
</button>
<!-- theme-button(darkMode) -->
<button class="btn btn_theme" tabindex="0">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
class="ico ico_theme"
>
<g fill="none" fill-rule="evenodd" stroke-linejoin="round">
<g stroke-width="1.5">
<path
d="M16.086 13.417c-5.013 0-9.076-4.04-9.076-9.023 0-1.596.42-3.093 1.152-4.394C3.58.456 0 4.3 0 8.977 0 13.961 4.064 18 9.076 18c3.407 0 6.372-1.868 7.924-4.628-.3.03-.605.045-.914.045z"
transform="translate(-1344 -24) translate(1248 24) translate(96) translate(4 3)"
></path>
</g>
</g>
</svg>
</button>
</div>
</div>
</header>
</body>
</html>
/* ./styles/main.scss */
@import url("./_reset.scss");
@import url("https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@400;500;700&display=swap");
/* global */
$fontColor: #000;
$baseForeground: #000;
$buttonBaseBackground: transparent;
$buttonBaseHoverColor: #eee;
body {
font-family: "Noto Sans KR", sans-serif;
}
a {
text-decoration: none;
}
.btn {
appearance: none;
outline: none;
border: none;
margin: 0;
padding: 0;
border-radius: 1.125em;
background-color: $buttonBaseBackground;
font-weight: 400;
color: #333;
cursor: pointer;
&:hover {
background-color: $buttonBaseHoverColor;
}
}
/* icon */
.ico {
width: 24px;
height: 24px;
vertical-align: top;
}
/* custom-common-styles (for deduplication) */
.flex-container--not-shrink {
display: flex;
flex-shrink: 0;
}
/* header */
.landing_header {
position: fixed;
width: 100%;
top: 0;
left: 0;
&__wrapper {
display: flex;
align-items: center;
min-width: 952px;
max-width: 1296px;
margin: 0 auto;
height: 72px;
justify-content: space-between;
a.logo_link {
display: block;
text-decoration: none;
width: 74px;
height: 24px;
.ico_logo {
width: 100%;
height: 100%;
}
}
}
}
/* gnb(nav) */
.gnb {
&_list {
display: flex;
align-items: center;
color: $fontColor;
margin-left: 74px;
&:hover > li > a:not(#link_if_kakao) {
color: #888;
}
&:hover > li.on > a:not(#link_if_kakao) {
color: inherit;
}
}
&_item {
position: relative;
color: $fontColor;
.menu_link {
display: block;
color: $fontColor;
flex-shrink: 0;
font-weight: 700;
padding: 0 28px;
line-height: 72px;
&:hover:not(#link_if_kakao) {
color: inherit;
}
}
&:not(.on) {
.gnb_sub_list {
display: none;
}
}
&.on {
.gnb_sub_list {
position: absolute;
display: flex;
gap: 24px;
width: max-content;
max-width: 352px;
border-radius: 24px;
top: 60px;
left: 4px;
padding: 0 24.5px;
background-color: $baseForeground;
box-sizing: border-box;
&_item {
.sub_menu_link {
display: block;
color: #eee;
font-weight: 500;
flex-shrink: 0;
padding: 11px 0 13px;
line-height: 24px;
z-index: 99;
&:hover {
font-weight: 700;
color: #eee;
}
}
}
}
}
#link_if_kakao {
height: 42px;
line-height: 42px;
padding: 0 20px;
color: #fff;
background-color: $baseForeground;
border-radius: 21px;
position: relative;
&::after {
content: "";
position: absolute;
top: 0;
right: -6px;
width: 6px;
height: 6px;
background-color: #ff4024;
border-radius: 50%;
}
}
}
}
/* util-area */
.area-util {
gap: 12px;
.btn {
width: 36px;
height: 36px;
flex-shrink: 0;
&:focus {
outline: 2px solid;
border-radius: 50%;
}
&_search {
&:hover {
border-radius: 50%;
}
.ico_search {
stroke: $baseForeground;
}
}
&_language {
&:hover {
border-radius: 50%;
}
.ico_language {
stroke: $baseForeground;
}
}
&_theme {
&:hover {
border-radius: 100%;
}
.ico_theme {
stroke: $baseForeground;
}
}
}
}
// ./src/index.js
const attachNavMenuEvent = () => {
const $nav_menu_items = document.querySelectorAll(
".gnb_list > li:not(:last-child)"
);
const notExpandMenuTitles = ["뉴스"];
$nav_menu_items.forEach((menu_item) => {
menu_item.addEventListener("click", (e) => {
const title = e.currentTarget.querySelector("a").textContent;
if (notExpandMenuTitles.includes(title)) {
return;
}
const [activedMenu] = Array.from($nav_menu_items).filter((menu_item) =>
menu_item.classList.contains("on")
);
if (activedMenu) activedMenu.classList.remove("on");
e.currentTarget.classList.toggle("on");
});
});
window.addEventListener(
"click",
(e) => {
const [activedMenu] = Array.from($nav_menu_items).filter((menu_item) =>
menu_item.classList.contains("on")
);
if (!activedMenu) return;
if (e.target !== activedMenu) activedMenu.classList.remove("on");
},
true
);
};
attachNavMenuEvent();