下拉导航菜单
兼顾桌面悬停与移动端点击操作的响应式导航。
启用 JavaScript 后可编辑、运行和保存此案例。固定源码如下:
<!doctype html>
<html lang="zh-Hans" dir="ltr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>下拉导航菜单</title>
<style>
* { box-sizing: border-box; }
body { min-height: 100vh; margin: 0; color: #1d2a25; font-family: "Avenir Next", "Microsoft YaHei", sans-serif; background: #f7f5ef; }
nav { position: relative; z-index: 5; display: flex; align-items: center; gap: 28px; width: min(1160px, calc(100% - 36px)); margin: 18px auto 0; padding: 12px 16px 12px 22px; border: 1px solid #d9ded7; border-radius: 18px; background: rgba(255,255,255,.92); box-shadow: 0 16px 40px rgba(42,64,55,.08); }
.brand { color: #1d2a25; font: 800 22px/1 Georgia, serif; text-decoration: none; letter-spacing: -.04em; }
.brand i { color: #e96545; font-style: normal; }
.menu { display: flex; align-items: center; gap: 6px; margin-left: auto; padding: 0; list-style: none; }
.menu > li { position: relative; }
.menu a, .drop-trigger { display: flex; align-items: center; gap: 7px; padding: 11px 13px; border: 0; border-radius: 10px; color: #48554f; font: inherit; font-size: 14px; font-weight: 700; text-decoration: none; background: transparent; cursor: pointer; }
.menu a:hover, .drop-trigger:hover, .drop-trigger[aria-expanded="true"] { color: #1d2a25; background: #f0f4ef; }
.drop-trigger::after { content: "⌄"; color: #85928c; transition: transform .2s ease; }
.drop-trigger[aria-expanded="true"]::after { transform: rotate(180deg); }
.dropdown { position: absolute; top: calc(100% + 10px); left: 0; width: 270px; padding: 10px; border: 1px solid #dce1dc; border-radius: 15px; background: #fff; box-shadow: 0 20px 50px rgba(42,64,55,.16); opacity: 0; visibility: hidden; transform: translateY(-8px); transition: .2s ease; }
.drop-trigger[aria-expanded="true"] + .dropdown { opacity: 1; visibility: visible; transform: none; }
.dropdown a { align-items: flex-start; padding: 12px; }
.dropdown b { display: block; color: #27352f; font-size: 13px; }
.dropdown small { display: block; margin-top: 3px; color: #84908a; font-weight: 500; line-height: 1.4; }
.nav-action { margin-left: 4px; padding: 11px 17px; border: 0; border-radius: 10px; color: white; font: inherit; font-weight: 800; background: #e96545; cursor: pointer; }
.menu-toggle { display: none; margin-left: auto; width: 42px; height: 42px; border: 1px solid #dce1dc; border-radius: 10px; color: #27352f; font-size: 20px; background: white; cursor: pointer; }
button:focus-visible, a:focus-visible { outline: 3px solid #e96545; outline-offset: 2px; }
main { width: min(1100px, calc(100% - 40px)); margin: 0 auto; min-height: calc(100vh - 100px); display: grid; place-items: center; text-align: center; }
.hero { max-width: 760px; }
.eyebrow { color: #e96545; font-size: 12px; font-weight: 900; letter-spacing: .19em; }
h1 { margin: 14px 0 18px; font: 700 clamp(44px, 9vw, 88px)/.95 Georgia, "STSong", serif; letter-spacing: -.05em; }
.hero p { max-width: 600px; margin: auto; color: #6b7771; font-size: 17px; line-height: 1.8; }
@media (min-width: 761px) { .has-dropdown:hover .dropdown { opacity: 1; visibility: visible; transform: none; } }
@media (max-width: 760px) {
nav { flex-wrap: wrap; }
.menu-toggle { display: block; }
.menu { display: none; flex: 1 0 100%; align-items: stretch; flex-direction: column; margin: 0; padding-top: 8px; border-top: 1px solid #e8ebe7; }
.menu.is-open { display: flex; }
.menu a, .drop-trigger { width: 100%; justify-content: space-between; }
.dropdown { position: static; display: none; width: 100%; margin-top: 4px; box-shadow: none; opacity: 1; visibility: visible; transform: none; }
.drop-trigger[aria-expanded="true"] + .dropdown { display: block; }
.nav-action { width: 100%; margin: 4px 0 0; }
}
@media (prefers-reduced-motion: reduce) { .dropdown, .drop-trigger::after { transition: none; } }
</style>
</head>
<body>
<nav aria-label="主导航">
<a class="brand" href="#">North<i>·</i>Lab</a>
<button id="menuToggle" class="menu-toggle" type="button" aria-expanded="false" aria-controls="mainMenu" aria-label="展开导航">☰</button>
<ul id="mainMenu" class="menu">
<li><a href="#work">作品</a></li>
<li class="has-dropdown"><button class="drop-trigger" type="button" aria-expanded="false">服务</button><div class="dropdown"><a href="#strategy"><span><b>品牌策略</b><small>找到品牌真正独特的表达方式</small></span></a><a href="#design"><span><b>数字产品</b><small>从原型到上线的完整体验设计</small></span></a><a href="#motion"><span><b>动态视觉</b><small>用节奏与运动讲好产品故事</small></span></a></div></li>
<li><a href="#about">关于</a></li>
<li><a href="#journal">手记</a></li>
<li><button class="nav-action" type="button">开始合作</button></li>
</ul>
</nav>
<main><section class="hero"><span class="eyebrow">INDEPENDENT DESIGN STUDIO</span><h1>复杂问题,简单表达</h1><p>这个导航在桌面端支持悬停与点击,在小屏幕上自动变成可展开菜单。试着缩放窗口查看变化。</p></section></main>
<script>
const menuToggle = document.querySelector('#menuToggle');
const menu = document.querySelector('#mainMenu');
const dropTrigger = document.querySelector('.drop-trigger');
menuToggle.addEventListener('click', () => {
const open = menuToggle.getAttribute('aria-expanded') !== 'true';
menuToggle.setAttribute('aria-expanded', String(open));
menu.classList.toggle('is-open', open);
});
dropTrigger.addEventListener('click', () => dropTrigger.setAttribute('aria-expanded', String(dropTrigger.getAttribute('aria-expanded') !== 'true')));
document.addEventListener('click', event => {
if (!event.target.closest('.has-dropdown')) dropTrigger.setAttribute('aria-expanded', 'false');
});
</script>
</body>
</html>