چرا بعضی سایتها با وجود طراحی زیبا، مانند یک کتاب بسته روی قفسه باقی میمانند؟
کاربران معمولاً در چند ثانیه اول تصمیم میگیرند که در یک سایت بمانند یا آن را ترک کنند. رنگبندی مناسب، تصاویر باکیفیت و تایپوگرافی زیبا میتوانند توجه کاربر را جلب کنند؛ اما برای نگهداشتن او کافی نیستند. اگر سایت فقط ظاهر زیبایی داشته باشد و هیچ واکنشی به رفتار کاربر نشان ندهد، تجربهای ایستا و فراموششدنی ایجاد خواهد کرد.
اینجاست که جاوا اسکریپت وارد عمل میشود.
با استفاده از چند قطعه کد جاوا اسکریپت سبک و هوشمند میتوان منوی موبایل، اسکرول نرم، تشخیص بخش فعال، حالت تاریک و بسیاری از قابلیتهای تعاملی دیگر را بدون نصب کتابخانههای سنگین به سایت اضافه کرد.
در ۱۵ سال فعالیت مستقیم در زمینه طراحی و توسعه سایت، بارها دیدهام که همین جزئیات ظاهراً کوچک، تفاوت میان یک سایت معمولی و سایتی را رقم میزنند که کاربر را به کلیک، ثبتنام یا خرید ترغیب میکند.
در این مقاله، سه مورد از بهترین کدهای جاوا اسکریپت برای طراحی سایت را بررسی میکنیم. تمام کدها با JavaScript خالص یا Vanilla JavaScript نوشته شدهاند و برای اجرای آنها به React، jQuery یا کتابخانههای جانبی نیاز ندارید.
مشکل اصلی بسیاری از سایتهای زیبا
بسیاری از طراحان تمام تمرکز خود را روی ظاهر صفحه میگذارند:
- انتخاب رنگ مناسب
- استفاده از فونت زیبا
- طراحی بنرهای حرفهای
- افزودن تصاویر باکیفیت
- ساخت چیدمان منظم
اما پس از بارگذاری صفحه، کاربر با محیطی تقریباً ثابت مواجه میشود. منوها رفتار مناسبی در موبایل ندارند، تغییر بخشها مشخص نیست، تنظیمات ظاهری کاربر ذخیره نمیشود و عناصر صفحه هیچ بازخوردی ارائه نمیدهند.
این کمبود تعامل ممکن است پیامدهای زیر را به همراه داشته باشد:
- خروج سریع کاربران از صفحه
- کاهش زمان حضور در سایت
- پایین ماندن نرخ کلیک روی دکمهها
- کاهش نرخ تبدیل
- ایجاد تجربه ضعیف در موبایل
- عقب ماندن از رقبایی که تجربه کاربری بهتری ارائه میکنند
برای مثال، در یکی از پروژههای فروشگاهی، نرخ پرش صفحه اصلی پیش از بهینهسازی حدود ۶۸ درصد و میانگین زمان حضور کاربران کمتر از یک دقیقه بود. پس از اصلاح منوی موبایل، بهبود مسیر پیمایش و اضافه کردن تعاملات هدفمند، زمان حضور کاربران افزایش یافت و نرخ افزودن محصول به سبد خرید نیز بهتر شد.
البته چنین نتایجی برای همه سایتها یکسان نیست. تأثیر هر تغییر باید با ابزارهایی مانند Google Analytics، Microsoft Clarity یا Matomo اندازهگیری شود.

