در این فصل چه میسازی#
تا حالا صفحههایی ساختی که فقط چیزی نشان میدهند: متن، تصویر، فهرست. این فصل اولین باری است که صفحهات از کاربر چیزی میگیرد: یک صفحهٔ عضویت که در آن اسمت را تایپ میکنی، ایمیل و رمز مینویسی، یکی از چند گزینه را انتخاب میکنی، یک تیک میزنی، در یک کادر بزرگتر برای خودت مینویسی، از یک فهرست بازشو یکی را برمیداری، و آخرش یک دکمه هست.

یک نکتهٔ مهم از همین اول: در این فصل فرم را میسازیم، نه اینکه بفرستیم. فعلاً فقط شکل فرم را میسازیم؛ فرستادن اطلاعات کار بعدهاست و به یک دنیای دیگر (سمت سرور) مربوط است. پس تمام تمرکزمان روی این است که فرم چه شکلی دارد و کاربر با آن چه کارهایی میتواند بکند.
آخر این فصل میتوانی:
- بگویی
<form>چیست و چرا همهٔ ورودیها داخلش میروند - برای هر نوع ورودی،
<input>را باtypeدرست انتخاب کنی - هر ورودی را با یک
<label>جفت کنی و بگویی چرا این جفتشدن اجباری است - بین
checkboxوradioدرست انتخاب کنی - یک
<textarea>، یک<select>و یک<button>بسازی
قبل از شروع#
- از فصل ۱: اسکلت کامل یک صفحه (
<!DOCTYPE html>تا<body>). - از فصل ۲: تیتر و پاراگراف — برای مرتبکردن فرم از
<p>استفاده میکنیم. - از فصل ۵: فهرست — فقط برای اینکه
<select>را با آن مقایسه کنیم.
فقط یک مرورگر لازم است. مثل همیشه، همهچیز را در آزمایشگاه میسازی و همانجا میبینی.
۱. <form>: ظرفِ همهٔ ورودیها#
هر جا از کاربر چیزی میگیری، همهاش داخل یک <form> میرود. <form> خودش چیزی نشان نمیدهد؛ فقط یک ظرف است که میگوید «این تکه از صفحه یک فرم است و این ورودیها به هم مربوطاند». وقتی روزی بخواهی فرم را واقعاً بفرستی، همین <form> است که میداند چه چیزهایی را با هم بفرستد.
کوچکترین ورودی ممکن یک کادر متن است. بیا یک کادر برای گرفتن اسم بسازیم. در آزمایشگاه این را بنویس:
<form>
<label for="name">نام تو</label>
<input type="text" id="name" name="name">
</form>
خط به خط:
<input>همان کادری است که کاربر داخلش تایپ میکند. دقت کن<input>تگ بسته ندارد — تنهاست، مثل<img>در فصل ۴.type="text"میگوید این یک کادر متنِ یکخطی است.id="name"یک اسم یکتا به این کادر میدهد. (یکتا یعنی در کل صفحه فقط یکیid="name"داشته باشد.)name="name"اسمی است که موقع فرستادن به این ورودی میدهیم. چون فعلاً نمیفرستیم زیاد مهم نیست — ولی جلوتر برایradioنقش کلیدی پیدا میکند.<label>متنی است که به کاربر میگوید این کادر برای چیست.for="name"این برچسب را به کادری وصل میکند کهidاشnameاست.
✅ چک کن: باید یک خط متن و کنارش یک کادر ببینی که میتوانی داخلش کلیک کنی و تایپ کنی.
حالا مهمترین کار این فصل: بهجای کلیک داخل کادر، روی خودِ کلمهٔ «نام تو» کلیک کن. میبینی که نشانگر (cursor) میپرد داخل کادر و آماده تایپ میشود. این همان پیوند for و id است که کار میکند.
این دقیقاً دلیل وجود <label> است، و دو فایده دارد:
- هدف کلیک بزرگتر: کاربر لازم نیست دقیقاً داخل کادرِ کوچک را بزند؛ کلیک روی متن هم کافی است. برای
checkboxوradioکه کادرشان ریز است، این خیلی مهم میشود. - screen reader: کسی که صفحه را نمیبیند و با screen reader کار میکند، وقتی به کادر میرسد باید بشنود «نام تو». بدون
<label>فقط میشنود «کادر متن» و نمیداند چه باید بنویسد.
💡 نکته:
forوidباید دقیقاً مثل هم باشند — حتی یک حرف یا یک نقطه فرق کند، پیوند برقرار نمیشود. و هرidدر صفحه باید یکتا باشد.
۲. type قلبِ <input> است#
یک <input> داریم، ولی همان یک تگ میتواند دهها کادرِ مختلف بسازد — فقط type را عوض میکنی. بیا سه type پرکاربرد دیگر را ببینیم: email، password و number. زیر کادر اسم، اینها را اضافه کن:
<label for="email">ایمیل</label>
<input type="email" id="email" name="email">
<label for="password">رمز عبور</label>
<input type="password" id="password" name="password">
<label for="age">سن</label>
<input type="number" id="age" name="age">
هر کدام کمی فرق دارند و فرقشان را میتوانی ببینی:
password: داخلش تایپ کن. بهجای حروف، نقطه یا ستاره میبینی. مرورگر رمز را از چشمِ کسی که کنارت نشسته پنهان میکند.number: خیلی از مرورگرها کنارش دو فلش کوچک بالا/پایین میگذارند و اجازه نمیدهند حرف تایپ کنی — فقط عدد.email: روی کامپیوتر شبیه کادر متن معمولی است، ولی روی موبایل صفحهکلیدی باز میشود که علامت@رویش راحت در دسترس است. به مرورگر گفتهای «اینجا قرار است ایمیل بیاید».
✅ چک کن: در کادر password تایپ کن و نقطهها را ببین؛ در کادر number سعی کن حرف تایپ کنی و ببین که قبول نمیکند.
انتخاب type درست فقط ظاهر را عوض نمیکند؛ به مرورگر و به کاربر میگوید چهجور دادهای اینجا انتظار میرود. همان فلسفهٔ همیشگی: HTML میگوید چیزی چه هست.
🤖 با AI: از دستیار AI ات بپرس «برای گرفتن شمارهٔ تلفن و برای گرفتن تاریخ تولد، چه
typeای برای<input>مناسب است؟». احتمالاً چندtypeنام میبرد که ما هنوز رسمی معرفیشان نکردهایم. همینجا قانون همیشگی را تمرین کن: هر کدام را در آزمایشگاه بنویس و ببین مرورگر چطور رفتار میکند — صفحهکلید موبایل عوض میشود؟ فقط عدد قبول میکند؟ اگر چیزی که با چشم دیدی با حرف AI نخواند، چیزی که دیدی معتبرتر است. اول خودت امتحان کن، بعد AI؛ و یادت باشد AI هم اشتباه میکند.
۳. یکی از چند تا با radio، چند تا از چند تا با checkbox#
گاهی میخواهی کاربر از بین چند گزینه فقط یکی را انتخاب کند. برای این کار radio است. جادویش در name است: همهٔ radio هایی که name یکسان دارند یک گروهاند، و از یک گروه فقط یکی میتواند انتخاب شود.
بیا از کاربر بپرسیم سطح تجربهاش چیست:
<p>سطح تجربهات چیست؟</p>
<p>
<input type="radio" id="level-beginner" name="level" value="beginner">
<label for="level-beginner">تازهکارم</label>
</p>
<p>
<input type="radio" id="level-pro" name="level" value="pro">
<label for="level-pro">حرفهایام</label>
</p>
دو نکته: اولاً برای radio (و checkbox) برچسب را معمولاً بعد از کادر میگذاریم، چون کادر ریز است و متن کنارش میآید — ولی پیوند for و id همچنان همان است. دوماً value مقدار درونی هر گزینه است که موقع فرستادن به کار میآید؛ چون فعلاً نمیفرستیم، فقط بگذار باشد.
✅ چک کن: روی «تازهکارم» کلیک کن، بعد روی «حرفهایام». میبینی اولی خودش خالی میشود — هر لحظه فقط یکی انتخاب است. تو یک خط کد برای این رفتار ننوشتی؛ همان name="level" مشترک این کار را کرد.
⚠️ مواظب باش: اگر به این دو
radioاسمهایnameمتفاوت بدهی، مرورگر فکر میکند دو گروهِ جدا هستند و آنوقت هر دو میتوانند همزمان انتخاب شوند — که برای «فقط یکی را انتخاب کن» غلط است. قانون را نگه دار:nameیکسان یعنی یک انتخاب.
حالا حالتِ دیگر: وقتی کاربر میتواند چند تا را با هم انتخاب کند و هر کدام مستقل است. این checkbox است:
<p>
<input type="checkbox" id="newsletter" name="newsletter">
<label for="newsletter">خبرنامه برایم بیاید</label>
</p>
✅ چک کن: روی برچسب کلیک کن تا تیک بخورد، دوباره کلیک کن تا برداشته شود. checkbox مستقل است؛ روشن و خاموششدنش به هیچ چیز دیگری کار ندارد.

