رفتن به محتوای اصلی

قسمت ۱۶ – اعتبارسنجی فرم با HTML

  • سینا قربانیان
  • ۲۳ آبان ۱۴۰۵
  • ۱۰ دقیقه مطالعه
  • ۰ بازدید
آموزش اعتبارسنجی فرم html با required و pattern در دوره کدپرس
فهرست مطالب
  1. اعتبارسنجی فرم html چیست و چطور کار می‌کند؟
  2. required در html چه کاری می‌کند؟
  3. pattern در input چطور کار می‌کند؟
  4. الگوی شماره موبایل ایرانی با پشتیبانی از ارقام فارسی
  5. min، max، step و minlength، maxlength چه تفاوتی دارند؟
  6. autocomplete و inputmode چه کمکی به فرم می‌کنند؟
  7. چطور فیلدهای نامعتبر را با CSS نمایش دهیم؟
  8. novalidate و formnovalidate چه زمانی استفاده می‌شوند؟
  9. مرجع اتریبیوت‌های اعتبارسنجی فرم html
  10. مثال کامل: فرم رزرو نوبت با اعتبارسنجی HTML
  11. از تجربه تیم siloow
  12. محدودیت‌ها؛ چرا اعتبارسنجی HTML کافی نیست؟
  13. اشتباهات رایج
  14. تمرین این قسمت
  15. خلاصه
  16. منابع
  17. سوالات متداول درباره اعتبارسنجی فرم html
  18. آیا با اعتبارسنجی HTML دیگر به اعتبارسنجی سمت سرور نیازی نیست؟
  19. چرا pattern من روی فیلد خالی خطا نمی‌دهد؟
  20. الگوی درست شماره موبایل ایران در HTML چیست؟
  21. تفاوت inputmode و type در input چیست؟
  22. چطور پیام خطای فارسی سفارشی نشان دهیم؟

اعتبارسنجی فرم HTML یعنی بررسی خودکار درستی داده‌های فرم توسط خود مرورگر و پیش از ارسال، فقط با اتریبیوت‌هایی مثل required، pattern، min، max، minlength و type؛ بدون حتی یک خط جاوااسکریپت. اگر داده نامعتبر باشد، مرورگر ارسال را متوقف می‌کند و پیام خطا نشان می‌دهد.

در این قسمت یاد می‌گیرید هر اتریبیوت اعتبارسنجی دقیقاً چه کاری می‌کند، چطور الگوی شماره موبایل و کد پستی ایرانی بنویسید، autocomplete و inputmode چطور پر کردن فرم را در موبایل سریع‌تر می‌کنند و چرا اعتبارسنجی HTML جایگزین اعتبارسنجی سمت سرور نیست.

نویسنده: تیم siloow (سیلو سولوشن) — آخرین به‌روزرسانی: آبان ۱۴۰۵

این قسمت ادامه مستقیم سه قسمت قبل است: فرم در HTML و تگ‌های form و label، انواع input در HTML و select، textarea، button و fieldset.

اعتبارسنجی فرم html چیست و چطور کار می‌کند؟

اعتبارسنجی فرم HTML که در مستندات به آن Constraint Validation می‌گویند، مجموعه‌ای از قیدهاست که روی هر فیلد تعریف می‌کنید و مرورگر هنگام ارسال فرم آن‌ها را بررسی می‌کند. اگر حتی یک فیلد قید خود را نقض کند، رویداد ارسال انجام نمی‌شود، روی اولین فیلد نامعتبر فوکوس می‌رود و پیام خطای بومی مرورگر به زبان سیستم کاربر نمایش داده می‌شود.

ساده‌ترین مثال، یک فرم ثبت‌نام با ایمیل و رمز عبور است:

<form action="/signup" method="post">
<label for="email">ایمیل</label>
<input type="email" id="email" name="email" required>

<label for="pass">رمز عبور (حداقل ۸ کاراکتر)</label>
<input type="password" id="pass" name="pass"
minlength="8" required autocomplete="new-password">

<button type="submit">ساخت حساب</button>
</form>

در این کد، type="email" خودش یک قید است: مقدار باید ساختار ایمیل داشته باشد. required خالی بودن را ممنوع می‌کند و minlength="8" حداقل طول را تعیین می‌کند.

فهرست اتریبیوت‌های اعتبارسنجی فرم html شامل required، pattern، min، max و minlength
قیدهای اصلی اعتبارسنجی

required در html چه کاری می‌کند؟