۱- منوی همبرگری ریسپانسیو و دسترسپذیر
منوی همبرگری یکی از مهمترین اجزای نسخه موبایل سایت است. اگر این منو بهدرستی طراحی نشود، کاربران نمیتوانند بهراحتی میان صفحات حرکت کنند.
یک منوی حرفهای باید:
- با کلیک باز و بسته شود
- با کلیک بیرون از منو بسته شود
- با کلید Escape بسته شود
- وضعیت باز یا بسته بودن را به صفحهخوان اعلام کند
- پس از انتخاب یک لینک در موبایل بسته شود
- در نمایشگرهای بزرگ به شکل منوی معمولی نمایش داده شود
کد HTML
<header class=”site-header”>
<a href=”/” class=”logo”>نام برند</a>
<button
id=”menuBtn”
class=”menu-btn”
type=”button”
aria-label=”باز کردن منوی اصلی”
aria-controls=”navMenu”
aria-expanded=”false”
>
<span aria-hidden=”true”>☰</span>
</button>
<nav id=”navMenu” class=”nav-menu” aria-label=”منوی اصلی”>
<a href=”#home”>خانه</a>
<a href=”#services”>خدمات</a>
<a href=”#portfolio”>نمونهکارها</a>
<a href=”#contact”>تماس با ما</a>
</nav>
</header>
کد JavaScript
const menuButton = document.getElementById(‘menuBtn’);
const navigationMenu = document.getElementById(‘navMenu’);
if (menuButton && navigationMenu) {
const setMenuState = (isOpen) => {
navigationMenu.classList.toggle(‘is-open’, isOpen);
menuButton.setAttribute(‘aria-expanded’, String(isOpen));
menuButton.setAttribute(
‘aria-label’,
isOpen ? ‘بستن منوی اصلی’ : ‘باز کردن منوی اصلی’
);
menuButton.querySelector(‘span’).textContent = isOpen ? ‘✕’ : ‘☰’;
};
menuButton.addEventListener(‘click’, () => {
const isOpen =
menuButton.getAttribute(‘aria-expanded’) === ‘true’;
setMenuState(!isOpen);
});
document.addEventListener(‘click’, (event) => {
const clickedInsideMenu = navigationMenu.contains(event.target);
const clickedMenuButton = menuButton.contains(event.target);
if (!clickedInsideMenu && !clickedMenuButton) {
setMenuState(false);
}
});
document.addEventListener(‘keydown’, (event) => {
if (event.key === ‘Escape’) {
setMenuState(false);
menuButton.focus();
}
});
navigationMenu.querySelectorAll(‘a’).forEach((link) => {
link.addEventListener(‘click’, () => {
setMenuState(false);
});
});
}
CSS کمکی
.site-header {
position: relative;
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px;
}
.menu-btn {
display: none;
cursor: pointer;
border: 0;
background: transparent;
font-size: 28px;
}
.nav-menu {
display: flex;
align-items: center;
gap: 24px;
}
@media (max-width: 768px) {
.menu-btn {
display: block;
}
.nav-menu {
position: absolute;
top: 100%;
right: 16px;
left: 16px;
z-index: 1000;
display: flex;
flex-direction: column;
align-items: stretch;
padding: 16px;
background: #ffffff;
border-radius: 12px;
box-shadow: 0 12px 30px rgb(0 0 0 / 12%);
opacity: 0;
visibility: hidden;
pointer-events: none;
transform: translateY(-10px);
transition:
opacity 0.25s ease,
transform 0.25s ease,
visibility 0.25s;
}
.nav-menu.is-open {
opacity: 1;
visibility: visible;
pointer-events: auto;
transform: translateY(0);
}
}
نکته حرفهای
فقط به تغییر آیکون همبرگری اکتفا نکنید. ویژگی aria-expanded برای کاربران صفحهخوان بسیار مهم است و مشخص میکند که منو در حال حاضر باز است یا بسته.
همچنین بهتر است در زمان باز بودن منو، اسکرول صفحه را در منوهای تمامصفحه غیرفعال کنید. برای این کار میتوانید یک کلاس مانند menu-open به عنصر body اضافه کنید.