چالش: radio یا checkbox؟
اول خودت فکر کن یا امتحان کن — بعد اینجا را باز کن.
۴. <textarea> برای متن بلند، <select> برای فهرست بازشو#
<input type="text"> فقط یک خط جا دارد. برای یک پیام چندخطی — مثلاً «دربارهٔ خودت بنویس» — کادری میخواهی که چند خط بگیرد. این <textarea> است:
<label for="message">دربارهٔ خودت بنویس</label>
<textarea id="message" name="message"></textarea>
برخلاف <input>، این یکی تگ بسته دارد: </textarea>. هرچه بین تگ باز و بسته بگذاری، متنِ شروع کادر میشود؛ معمولاً خالی نگهش میداریم تا کادر خالی شروع شود.
✅ چک کن: یک کادر بزرگتر میبینی. داخلش تایپ کن و Enter بزن تا به خط بعد بروی — کاری که کادر متن یکخطی نمیتواند. اگر گوشهٔ کادر را بگیری و بکشی، میتوانی اندازهاش را عوض کنی.
⚠️ مواظب باش:
</textarea>را فراموش نکن. چون تگ بسته دارد، اگر جا بیندازی هرچه بعدش نوشتهای ممکن است داخل کادر بیفتد و صفحه بههم بریزد.
حالا <select>: یک فهرست بازشو که کاربر از داخلش یکی را برمیدارد. هر گزینه یک <option> است:
<label for="topic">موضوع مورد علاقه</label>
<select id="topic" name="topic">
<option value="html">HTML</option>
<option value="css">CSS</option>
<option value="js">JavaScript</option>
</select>
متنی که بین <option> و </option> مینویسی همان چیزی است که کاربر میبیند. value باز هم مقدار درونی است برای وقتِ فرستادن.
✅ چک کن: روی <select> کلیک کن؛ فهرست باز میشود. یکی را انتخاب کن؛ فهرست بسته میشود و انتخابت را نشان میدهد. <select> فقط یک انتخاب میگیرد و جای کمی میبرد.
💡 نکته:
<select>و گروهradioهر دو «یکی را انتخاب کن» هستند. برای چند گزینهٔ کم،radioروشنتر است چون همه همزمان جلوی چشماند. برای گزینههای زیاد (مثل فهرست کشورها)<select>مرتبتر است.
۵. <button> و کنار هم چیدنِ کل فرم#
هر فرم آخرش یک دکمه میخواهد تا کاربر بگوید «تمام شد». این <button> است، و type="submit" یعنی دکمهای که (بهطور معمول) فرم را میفرستد:
<button type="submit">عضو شو</button>
متنِ بین تگ باز و بسته، همان چیزی است که روی دکمه نوشته میشود.
حالا همهچیز را کنار هم بگذار. من هر ورودی را داخل یک <p> گذاشتهام تا هر کدام سرِ خط خودش بیفتد و شلوغ نشود. این فرمِ کامل است:
<!-- index.html -->
<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
<meta charset="UTF-8">
<title>فرم عضویت</title>
</head>
<body>
<h1>عضویت در باشگاه کدنویسی</h1>
<form>
<p>
<label for="name">نام تو</label>
<input type="text" id="name" name="name">
</p>
<p>
<label for="email">ایمیل</label>
<input type="email" id="email" name="email">
</p>
<p>
<label for="age">سن</label>
<input type="number" id="age" name="age">
</p>
<p>
<label for="password">رمز عبور</label>
<input type="password" id="password" name="password">
</p>
<p>سطح تجربهات چیست؟</p>
<p>
<input type="radio" id="level-beginner" name="level" value="beginner">
<label for="level-beginner">تازهکارم</label>
</p>
<p>
<input type="radio" id="level-pro" name="level" value="pro">
<label for="level-pro">حرفهایام</label>
</p>
<p>
<label for="topic">موضوع مورد علاقه</label>
<select id="topic" name="topic">
<option value="html">HTML</option>
<option value="css">CSS</option>
<option value="js">JavaScript</option>
</select>
</p>
<p>
<label for="message">دربارهٔ خودت بنویس</label>
<textarea id="message" name="message"></textarea>
</p>
<p>
<input type="checkbox" id="newsletter" name="newsletter">
<label for="newsletter">خبرنامه برایم بیاید</label>
</p>
<p>
<button type="submit">عضو شو</button>
</p>
</form>
</body>
</html>
✅ چک کن: کل فرم را میبینی — کادرهای اسم و ایمیل و سن و رمز، یک گروه «یکی را انتخاب کن»، یک فهرست بازشو، یک کادر بزرگ پیام، یک checkbox و یک دکمه. روی کلمهٔ هر برچسب کلیک کن و ببین نشانگر توی همان کادرِ درست میپرد. دکمه را هم بزن — هیچ اتفاقی نمیافتد، و این درست است: فعلاً فقط شکل فرم را میسازیم؛ فرستادن اطلاعات کار بعدهاست.
۶. حالا عمداً خرابش کن: پیوند <label> را بشکن#
مهمترین پیوند این فصل، پیوندِ for و id است. برای اینکه واقعاً حسش کنی، بیا بشکنیمش. در همان کادر اسم، for="name" را عوض کن به for="fullname" — حالا دیگر با id="name" جور نیست:
<label for="fullname">نام تو</label>
<input type="text" id="name" name="name">
حالا روی کلمهٔ «نام تو» کلیک کن. قبلاً نشانگر میپرید داخل کادر؛ الان هیچ اتفاقی نمیافتد. برچسب تبدیل شده به یک متنِ ساده که به هیچ کادری وصل نیست. کادر هنوز کار میکند اگر مستقیم داخلش کلیک کنی — ولی پیوند رفته، و کاربرِ screen reader که کاملاً به همین پیوند تکیه دارد، دیگر نمیداند این کادر برای چیست.
باز هم دقت کن: مرورگر خطا نداد. درست مثل فصلهای قبل، فقط بیسروصدا کار نکرد. این همان رفتار موذی HTML است.
حالا درستش کن: for را برگردان به name تا دوباره با id یکی شود. روی کلمه کلیک کن و ببین نشانگر دوباره داخل کادر میپرد.
✅ چک کن: بعد از اصلاح، کلیک روی کلمهٔ برچسب دوباره کادر را فعال میکند. هر <input> در فرمت باید دقیقاً همین جفتِ سالم را داشته باشد.
💡 نکته: قانونِ کلِ این فصل در یک جمله: هر ورودی یک
<label>میخواهد،forباید دقیقاً برابرidباشد، و هرidیکتا. اگر این را رعایت کنی، نصفِ کارِ دسترسپذیریِ فرم را همینجا انجام دادهای.
واژههای تازهٔ این فصل#
| کلمه | تلفظ به حروف فارسی | یعنی چه |
|---|---|---|
| form | فُرم | ظرفی که همهٔ ورودیهای بههممربوط داخلش میروند (<form>) |
| input | اینپوت | کادری که کاربر داخلش چیزی وارد میکند (<input>) |
| type | تایپ | attribute ای که میگوید <input> چهجور کادری باشد |
| label | لِیبل | متنی که میگوید یک ورودی برای چیست (<label>) |
| radio | رِیدیو | دکمهٔ «فقط یکی از چند تا»؛ با name مشترک یک گروه میشود |
| checkbox | چِکباکس | تیکِ مستقلِ روشن/خاموش |
| textarea | تِکستاِریا | کادر متنِ چندخطی (<textarea>) |
| select | سِلِکت | فهرست بازشو برای انتخاب یکی (<select>) |
| option | آپشِن | یک گزینه داخل <select> (<option>) |
| button | باتِن | دکمه (<button>) |
تمرینها
اول خودت فکر کن یا امتحان کن — بعد اینجا را باز کن.
در فصل بعد#
الان میتوانی از کاربر ورودی بگیری — و بدون اینکه اسمش را برده باشیم، بخش بزرگی از دسترسپذیری را هم رعایت کردهای: همان عادتِ <label> برای هر <input>. فصل بعد دقیقاً دربارهٔ همین است: دسترسپذیری از خودِ HTML — ترتیب درست heading ها، landmark ها، پیمایش کل صفحه فقط با کلید Tab، و اینکه alt درست کِی لازم است و کِی باید خالی بماند. آنجا میبینی که چقدر از این کار را همین semantic HTML برایت انجام داده.
به آخر این فصل رسیدی!
اگر ساختی و جواب داد، این دکمه مال توست.