Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 85 additions & 1 deletion script.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,83 @@ if (year) year.textContent = String(new Date().getFullYear());
// Mobile nav: hamburger toggle
const navToggle = document.getElementById("navToggle");
const navInner = document.querySelector(".nav__inner");

function rectsOverlap(a, b, gap) {
gap = gap == null ? 2 : gap;
return a.right > b.left + gap && a.left < b.right - gap && a.bottom > b.top + gap && a.top < b.bottom - gap;
}

function detectNavBarOverlap(inner) {
var menuWrap = inner.querySelector(".nav__menu-wrap");
var links = menuWrap && menuWrap.querySelector(".nav__links");
var actions = menuWrap && menuWrap.querySelector(".nav__actions");
var brand = inner.querySelector(".brand");
var toggle = inner.querySelector(".nav__toggle");
if (!menuWrap || !links || !actions || !brand) return false;

var toggleWidth = toggle ? toggle.getBoundingClientRect().width : 40;
var reserved = brand.getBoundingClientRect().width + toggleWidth + 24;
if (menuWrap.scrollWidth > inner.clientWidth - reserved + 1) return true;

var linksRect = links.getBoundingClientRect();
var actionsRect = actions.getBoundingClientRect();
if (Math.abs(linksRect.top - actionsRect.top) < 8 && linksRect.right > actionsRect.left + 2) {
return true;
}

var linkItems = links.querySelectorAll(":scope > a, :scope > .nav__dropdown");
for (var i = 0; i < linkItems.length; i += 1) {
var r1 = linkItems[i].getBoundingClientRect();
if (r1.width < 1) continue;
for (var j = i + 1; j < linkItems.length; j += 1) {
var r2 = linkItems[j].getBoundingClientRect();
if (r2.width < 1) continue;
if (Math.abs(r1.top - r2.top) < 4 && r1.right > r2.left + 1) return true;
}
if (toggle && rectsOverlap(r1, toggle.getBoundingClientRect(), 0)) return true;
if (rectsOverlap(r1, actionsRect, 0)) return true;
}

if (toggle && rectsOverlap(toggle.getBoundingClientRect(), actionsRect, 0)) return true;
return false;
}

function updateNavCollapse() {
if (!navInner) return;

if (window.innerWidth <= 768) {
navInner.classList.add("nav--collapsed");
return;
}

navInner.classList.remove("nav--collapsed");
navInner.classList.remove("nav--open");
if (navToggle) navToggle.setAttribute("aria-expanded", "false");

if (detectNavBarOverlap(navInner)) {
navInner.classList.add("nav--collapsed");
}
}

function initNavCollapse() {
updateNavCollapse();
var timer = null;
function scheduleUpdate() {
if (timer) clearTimeout(timer);
timer = setTimeout(updateNavCollapse, 80);
}
window.addEventListener("resize", scheduleUpdate);
window.addEventListener("languagechange", scheduleUpdate);
window.addEventListener("load", updateNavCollapse);
if (typeof ResizeObserver !== "undefined") {
var ro = new ResizeObserver(scheduleUpdate);
ro.observe(navInner);
var menuWrap = navInner.querySelector(".nav__menu-wrap");
if (menuWrap) ro.observe(menuWrap);
}
scheduleUpdate();
}