۲- اسکرول نرم و تشخیص خودکار بخش فعال
در سایتهای تکصفحهای، لندینگ پیجها و صفحات معرفی خدمات، کاربران معمولاً با کلیک روی لینکهای منو به قسمتهای مختلف همان صفحه منتقل میشوند.
پرش ناگهانی به بخش مقصد تجربه چندان مطلوبی ایجاد نمیکند. همچنین اگر لینک مربوط به بخش فعلی برجسته شود، کاربر بهتر متوجه موقعیت خود در صفحه خواهد شد.
برای این کار به دو قابلیت نیاز داریم:
- اسکرول نرم به بخش مقصد
- تشخیص بخشی که در محدوده دید کاربر قرار دارد
کد HTML نمونه
<nav class=”page-nav”>
<a href=”#home”>خانه</a>
<a href=”#services”>خدمات</a>
<a href=”#about”>درباره ما</a>
<a href=”#contact”>تماس</a>
</nav>
<main>
<section id=”home”>…</section>
<section id=”services”>…</section>
<section id=”about”>…</section>
<section id=”contact”>…</section>
</main>
کد JavaScript
const navigationLinks = document.querySelectorAll(
‘.page-nav a[href^=”#”]’
);
const pageSections = document.querySelectorAll(
‘main section[id]’
);
const reduceMotion = window.matchMedia(
‘(prefers-reduced-motion: reduce)’
).matches;
// اسکرول نرم به بخش مقصد
navigationLinks.forEach((link) => {
link.addEventListener(‘click’, (event) => {
const selector = link.getAttribute(‘href’);
const targetSection = document.querySelector(selector);
if (!targetSection) return;
event.preventDefault();
targetSection.scrollIntoView({
behavior: reduceMotion ? ‘auto’ : ‘smooth’,
block: ‘start’
});
history.pushState(null, ”, selector);
});
});
// تشخیص بخش فعال
const sectionObserver = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (!entry.isIntersecting) return;
const activeSectionId = entry.target.id;
navigationLinks.forEach((link) => {
const isActive =
link.getAttribute(‘href’) === `#${activeSectionId}`;
link.classList.toggle(‘active’, isActive);
if (isActive) {
link.setAttribute(‘aria-current’, ‘location’);
} else {
link.removeAttribute(‘aria-current’);
}
});
});
},
{
rootMargin: ‘-30% 0px -60% 0px’,
threshold: 0
}
);
pageSections.forEach((section) => {
sectionObserver.observe(section);
});
CSS کمکی
html {
scroll-behavior: smooth;
}
section {
min-height: 100vh;
scroll-margin-top: 90px;
}
.page-nav a {
position: relative;
text-decoration: none;
}
.page-nav a.active {
font-weight: 700;
}
.page-nav a.active::after {
content: “”;
position: absolute;
right: 0;
bottom: -6px;
width: 100%;
height: 2px;
background: currentColor;
}
@media (prefers-reduced-motion: reduce) {
html {
scroll-behavior: auto;
}
}
چرا از Intersection Observer استفاده کردیم؟
روش قدیمی این بود که با هر بار اسکرول کاربر، موقعیت تمام بخشهای صفحه بررسی شود. اجرای مداوم کد در رویداد scroll، بهخصوص در صفحات طولانی، میتواند مصرف پردازنده را افزایش دهد.
IntersectionObserver فقط زمانی اجرا میشود که وضعیت مشاهده یک عنصر تغییر کند. به همین دلیل معمولاً سبکتر، تمیزتر و مناسبتر از بررسی مداوم موقعیت اسکرول است.
ویژگی scroll-margin-top نیز مانع از آن میشود که عنوان بخش مقصد زیر هدر ثابت سایت پنهان شود.

۳- دارک مود هوشمند با ذخیره انتخاب کاربر
حالت تاریک دیگر فقط یک قابلیت تزئینی نیست. بسیاری از کاربران به دلیل راحتی چشم، کاهش نور صفحه یا سلیقه شخصی، استفاده از رابط تاریک را ترجیح میدهند.
یک دارک مود حرفهای باید:
- تنظیم سیستمعامل کاربر را تشخیص دهد
- انتخاب دستی کاربر را ذخیره کند
- پس از بارگذاری مجدد صفحه حفظ شود
- وضعیت دکمه را برای صفحهخوان مشخص کند
- از چشمکزدن اولیه صفحه جلوگیری کند
کد HTML
<button
id=”themeToggle”
type=”button”
aria-label=”فعال کردن حالت تاریک”
aria-pressed=”false”
>
<span aria-hidden=”true”>🌙</span>
</button>
کد JavaScript
const themeToggle = document.getElementById(‘themeToggle’);
const rootElement = document.documentElement;
const systemTheme = window.matchMedia(
‘(prefers-color-scheme: dark)’
);
const savedTheme = localStorage.getItem(‘theme’);
const initialTheme =
savedTheme || (systemTheme.matches ? ‘dark’ : ‘light’);
const applyTheme = (theme) => {
const isDark = theme === ‘dark’;
rootElement.classList.toggle(‘dark’, isDark);
if (!themeToggle) return;
themeToggle.setAttribute(‘aria-pressed’, String(isDark));
themeToggle.setAttribute(
‘aria-label’,
isDark
? ‘فعال کردن حالت روشن’
: ‘فعال کردن حالت تاریک’
);
themeToggle.querySelector(‘span’).textContent =
isDark ? ‘☀️’ : ‘🌙’;
};
applyTheme(initialTheme);
themeToggle?.addEventListener(‘click’, () => {
const nextTheme = rootElement.classList.contains(‘dark’)
? ‘light’
: ‘dark’;
localStorage.setItem(‘theme’, nextTheme);
applyTheme(nextTheme);
});
CSS پیشنهادی با متغیرها
:root {
color-scheme: light;
–background-color: #ffffff;
–surface-color: #f5f7fa;
–text-color: #172033;
–border-color: #dfe3e8;
}
:root.dark {
color-scheme: dark;
–background-color: #10131a;
–surface-color: #1a1f2b;
–text-color: #f1f4f8;
–border-color: #303746;
}
body {
color: var(–text-color);
background: var(–background-color);
transition:
color 0.25s ease,
background-color 0.25s ease;
}
.card {
background: var(–surface-color);
border: 1px solid var(–border-color);
}
جلوگیری از چشمکزدن حالت روشن
اگر فایل جاوا اسکریپت در انتهای صفحه بارگذاری شود، ممکن است صفحه ابتدا روشن نمایش داده شود و سپس به حالت تاریک تغییر کند. برای جلوگیری از این مشکل، کد کوتاه تشخیص تم را در بخش <head> قرار دهید:
<script>
const savedTheme = localStorage.getItem(‘theme’);
const prefersDark = window.matchMedia(
‘(prefers-color-scheme: dark)’
).matches;
if (savedTheme === ‘dark’ || (!savedTheme && prefersDark)) {
document.documentElement.classList.add(‘dark’);
}
</script>
این اسکریپت باید پیش از بارگذاری فایلهای CSS اصلی اجرا شود.

