ساخت Header متحرک با CSS
Header متحرک یا هدر دینامیک یکی از المانهای متداول در طراحی وبسایتهای امروزی است. هدف میتواند ثابت نگه داشتن منو (sticky)، جمعشدن هنگام اسکرول (shrink)، یا پنهان/نمایان شدن هوشمندانه برای بهبود فضای محتوایی باشد. در این مقاله نحوه پیادهسازی چند الگوی رایج با تاکید بر عملکرد، دسترسیپذیری و بهترین شیوهها توضیح داده میشود.
چرا از Header متحرک استفاده کنیم؟
- دسترسی سریع به ناوبری بدون اشغال فضای زیاد.
- بهبود تجربه کاربر در صفحات بلند.
- قابلیت نمایش/پنهان کردن بر اساس رفتار کاربر برای افزایش تمرکز روی محتوا.
انواع رایج Header متحرک
- Sticky (چسبان) — با CSS فقط؛ ساده و کمهزینه.
- Shrink on scroll — هدر هنگام اسکرول کوچک میشود؛ معمولاً با JS.
- Hide/Show on scroll — هنگام اسکرول به پایین پنهان و به بالا نمایان میشود؛ با JS بهینهتر است.
- Animated reveal — افکت ظاهر شدن یا پارالاکس؛ برای زیبایی با توجه به عملکرد استفاده شود.
مثال 1 — Header چسبان ساده با CSS
<header class="site-header">
<div class="container">
<h1>Logo</h1>
<nav>...</nav>
</div>
</header>
.site-header {
position: sticky;
top: 0;
z-index: 1000;
background: rgba(255,255,255,0.95);
backdrop-filter: blur(4px); /* optional */ box-shadow: 0 1px 4px rgba(0,0,0,0.08);
transition: box-shadow 200ms ease, transform 200ms ease;
}توضیح: این کد یک هدر چسبان ساده میسازد. position: sticky باعث میشود هدر تا رسیدن به بالای نما به حالت عادی باشد و پس از آن بچسبد. استفاده از backdrop-filter برای افکت مات (در مرورگرهای پشتیبانیشده) و transition برای حرکت نرم پیشنهاد شده است. این روش کمترین هزینه پردازشی را دارد و برای بیشتر سایتها کافی است.
مثال 2 — جمعشدن هدر هنگام اسکرول (JS + CSS)
<header id="mainHeader" class="header" role="banner">
<div class="header-inner">
<h1 class="logo">Site</h1>
<nav>...</nav>
</div>
</header>
/* CSS */.header {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 80px;
background: #fff;
transition: height 200ms ease, box-shadow 200ms ease;
z-index: 1000;
}
.header.shrink {
height: 56px;
box-shadow: 0 2px 8px rgba(0,0,0,0.12);
}
/* JS (vanilla) */let lastScroll = 0;
const header = document.getElementById('mainHeader');
window.addEventListener('scroll', () => {
const current = window.pageYOffset || document.documentElement.scrollTop;
if (current > 100) {
header.classList.add('shrink');
} else {
header.classList.remove('shrink');
}
lastScroll = current;
});توضیح: در این مثال با استفاده از JS وقتی که اسکرول از 100px بیشتر شود، کلاس shrink به هدر اضافه میشود و ارتفاع هدر با CSS کاهش مییابد. این روش کنترل دقیقتری روی آستانه و افکتها میدهد. برای جلوگیری از فلکر یا بار زیاد پردازشی میتوان از requestAnimationFrame یا تکنیک debouncing استفاده کرد.
مثال 3 — پنهان/نمایان شدن Header هنگام اسکرول (بهینه با requestAnimationFrame)
/* HTML: همان header با id="mainHeader" */
/* CSS */.header.hide {
transform: translateY(-110%);
transition: transform 220ms cubic-bezier(.2,.7,.2,1);
}
.header.show {
transform: translateY(0);
}
/* JS */let lastY = 0;
let ticking = false;
const headerEl = document.getElementById('mainHeader');
function onScroll() {
const currentY = window.pageYOffset || document.documentElement.scrollTop;
if (!ticking) {
window.requestAnimationFrame(() => {
if (currentY > lastY && currentY > 120) {
// scrolling down
headerEl.classList.remove('show');
headerEl.classList.add('hide');
} else {
// scrolling up
headerEl.classList.remove('hide');
headerEl.classList.add('show');
}
lastY = currentY > 0 ? currentY : 0;
ticking = false;
});
ticking = true;
}
}
window.addEventListener('scroll', onScroll);توضیح: این الگو هدر را هنگام اسکرول به پایین مخفی و هنگام اسکرول به بالا نمایش میدهد، با استفاده از requestAnimationFrame برای حفظ عملکرد روان و جلوگیری از فراخوانیهای مکرر رویداد اسکرول. برای انیمیشن از transform استفاده شده که توسط مرورگرها بهینهتر و GPU-accelerated است، در مقابل استفاده از تغییر موقعیت با top که پرهزینهتر است.
نکات مهم عملکرد و دسترسی (Performance & Accessibility)
- انیمیشنها را با transform و opacity پیاده کنید؛ از تغییر خصیصههایی مثل width/height/top در انیمیشنهای مداوم خودداری کنید.
- از media query مربوط به
prefers-reduced-motionبرای احترام به کاربران با حساسیت به حرکت استفاده کنید:
@media (prefers-reduced-motion: reduce) {
.header, .header * {
transition: none !important;
animation: none !important;
}
}توضیح: این کد باعث میشود کاربران که حرکتهای زیاد را دوست ندارند یا نیاز به تجربهای با حرکت کمتر دارند، از انیمیشنها معاف شوند. این موضوع از منظر دسترسی (a11y) بسیار مهم است.
مقایسه سریع روشها
| روش | پیچیدگی | عملکرد | قابلیت کنترل |
|---|---|---|---|
| CSS-only (position: sticky) | پایین | عالی | پایین |
| CSS + JS (shrink/hide) | متوسط | خوب (با بهینهسازی) | بالا |
| انیمیشنهای پیچیده (پارالاکس) | بالا | متوسط تا پایین | بسیار بالا |
نکات تکمیلی و بهترین شیوهها
- کاهش بازپخشها: از repaint/relayoutهای مکرر خودداری کنید. تغییرات بر پایه
transformوopacityرا ترجیح دهید. - بارگذاری CSS در بالای صفحه (critical CSS) و JS غیرمسدود برای رفتارهای دینامیک.
- آزمایش در دستگاههای موبایل با شبکه و سختافزار ضعیف؛ عملکرد را با ابزارهایی مثل Lighthouse بررسی کنید.
- برای افکتهای بصری، از مقدار کم و رفتارهای طبیعی استفاده کنید تا مزاحم تجربه کاربر نشود.
جمعبندی و الگوهای پیشنهادی
برای اکثر وبسایتها، شروع با یک هدر sticky ساده (CSS-only) بهترین گزینه است. اگر نیاز به تجربه کاربری پیشرفتهتر دارید — مثل کوچکشدن یا مخفیشدن بر اساس جهت اسکرول — از JS به همراه requestAnimationFrame و انیمیشنهای مبتنی بر transform استفاده کنید. همواره دسترسی و عملکرد را در مرکز تصمیمگیری قرار دهید و از prefers-reduced-motion برای احترام به ترجیحات کاربران استفاده کنید.
در صورت نیاز میتوان نمونه کد ترکیبی کامل (Responsive + Accessible + Tiny JS) ارائه داد تا بهراحت در پروژهتان وارد شود.
آیا این مطلب برای شما مفید بود ؟