if (navToggle && navInner) {
navToggle.addEventListener("click", function () {
var open = navInner.classList.toggle("nav--open");
Expand All @@ -25,13 +102,20 @@ if (navToggle && navInner) {
}
}

if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", initNavCollapse);
} else {
initNavCollapse();
}

// Mobile: "项目" dropdown click-to-toggle (instead of hover)
function initNavDropdownMobile() {
var dropbtn = document.querySelector(".nav__dropdown .nav__dropbtn");
var dropdown = document.querySelector(".nav__dropdown");
if (!dropbtn || !dropdown) return;
dropbtn.addEventListener("click", function (e) {
if (window.innerWidth > 768) return;
var inner = document.querySelector(".nav__inner");
if (!inner || !inner.classList.contains("nav--collapsed")) return;
e.preventDefault();
dropdown.classList.toggle("is-open");
});
Expand Down
76 changes: 75 additions & 1 deletion styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -584,8 +584,80 @@ html[lang="zh-CN"] .nav__dropbtn{ letter-spacing: 0.15em; }
.hero__title-main{ font-size: 56px; }
.hero__title-sub{ font-size: 32px; }
}

/* 导航栏收起:JS 检测到区域重叠,或窄屏时 */
.nav__inner.nav--collapsed .nav__toggle{ display: flex; margin-left: auto; }
.nav__inner.nav--collapsed .nav__menu-wrap{
display: none;
position: absolute;
top: 100%;
left: 0;
right: 0;
flex-direction: column;
background: var(--bg);
border-bottom: 1px solid var(--line);
padding: 12px 16px 20px;
box-shadow: 0 10px 30px rgba(0,0,0,0.08);
z-index: 40;
}
.nav__inner.nav--collapsed.nav--open .nav__menu-wrap{ display: flex; }
.nav__inner.nav--collapsed .nav__links{
flex-direction: column;
flex-wrap: nowrap;
align-items: stretch;
margin-left: 0;
width: 100%;
gap: 4px;
}
.nav__inner.nav--collapsed .nav__links > a,
.nav__inner.nav--collapsed .nav__links > .nav__dropdown{
min-width: 0;
}
.nav__inner.nav--collapsed .nav__links > a{
display: block;
width: 100%;
padding: 12px 14px;
text-align: left;
border-radius: 10px;
}
.nav__inner.nav--collapsed .nav__dropdown{
position: static;
width: 100%;
}
.nav__inner.nav--collapsed .nav__dropdown .nav__dropbtn{
display: flex;
justify-content: flex-start;
align-items: center;
width: 100%;
min-width: 0;
padding: 12px 14px;
text-align: left;
border-radius: 10px;
}
.nav__inner.nav--collapsed .nav__dropdown .nav__menu{
position: static;
min-width: auto;
box-shadow: none;
padding: 8px 0 8px 16px;
margin-top: 4px;
margin-bottom: 8px;
border-left: 2px solid var(--line);
display: none;
}
.nav__inner.nav--collapsed .nav__dropdown.is-open .nav__menu{ display: block; }
.nav__inner.nav--collapsed .nav__dropdown.is-open .nav__chev{ transform: rotate(180deg); }
.nav__inner.nav--collapsed .nav__actions{
margin-left: 0;
width: 100%;
border-top: 1px solid var(--line);
padding-top: 12px;
margin-top: 8px;
}
.nav__inner.nav--collapsed{ padding: 12px 16px; flex-wrap: wrap; }

@media (max-width: 768px){
html, body{ overflow-x: hidden; }
.nav__inner{ padding: 12px 16px; flex-wrap: wrap; }
.nav__toggle{ display: flex; margin-left: auto; }
.nav__menu-wrap{
display: none;
Expand All @@ -612,19 +684,22 @@ html[lang="zh-CN"] .nav__dropbtn{ letter-spacing: 0.15em; }
.nav__links > a{
display: block;
width: 100%;
min-width: 0;
padding: 12px 14px;
text-align: left;
border-radius: 10px;
}
.nav__dropdown{
position: static;
width: 100%;
min-width: 0;
}
.nav__dropdown .nav__dropbtn{
display: flex;
justify-content: flex-start;
align-items: center;
width: 100%;
min-width: 0;
padding: 12px 14px;
text-align: left;
border-radius: 10px;
Expand All @@ -648,7 +723,6 @@ html[lang="zh-CN"] .nav__dropbtn{ letter-spacing: 0.15em; }
padding-top: 12px;
margin-top: 8px;
}
.nav__inner{ padding: 12px 16px; flex-wrap: wrap; }
.page{ padding: 20px 16px 48px; }
.hero{ padding-top: 20px; gap: 24px; }
.hero__left{ min-width: 0; width: 100%; }
Expand Down
Loading