هماهنگسازی با Tailwind CSS
در Tailwind میتوانید حالت تاریک را بر اساس کلاس فعال کنید و سپس از کلاسهای dark: استفاده کنید:
<div class=”bg-white text-gray-900 dark:bg-gray-900 dark:text-white”>
محتوای صفحه
</div>
در این حالت، همان کد جاوا اسکریپت با اضافه یا حذف کردن کلاس dark روی عنصر <html>، تم سایت را کنترل میکند.
بهینهسازی تصاویر بدون کد سنگین
برای لود تنبل تصاویر، در بسیاری از پروژههای جدید نیازی به نوشتن JavaScript جداگانه ندارید. مرورگرهای مدرن از ویژگی loading=”lazy” پشتیبانی میکنند:
<img
src=”product.webp”
alt=”تصویر محصول”
width=”800″
height=”600″
loading=”lazy”
decoding=”async”
>
ویژگیهای width و height را حتماً مشخص کنید تا پیش از بارگذاری تصویر، فضای آن رزرو شود. این کار از جابهجایی ناگهانی محتوای صفحه و افزایش شاخص CLS جلوگیری میکند.
تصویر اصلی بالای صفحه یا تصویر Hero را معمولاً Lazy Load نکنید؛ زیرا تأخیر در بارگذاری آن میتواند شاخص LCP را ضعیف کند.
بهترین روش ترکیب کدها در یک پروژه واقعی
تمام کدها را بدون نظم در یک تگ <script> بزرگ قرار ندهید. بهتر است هر قابلیت را در یک تابع مستقل بنویسید:
function initializeMobileMenu() {
// کد منوی موبایل
}
function initializeSectionNavigation() {
// کد اسکرول و تشخیص بخش فعال
}
function initializeThemeToggle() {
// کد دارک مود
}
document.addEventListener(‘DOMContentLoaded’, () => {
initializeMobileMenu();
initializeSectionNavigation();
initializeThemeToggle();
});
در پروژههای بزرگتر میتوانید هر قابلیت را در یک فایل جداگانه قرار دهید:
assets/
├── js/
│ ├── menu.js
│ ├── navigation.js
│ ├── theme.js
│ └── main.js
└── css/
└── style.css
این ساختار، عیبیابی و نگهداری پروژه را سادهتر میکند.