اتریبیوت required در HTML یک اتریبیوت بولین است که پر کردن فیلد را اجباری می‌کند؛ فرم تا وقتی آن فیلد خالی باشد ارسال نمی‌شود. required روی <input> (به‌جز انواعی مثل hidden، range و color)، <select> و <textarea> کار می‌کند.

  • برای checkbox، required یعنی تیک باید زده شود؛ مناسب «قوانین را می‌پذیرم».
  • برای گروه radio با name یکسان، کافی است required روی یکی از آن‌ها باشد تا انتخاب یکی از گزینه‌ها اجباری شود.
  • برای select، گزینه راهنمای اول با value="" انتخاب معتبر حساب نمی‌شود.

چون نوشتن required="false" هم فیلد را اجباری می‌کند (حضور اتریبیوت بولین مهم است، نه مقدارش)، برای اختیاری کردن فیلد باید اتریبیوت را کامل حذف کنید. بهتر است در متن label هم مشخص کنید کدام فیلدها اجباری‌اند؛ مثلاً با کلمه «(الزامی)» یا علامت ستاره همراه توضیح.

pattern در input چطور کار می‌کند؟

اتریبیوت pattern در input یک عبارت باقاعده (Regular Expression) است که کل مقدار فیلد باید با آن منطبق باشد؛ مرورگر به‌طور خودکار ابتدای و انتهای الگو را قفل می‌کند، پس نیازی به ^ و $ نیست. طبق مستندات MDN درباره pattern، این اتریبیوت فقط روی انواع text، tel، email، url، password و search اعمال می‌شود و فیلد خالی را نامعتبر نمی‌داند؛ برای اجباری کردن، required را هم اضافه کنید.

الگوی شماره موبایل ایرانی با پشتیبانی از ارقام فارسی

بسیاری از کاربران ایرانی با کیبورد فارسی تایپ می‌کنند و شماره را با ارقام ۰ تا ۹ فارسی وارد می‌کنند. الگوی [0-9] این ارقام را قبول نمی‌کند و کاربر بدون اینکه دلیلش را بفهمد خطا می‌گیرد. الگوی زیر هر دو نوع رقم را می‌پذیرد:

<label for="mobile">شماره موبایل</label>
<input type="tel" id="mobile" name="mobile"
pattern="(09|۰۹)[0-9۰-۹]{9}"
inputmode="tel" autocomplete="tel"
aria-describedby="mobile-hint" required>
<p id="mobile-hint">۱۱ رقم و با ۰۹ شروع شود؛ مثل 09121234567</p>

یادتان باشد در سمت سرور، ارقام فارسی را به لاتین تبدیل کنید و بعد ذخیره کنید. برای کد پستی ده‌رقمی هم الگوی ساده‌ای کافی است:

<label for="postal">کد پستی</label>
<input id="postal" name="postal"
pattern="[0-9]{10}" inputmode="numeric"
autocomplete="postal-code"
aria-describedby="postal-hint">
<p id="postal-hint">۱۰ رقم بدون خط تیره</p>