PDF بهترین کد های جاوا اسکریپت برای طراحی سایت
نکات مهم عملکرد و دسترسپذیری
- به ترجیح کاهش حرکت احترام بگذارید
برخی کاربران انیمیشنهای زیاد را آزاردهنده میدانند. تنظیم prefers-reduced-motion را در CSS و JavaScript بررسی کنید.
- از رویدادهای سنگین اسکرول خودداری کنید
برای تشخیص دیدهشدن عناصر از IntersectionObserver استفاده کنید. اگر مجبور به استفاده از رویداد scroll شدید، آن را با روشهایی مانند requestAnimationFrame، throttle یا debounce کنترل کنید.
- عناصر تعاملی را با button بسازید
برای باز کردن منو یا تغییر تم از <div> و <span> قابلکلیک استفاده نکنید. عنصر <button> بهصورت پیشفرض از کیبورد، فوکوس و بسیاری از امکانات دسترسپذیری پشتیبانی میکند.
- جاوا اسکریپت را با defer بارگذاری کنید
<script src=”/assets/js/main.js” defer></script>
ویژگی defer اجازه میدهد فایل جاوا اسکریپت همزمان با پردازش HTML دانلود شود، اما پس از آماده شدن ساختار صفحه اجرا شود.
کد را فقط در صفحات موردنیاز اجرا کنید
پیش از افزودن Event Listener بررسی کنید که عنصر موردنظر واقعاً در صفحه وجود دارد. استفاده از شرطهایی مانند زیر از خطاهای غیرضروری جلوگیری میکند:
const element = document.querySelector(‘.example’);
if (element) {
// اجرای قابلیت
}
پنج نکته طلایی برای پیادهسازی
۱. ابتدا کد را در یک محیط آزمایشی اجرا کنید، نه مستقیماً روی سایت اصلی.
۲. قابلیتها را بهصورت ماژولار و مستقل بنویسید تا تغییر یک بخش باعث خراب شدن قسمتهای دیگر نشود.
۳. طراحی را ابتدا روی موبایل بررسی کنید؛ زیرا منو، اندازه دکمهها و فاصله عناصر در نمایشگرهای کوچک اهمیت بیشتری دارند.
۴. عملکرد سایت را پیش و پس از تغییر اندازهگیری کنید. بدون اندازهگیری نمیتوان فهمید یک قابلیت واقعاً مفید بوده است یا خیر.
۵. تمام تغییرات را با Git نسخهبندی کنید تا در صورت بروز مشکل بتوانید به نسخه قبلی بازگردید.

سؤالات متداول
1-آیا این کدها در وردپرس و المنتور کار میکنند؟
بله. کدهای HTML را میتوان در ویجت HTML المنتور، CSS را در بخش Custom CSS و JavaScript را در قابلیت Custom Code یا فایل قالب فرزند قرار داد.
بهتر است کد جاوا اسکریپت را مستقیماً داخل محتوای هر صفحه تکرار نکنید. قرار دادن آن در فایل جداگانه یا بخش مدیریت کدهای سفارشی، نگهداری سایت را سادهتر میکند.
2-آیا این کدها سرعت سایت را کاهش میدهند؟
این کدها سبک هستند و وابستگی خارجی ندارند. بااینحال، هر کد جاوا اسکریپت میتواند در صورت پیادهسازی نادرست روی عملکرد سایت تأثیر بگذارد. کد را فقط در صفحات موردنیاز اجرا کنید و نتیجه را با ابزارهای سنجش عملکرد بررسی کنید.
3-آیا برای اجرای این قابلیتها به React نیاز داریم؟
خیر. برای سایتهای شرکتی، شخصی، فروشگاهی معمولی و بسیاری از لندینگ پیجها، Vanilla JavaScript کافی است. استفاده از React زمانی منطقی است که رابط کاربری پیچیده، دادههای پویا و مدیریت وضعیت گسترده داشته باشید.
4-آیا میتوان این کدها را در سایتهای چندزبانه استفاده کرد؟
بله. فقط متن ویژگیهایی مانند aria-label و نوشته دکمهها را متناسب با زبان صفحه تغییر دهید. منطق اصلی کد به زبان محتوا وابسته نیست.
5-چگونه تأثیر این تغییرات را اندازهگیری کنیم؟
میتوانید شاخصهای زیر را قبل و بعد از اجرای تغییرات مقایسه کنید:
- نرخ پرش
- میانگین زمان حضور
- عمق اسکرول
- تعداد کلیک روی لینکهای منو
- نرخ تکمیل فرم
- نرخ افزودن محصول به سبد خرید
- نرخ تبدیل نهایی
فقط یک قابلیت را در هر مرحله تغییر دهید تا مشخص باشد بهبود یا افت نتیجه مربوط به کدام تغییر بوده است.
جمعبندی
برای ساخت یک سایت مدرن همیشه به فریمورکها و کتابخانههای پیچیده نیاز ندارید. گاهی سه قطعه کد ساده و اصولی میتوانند تجربه کاربری سایت را به شکل محسوسی بهتر کنند:
- منوی ریسپانسیو و دسترسپذیر، پیمایش موبایل را سادهتر میکند.
- اسکرول نرم و تشخیص بخش فعال، مسیر حرکت کاربر را واضحتر نشان میدهد.
- دارک مود هوشمند، امکان شخصیسازی تجربه کاربری را فراهم میکند.
نکته مهم این است که هیچ قابلیتی را فقط به دلیل جذاب بودن به سایت اضافه نکنید. ابتدا نیاز کاربر را شناسایی کنید، قابلیت مناسب را اجرا کنید و سپس نتیجه را با دادههای واقعی بسنجید.