نکته: مرورگرها الگو را با پرچم v (حالت یونیکد) کامپایل می‌کنند؛ پس کاراکترهایی مثل (، )، [، {، /، - و | اگر منظورتان خود کاراکتر است، باید با بک‌اسلش گریز داده شوند. الگوی نامعتبر بی‌صدا نادیده گرفته می‌شود و فیلد اصلاً اعتبارسنجی نمی‌شود.

توضیح قالب درست را همیشه به‌صورت متن قابل مشاهده کنار فیلد بنویسید و با aria-describedby به input وصل کنید. اتریبیوت title در بعضی مرورگرها در پیام خطا نمایش داده می‌شود، اما در موبایل و برای کاربران کیبورد دیده نمی‌شود و نباید تنها راهنما باشد.

min، max، step و minlength، maxlength چه تفاوتی دارند؟

اتریبیوت‌های min و max محدوده مقدار را برای فیلدهای عددی و تاریخی تعیین می‌کنند، در حالی که minlength و maxlength محدوده تعداد کاراکترها را برای فیلدهای متنی مشخص می‌کنند. step فاصله مجاز بین مقادیر را تعیین می‌کند؛ مثلاً step=”۱۰۰۰″ یعنی فقط مضرب‌های ۱۰۰۰ (از مبدأ min) معتبرند.

<label for="qty">تعداد (۱ تا ۱۰)</label>
<input type="number" id="qty" name="qty"
min="1" max="10" step="1" value="1">

<label for="price">مبلغ (مضرب ۱۰۰۰ تومان)</label>
<input type="number" id="price" name="price"
min="10000" step="1000">

<label for="visit">تاریخ مراجعه</label>
<input type="date" id="visit" name="visit"
min="2026-11-14" max="2026-12-31">

maxlength با بقیه کمی فرق دارد: مرورگر اجازه تایپ کاراکتر اضافه را نمی‌دهد، در حالی که بقیه قیدها فقط هنگام ارسال خطا می‌دهند. برای input تاریخ، مقدار min و max همیشه با فرمت YYYY-MM-DD میلادی نوشته می‌شود، حتی اگر تقویم سیستم کاربر شمسی باشد.

autocomplete و inputmode چه کمکی به فرم می‌کنند؟

autocomplete به مرورگر می‌گوید هر فیلد چه نوع داده‌ای است تا پر کردن خودکار درست انجام شود، و inputmode تعیین می‌کند گوشی کدام کیبورد مجازی را نشان دهد. هیچ‌کدام از این دو داده را اعتبارسنجی نمی‌کنند؛ اما با کم کردن تایپ، خطای ورودی را کاهش می‌دهند.

<label for="fullname">نام و نام خانوادگی</label>
<input id="fullname" name="fullname" autocomplete="name">

<label for="addr">نشانی</label>
<textarea id="addr" name="addr" autocomplete="street-address"></textarea>

<label for="otp">کد تأیید پیامکی</label>
<input id="otp" name="otp" inputmode="numeric"
autocomplete="one-time-code" pattern="[0-9]{5,6}">

مقدار one-time-code در گوشی‌های امروزی پیشنهاد پر کردن کد پیامکی را فعال می‌کند و new-password به مدیر رمز عبور اجازه می‌دهد رمز قوی پیشنهاد دهد. طبق MDN، اگر داده قالب خاصی دارد، اول type مناسب را انتخاب کنید و inputmode را فقط برای مواردی مثل کد پستی و کد تأیید که type مخصوص ندارند به کار ببرید.

مقدار inputmodeکیبورد نمایش‌داده‌شدهکاربرد فارسی
numericفقط ارقامکد پستی، کد ملی، کد تأیید
decimalارقام و جداکننده اعشاروزن، مقدار
telصفحه شماره‌گیر با * و #شماره تلفن
emailکیبورد با @ایمیل (معمولاً type=”email” کافی است)
searchدکمه Enter با عنوان جستجوکادر جستجوی سایت
مقادیر پرکاربرد inputmode برای فرم‌های فارسی

چطور فیلدهای نامعتبر را با CSS نمایش دهیم؟

شبه‌کلاس‌های :user-invalid و :user-valid فیلد را فقط بعد از اینکه کاربر با آن تعامل کرد یا فرم را ارسال کرد، نامعتبر یا معتبر علامت می‌زنند. شبه‌کلاس قدیمی‌تر :invalid از همان لحظه بارگذاری صفحه فعال است و فیلدهای required خالی را پیش از تایپ قرمز می‌کند که تجربه بدی است.

/* فقط بعد از تعامل کاربر قرمز شود */
input:user-invalid {
border-color: #c62828;
}
input:user-valid {
border-color: #2e7d32;
}

CSS را از قسمت ۲۳ به بعد کامل یاد می‌گیرید؛ فعلاً بدانید این شبه‌کلاس‌ها در همه مرورگرهای اصلی پشتیبانی می‌شوند و انتخاب بهتری از :invalid هستند. فقط به رنگ تکیه نکنید؛ متن خطا یا آیکن هم لازم است.

مقایسه شبه‌کلاس invalid و user-invalid در نمایش خطای فرم
invalid در برابر user-invalid

novalidate و formnovalidate چه زمانی استفاده می‌شوند؟

اتریبیوت novalidate روی تگ form کل اعتبارسنجی بومی را خاموش می‌کند و formnovalidate روی یک دکمه، فقط برای ارسال با همان دکمه اعتبارسنجی را غیرفعال می‌کند. کاربرد رایج novalidate، فرم‌هایی است که پیام‌های خطا را با جاوااسکریپت سفارشی نشان می‌دهند؛ کاربرد formnovalidate، دکمه «ذخیره پیش‌نویس» است.

<form action="/draft" method="post">
<label for="title">عنوان آگهی</label>
<input id="title" name="title" required minlength="10">

<!-- ارسال نهایی با اعتبارسنجی -->
<button type="submit">انتشار آگهی</button>

<!-- ذخیره پیش‌نویس بدون اعتبارسنجی -->
<button type="submit" formnovalidate formaction="/save-draft">
ذخیره پیش‌نویس
</button>
</form>

مرجع اتریبیوت‌های اعتبارسنجی فرم html

این جدول همه اتریبیوت‌های این قسمت را با نوع فیلدهای مجاز خلاصه می‌کند.

اتریبیوتکارروی کدام فیلدها
requiredاجباری کردن فیلداکثر inputها، select، textarea
patternتطبیق کل مقدار با Regextext، tel، email، url، password، search
min / maxکمینه و بیشینه مقدارnumber، range، date، time، month، week
stepگام مجاز مقدارnumber، range، date، time
minlength / maxlengthکمینه و بیشینه طول متنtext، email، tel، url، password، search، textarea
typeقید ساختاری (ایمیل، URL، عدد)input
autocompleteراهنمای پر کردن خودکارinput، select، textarea، form
inputmodeانتخاب کیبورد مجازیهر عنصر قابل ویرایش
novalidate / formnovalidateخاموش کردن اعتبارسنجیform / دکمه submit
جدول مرجع اتریبیوت‌های اعتبارسنجی فرم HTML

مثال کامل: فرم رزرو نوبت با اعتبارسنجی HTML

فرم رزرو زیر همه قیدهای این قسمت را در یک سند راست‌چین ترکیب می‌کند و بدون جاوااسکریپت از ارسال نام کوتاه، شماره اشتباه و تاریخ گذشته جلوگیری می‌کند.

<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>فرم رزرو نوبت</title>
</head>
<body>
<h1>رزرو نوبت مشاوره</h1>
<form action="/booking" method="post">
<label for="name">نام و نام خانوادگی</label>
<input id="name" name="name" required minlength="3"
autocomplete="name">

<label for="tel">شماره موبایل</label>
<input type="tel" id="tel" name="tel" required
pattern="(09|۰۹)[0-9۰-۹]{9}" inputmode="tel"
autocomplete="tel" aria-describedby="tel-hint">
<p id="tel-hint">مثال: 09121234567</p>

<label for="day">تاریخ</label>
<input type="date" id="day" name="day" required
min="2026-11-14">

<label for="note">توضیحات (اختیاری، حداکثر ۳۰۰ کاراکتر)</label>
<textarea id="note" name="note" maxlength="300"></textarea>

<button type="submit">ثبت نوبت</button>
</form>
</body>
</html>
نمونه کد اعتبارسنجی فرم html برای شماره موبایل ایرانی با pattern و inputmode
الگوی شماره موبایل با ارقام فارسی

از تجربه تیم siloow

در قالب کلینیکی siloow Medical که امکان نوبت‌دهی آنلاین دارد، مشکل رایج فرم‌ها، شماره موبایلی بود که با ارقام فارسی یا با فاصله وارد می‌شد. راه‌حل ما سه لایه بود: الگوی HTML که ارقام فارسی و لاتین را بپذیرد، تبدیل ارقام فارسی به لاتین در سمت سرور پیش از ذخیره، و یک متن راهنمای ثابت زیر فیلد. درس اصلی این بود که اعتبارسنجی سخت‌گیرانه‌ای که ورودی طبیعی کاربر فارسی‌زبان را رد کند، به‌جای کمک، فرم را رها‌شده می‌کند.

محدودیت‌ها؛ چرا اعتبارسنجی HTML کافی نیست؟

اعتبارسنجی HTML فقط برای تجربه کاربری است و امنیت ایجاد نمی‌کند. هر کسی می‌تواند با ابزار توسعه‌دهنده مرورگر اتریبیوت‌ها را حذف کند یا درخواست را مستقیم به سرور بفرستد. بنابراین همه داده‌ها باید در سمت سرور (مثلاً در PHP یا وردپرس) دوباره اعتبارسنجی و پاک‌سازی شوند.

  • پیام‌های خطای بومی به زبان سیستم‌عامل یا مرورگر نمایش داده می‌شوند و ظاهرشان قابل استایل نیست.
  • قیدهای وابسته به هم (مثل «تکرار رمز با رمز یکی باشد») بدون جاوااسکریپت ممکن نیست.
  • پیام‌های خطای بومی همیشه به‌خوبی توسط همه صفحه‌خوان‌ها اعلام نمی‌شوند؛ متن راهنمای قابل مشاهده ضروری است.

اشتباهات رایج

  1. نوشتن ^ و $ یا اسلش دور الگو در pattern؛ لازم نیست و اسلش حتی الگو را خراب می‌کند.
  2. الگوی [0-9] برای شماره موبایل بدون در نظر گرفتن ارقام فارسی.
  3. تکیه بر pattern بدون required و تعجب از اینکه فیلد خالی ارسال می‌شود.
  4. استفاده از type="number" برای کد ملی یا کد پستی؛ صفرهای ابتدایی و فلش‌های کم و زیاد مشکل‌سازند. از text با inputmode=”numeric” استفاده کنید.
  5. استایل‌دهی با :invalid که فیلدها را قبل از تایپ قرمز می‌کند.
  6. حذف اعتبارسنجی سمت سرور به این خیال که HTML کافی است.

تمرین این قسمت

  1. فیلد کد ملی ده‌رقمی با پشتیبانی از ارقام فارسی و لاتین بسازید.
  2. یک فرم ثبت‌نام با ایمیل، رمز عبور حداقل ۸ کاراکتری و checkbox اجباری پذیرش قوانین بنویسید.
  3. یک input تاریخ بسازید که فقط روزهای ماه آینده را بپذیرد.
  4. برای فرم سفارش یک دکمه «ذخیره پیش‌نویس» با formnovalidate اضافه کنید.
  5. همه فیلدهای فرم رزرو بالا را با autocomplete مناسب کامل کنید و در گوشی تست کنید.

خلاصه

  • اعتبارسنجی فرم html با اتریبیوت‌های required، pattern، min/max، minlength/maxlength و type بدون جاوااسکریپت کار می‌کند.
  • pattern کل مقدار را بررسی می‌کند، فیلد خالی را رد نمی‌کند و باید ارقام فارسی را هم در نظر بگیرد.
  • autocomplete و inputmode اعتبارسنجی نمی‌کنند اما خطای ورودی را کم می‌کنند.
  • برای نمایش خطا از :user-invalid استفاده کنید، نه :invalid.
  • اعتبارسنجی سمت سرور همیشه الزامی است.

در قسمت بعد، «قسمت ۱۷ – div و span؛ المان‌های بلاکی و اینلاین»، از فرم‌ها فاصله می‌گیریم و با ظرف‌های عمومی HTML آشنا می‌شویم. همه قسمت‌ها را در دوره رایگان آموزش HTML و CSS کدپرس دنبال کنید. فرم‌های رزرو و سفارش، قلب بسیاری از وب اپلیکیشن‌های کسب‌وکاری هستند؛ اگر چنین پروژه‌ای دارید، خدمات طراحی سایت siloow را ببینید.

منابع

سوالات متداول درباره اعتبارسنجی فرم html

آیا با اعتبارسنجی HTML دیگر به اعتبارسنجی سمت سرور نیازی نیست؟

خیر. اعتبارسنجی HTML فقط برای راحتی کاربر است و با ابزار توسعه‌دهنده یا ارسال مستقیم درخواست دور زده می‌شود. همه داده‌ها باید در سرور دوباره بررسی و پاک‌سازی شوند.

چرا pattern من روی فیلد خالی خطا نمی‌دهد؟

pattern فقط مقدار غیرخالی را بررسی می‌کند. اگر فیلد باید حتماً پر شود، اتریبیوت required را هم به آن اضافه کنید.

الگوی درست شماره موبایل ایران در HTML چیست؟

الگوی (۰۹|۰۹)[۰-۹۰-۹]{۹} شماره یازده‌رقمی که با ۰۹ شروع می‌شود را با ارقام فارسی و لاتین می‌پذیرد. در سرور ارقام فارسی را به لاتین تبدیل کنید.

تفاوت inputmode و type در input چیست؟

type نوع داده را تعیین و آن را اعتبارسنجی می‌کند، اما inputmode فقط کیبورد مجازی گوشی را انتخاب می‌کند و هیچ قیدی اعمال نمی‌کند.

چطور پیام خطای فارسی سفارشی نشان دهیم؟

پیام‌های بومی به زبان مرورگر هستند. برای پیام سفارشی باید از متد setCustomValidity در جاوااسکریپت یا novalidate و نمایش پیام دستی استفاده کنید.

اشتراک‌گذاری