এই পর্বে যা শিখবেন
- ফর্ম আসলে কী কাজ করে, আর জমা দিলে ব্রাউজার ভেতরে ভেতরে কী বানায়
actionআরmethod— GET বনাম POST, কোন তথ্য URL-এ যায় আর কোনটা যায় body-তেinput-এরname,value,type— text, email, password, number, tel- label-এর দুই নিয়ম (for/id আর মোড়ানো), placeholder-এর ফাঁদ, button-এর তিন type আর fieldset/legend
- autocomplete আর inputmode দিয়ে ফোনে দ্রুত পূরণ করা যায় এমন একটি পূর্ণ সাইন-আপ ফর্ম
১ · ফর্ম কী — ব্যাংকের কাগজের ফর্ম থেকে ওয়েবের ফর্ম
ব্যাংকে নতুন অ্যাকাউন্ট খুলতে গেলে আপনার হাতে একটি ছাপা কাগজ দেওয়া হয়। তাতে লেখা থাকে “নাম”, “পিতার নাম”, “মোবাইল নম্বর”, “ঠিকানা”। প্রতিটি লেখার পাশে একটি ফাঁকা ঘর। আপনি ঘরগুলো পূরণ করেন, তারপর কাগজটি কাউন্টারে জমা দেন। কাউন্টারের কর্মকর্তা সেটি ভেতরে পাঠিয়ে দেন। কলেজে ভর্তির ফর্মও তাই, পাসপোর্টের আবেদনও তাই।
ওয়েবের form ঠিক এই কাগজটি। এতে চারটি অংশ থাকে, আর প্রতিটির জন্য HTML-এ আলাদা element আছে:
| কাগজের ফর্মে | HTML-এ | কাজ |
|---|---|---|
| পুরো কাগজটি, ওপরে “কোথায় জমা দেবেন” | <form> | সব ঘরকে এক দলে রাখে, আর বলে তথ্য কোথায় যাবে |
| ফাঁকা ঘর | <input> | যেখানে ব্যবহারকারী লেখেন |
| ঘরের পাশে ছাপা “নাম” | <label> | ঘরটি কিসের, তা বলে |
| “জমা দিন” কাউন্টার | <button> | ফর্ম পাঠানোর নির্দেশ দেয় |
লেখা যায়, বেছে নেওয়া যায় বা চাপা যায় এমন প্রতিটি অংশকে বলে form control — যেমন input, button, পরে দেখবেন select আর textarea. এখন একটি বড় প্রশ্ন: আপনি “জমা দিন” চাপলে আসলে কী ঘটে? নিচের ডায়াগ্রামে “পরে” চাপুন:
- আপনি পূরণ করেন
নাম, মোবাইলঘরে লেখা - ব্রাউজার যাচাই করে
required? email?পর্ব ৯-এ বিস্তারিত - জোড়া বানায়
name=valuename থাকা ঘরগুলো - request পাঠায়
GET / POSTaction-এর ঠিকানায় - নতুন পাতা আসে
“ধন্যবাদ!”সার্ভারের উত্তর
- পূরণ। আপনি ঘরে লেখেন। এই পর্যায়ে সবকিছু শুধু আপনার ব্রাউজারের ভেতরে, কোথাও কিছু যায়নি। ঘরে যা লেখা আছে, তাকে বলে ঘরটির value বা মান।
- যাচাই। জমা দেওয়ার আগে ব্রাউজার নিজের নিয়মগুলো দেখে নেয় — ইমেইলের ঘরে “@” আছে কি না, বাধ্যতামূলক ঘর ফাঁকা কি না। ভুল থাকলে এখানেই থামে আর একটি বার্তা দেখায়। এই built-in যাচাই পুরোটা শিখবেন পর্ব ৯-এ।
- জোড়া বানানো। ব্রাউজার প্রতিটি ঘর থেকে একটি নাম=মান জোড়া বানায়: ঘরের
nameattribute হয় নাম, ভেতরের লেখা হয় মান — যেমনmobile=01712345678. যে ঘরেরnameনেই, সেটি বাদ পড়ে। - পাঠানো। জোড়াগুলো সাজিয়ে ব্রাউজার একটি HTTP request বানায় আর
<form>-এরaction-এ লেখা ঠিকানায় পাঠায়। কীভাবে সাজাবে — URL-এ না request-এর ভেতরে — সেটা ঠিক করেmethod. - উত্তর। সার্ভার তথ্য নিয়ে কাজ করে (ডেটাবেসে রাখে, SMS পাঠায়) আর একটি নতুন পাতা ফেরত দেয়। সার্ভারের দিকের প্রোগ্রাম লেখা এই কোর্সের অংশ নয় — আমাদের কাজ ধাপ ১ থেকে ৪, অর্থাৎ ফর্মটি সঠিকভাবে বানানো। (ব্রাউজার আর সার্ভারের কথোপকথন দেখেছেন পর্ব ০১-এ।)
HTML ফর্ম একটি চুক্তি: আপনি ঠিক করে দেন কোন ঘরের কী নাম, আর ব্রাউজার সেই নাম ধরে তথ্য গুছিয়ে পাঠায়। সার্ভারের প্রোগ্রাম ঠিক এই নামগুলোই খোঁজে। তাই HTML-এ name="mobile" লিখলে সার্ভারের কোডেও mobile খুঁজতে হবে — একটি অক্ষর এদিক-ওদিক হলে তথ্য “হারিয়ে” যায়।
এই পাতার প্রতিটি লাইভ এডিটরে ফর্ম জমা দিলে সত্যিই কোথাও কিছু যায় না। তার বদলে প্রিভিউর নিচে লেখা আসে ফর্ম জমা হতো → … — অর্থাৎ ব্রাউজার ঠিক কোন জোড়াগুলো পাঠাত। এটাই আপনার “এক্স-রে চোখ”।
২ · form, action আর method — তথ্য কোথায় আর কীভাবে যাবে
<form> element-এর দুটি প্রধান attribute:
action— তথ্য কোন ঠিকানায় যাবে, যেমনaction="/register". এটি একটি URL; না লিখলে ফর্ম যে পাতায় আছে, সেই পাতার ঠিকানাতেই যায়।method— কীভাবে যাবে:get(ডিফল্ট) অথবাpost. (তৃতীয় একটি মানdialogআছে, সেটি পর্ব ১১-এর<dialog>-এর সাথে কাজ করে।)
দুই রকমভাবে কাউকে চিঠি পাঠানোর কথা ভাবুন। GET যেন পোস্টকার্ড — বার্তাটা খামের বাইরে, ঠিকানার ঠিক পাশেই লেখা; ডাকপিয়ন থেকে শুরু করে যে-ই হাতে নেয়, সবাই পড়তে পারে। POST যেন খামে ভরা চিঠি — বাইরে শুধু ঠিকানা, বার্তা ভেতরে। (তবে খামটাও কাচের হতে পারে! খাম আসলে বন্ধ হয় HTTPS-এ — পর্ব ০১-এ দেখেছেন।)
সহজ নিয়ম: যে ফর্ম শুধু কিছু খোঁজে বা দেখতে চায় — সার্চ, পরীক্ষার ফল দেখা, পণ্য ফিল্টার — সেখানে GET. ফলের পাতাটি বুকমার্ক বা শেয়ার করা যায়, কারণ পুরো প্রশ্নটাই URL-এ থাকে। যে ফর্ম কিছু বদলায় বা গোপন তথ্য পাঠায় — অ্যাকাউন্ট খোলা, লগইন, অর্ডার, পেমেন্ট — সেখানে POST. পাসওয়ার্ড কখনো GET-এ পাঠাবেন না: URL থেকে যায় ব্রাউজারের history-তে, সার্ভারের log-এ, আর কারও স্ক্রিনশটে।
নিচের এডিটরে একটি সার্চ ফর্ম আছে। এর সাথে একটি ছোট <script> জুড়ে দিয়েছি, যেটি দেখায় ব্রাউজার ঠিক কোন URL বা body বানাত। “খুঁজুন” চাপুন:
<form action="/search" method="get">
<label for="q">কী খুঁজছেন?</label>
<input type="text" id="q" name="q" value="html ফর্ম">
<label for="lvl">লেভেল</label>
<input type="text" id="lvl" name="level" value="beginner">
<button type="submit">খুঁজুন</button>
</form>
<script>
document.querySelector('form').addEventListener('submit', (e) => {
const f = e.target;
const packed = new URLSearchParams(new FormData(f)).toString();
if (f.method === 'get') {
console.log('URL হতো → ' + f.getAttribute('action') + '?' + packed);
} else {
console.log('URL শুধু ' + f.getAttribute('action') + ', body-তে → ' + packed);
}
});
</script>দুটি লাইন আসবে। প্রথমটি আমাদের স্ক্রিপ্টের: URL হতো → /search?q=html+%E0%A6…&level=beginner. খেয়াল করুন — ফাঁকা জায়গা হয়ে গেছে +, আর “ফর্ম” শব্দটি হয়ে গেছে লম্বা একটি %E0%A6… সংকেত। দ্বিতীয় লাইনটি এডিটরের নিজের: ফর্ম জমা হতো → q=html ফর্ম&level=beginner — মূল জোড়াগুলো, সংকেত ছাড়া। চেষ্টা করুন: method="get"-কে method="post" করে আবার চাপুন — এবার URL-এ শুধু /search, তথ্য গেছে body-তে। তারপর দ্বিতীয় input থেকে name="level" মুছে দেখুন, “level” জোড়াটি পুরো উধাও।
GET-এ URL-এর ?-এর পরের অংশটিকে বলে query string — জোড়াগুলো সেখানে & দিয়ে জোড়া থাকে। আর বাংলা অক্ষর বা বিশেষ চিহ্ন URL-এ সরাসরি রাখা যায় না বলে ব্রাউজার সেগুলোকে percent-encoding-এ লেখে (পর্ব ০৫-এ দেখেছেন)। POST-এ একই জোড়া যায় request-এর body-তে — URL পরিষ্কার থাকে। একই তথ্য দুই পথে কীভাবে যায়, ধাপে ধাপে দেখুন:
<form action="/result" method="get"> <input name="roll" value="123456"> <input name="board" value="dhaka"> <input value="কিছু একটা"> ← name নেই <button type="submit">ফল দেখুন</button> </form>
roll = 123456 board = dhaka (name ছাড়া ঘরটি তালিকায় ঢোকেনি)
GET /result?roll=123456&board=dhaka HTTP/1.1 Host: example.com (body নেই)
POST /result HTTP/1.1 Host: example.com Content-Type: application/x-www-form-urlencoded roll=123456&board=dhaka
<input name="q" value="ফর্ম"> ↓ q=%E0%A6%AB%E0%A6%B0%E0%A7%8D%E0%A6%AE
- ফর্মটি। একটি পরীক্ষার ফল দেখার ফর্ম (ঠিকানা কাল্পনিক): দুটি ঘরে
nameআছে, তৃতীয়টিতে নেই। ফল দেখা মানে কিছু “খোঁজা”, কিছু বদলানো নয় — তাইmethod="get". - জোড়ার তালিকা। জমা দিলে ব্রাউজার HTML-এর ক্রম ধরে ঘরগুলো দেখে আর একটি তালিকা বানায় (স্পেসিফিকেশনে এর নাম entry list). name ছাড়া ঘরটি এখানেই বাদ — তার লেখা কখনো সার্ভারে পৌঁছায় না।
- GET. তালিকাটি
?-এর পরে URL-এ বসে, জোড়াগুলোর মাঝে&. ঠিকানার ঘরে পুরোটা দেখা যায় — এই লিংক কাউকে পাঠালে তিনিও সরাসরি একই ফল দেখবেন। এটাই GET-এর শক্তি। - POST. URL-এ শুধু
/result; জোড়াগুলো request-এর body-তে, আরContent-Typeheader জানায় কোন ধাঁচে সাজানো। Reload করলে ব্রাউজার জিজ্ঞেস করে “ফর্মটি আবার পাঠাবেন?” — কারণ POST কিছু বদলাতে পারে (যেমন দুবার অর্ডার)। - বাংলা অক্ষর। “ফর্ম” দেখতে চার অক্ষর (ফ, র, ্, ম), UTF-8-এ প্রতিটি ৩ বাইট — মোট ১২ বাইট, প্রতিটি বাইট
%আর দুই অঙ্কে। GET আর POST দুই পথেই এই সংকেত হয়; সার্ভার উল্টো হিসাব করে আবার “ফর্ম” ফিরে পায়।
POST মানেই নিরাপদ নয়। POST-এর তথ্য URL-এ দেখা যায় না ঠিকই, কিন্তু সাধারণ http:// সংযোগে পথের যেকোনো যন্ত্র body-ও পড়তে পারে। পাসওয়ার্ড বা ব্যক্তিগত তথ্য নিরাপদ হয় তখনই, যখন সাইটটি https://. আধুনিক ব্রাউজার HTTPS পাতার ফর্ম http:// ঠিকানায় পাঠাতে গেলে সতর্কবার্তা দেখায় বা আটকে দেয়।
৩ · input — name, value আর type
<input> একটি void element — এর কোনো closing tag নেই, ভেতরে কিছু লেখা হয় না। এর আচরণ পুরোটা আসে attribute থেকে। তিনটি সবচেয়ে জরুরি:
name— জোড়ার নাম, যা সার্ভারে যায়। ছোট, ইংরেজি, অর্থবহ রাখুন:fullname,mobile,email. এটি ব্যবহারকারী দেখেন না।value— ঘরের শুরুর মান। ব্যবহারকারী লিখলে আসল মান বদলে যায়, কিন্তু attribute-টি থেকে যায় “ডিফল্ট মান” হিসেবে (পরে reset বোতামে কাজে লাগবে)।type— ঘরটি কী ধরনের তথ্য নেবে। না লিখলেtext.
type শুধু চেহারা বদলায় না — ব্রাউজারকে ঘরটির অর্থ জানায়। ফোনে সবচেয়ে বড় পার্থক্য চোখে পড়ে: কোন ধরনের অন-স্ক্রিন কি-বোর্ড আসবে।
| type | কিসের জন্য | ব্রাউজার যা করে |
|---|---|---|
text | নাম, শহর — সাধারণ এক লাইনের লেখা | সাধারণ কি-বোর্ড |
email | ইমেইল ঠিকানা | ফোনে “@” আর “.” সহ কি-বোর্ড; জমার আগে ঠিকানার গঠন যাচাই |
password | পাসওয়ার্ড, পিন | লেখা বিন্দু (•••) দিয়ে ঢাকে; পাসওয়ার্ড ম্যানেজারকে জানায় |
number | পরিমাণ — বয়স, কয়টি পণ্য | সংখ্যার কি-বোর্ড, পাশে বাড়ানো-কমানোর তীর; বৈধ সংখ্যা না হলে মান বাতিল করে |
tel | ফোন নম্বর | ফোনে ডায়াল-প্যাডের মতো কি-বোর্ড; কোনো গঠন চাপিয়ে দেয় না |
<form>
<p><label>নাম: <input type="text" name="fullname" value="রাকিব হাসান"></label></p>
<p><label>ইমেইল: <input type="email" name="email" value="rakib@example.com"></label></p>
<p><label>পাসওয়ার্ড: <input type="password" name="pass" value="dhaka123"></label></p>
<p><label>বয়স: <input type="number" name="age" value="21"></label></p>
<p><label>মোবাইল: <input type="tel" name="mobile" value="01712345678"></label></p>
<p><label>রেফারেল কোড: <input type="text" value="BD2026"></label></p>
<button type="submit">জমা দিন</button>
</form>পাঁচটি ঘর দেখতে প্রায় এক; শুধু পাসওয়ার্ড বিন্দুতে ঢাকা আর বয়সের ঘরে তীর। “জমা দিন” চাপলে আসবে fullname=রাকিব হাসান&email=…&pass=dhaka123&age=21&mobile=01712345678 — দুটি জিনিস খেয়াল করুন: পাসওয়ার্ড পর্দায় ঢাকা থাকলেও পাঠানো হয় সাধারণ লেখায় (তাই HTTPS জরুরি), আর রেফারেল কোডটি নেই, কারণ তার name নেই। চেষ্টা করুন: রেফারেল ঘরে name="ref" যোগ করুন। তারপর ইমেইলের মান থেকে “@” মুছে আবার জমা দিন — ব্রাউজার নিজেই থামিয়ে একটি বার্তা দেখাবে (এই যাচাই পর্ব ৯-এ)।
এখানে প্রতিটি ঘর <label>-এর ভেতরে রাখা হয়েছে — কেন, সেটা পরের অংশের বিষয়। তার আগে আরও দুটি দরকারি কথা। এক, type-এ অচেনা কিছু লিখলে (যেমন ভুল বানানে type="emial") ব্রাউজার কোনো error দেখায় না, চুপচাপ text বানিয়ে দেয় — তাই বানান ভুল সহজে চোখে পড়ে না। দুই, email, password বা tel-এর মতো type-ও আসলে লেখা নেয়; শুধু ইঙ্গিত বদলায়। বাকি type — তারিখ, রং, ফাইল, checkbox, radio — পর্ব ৯-এ।
৪ · label — প্রতিটি ঘরের নাম, আর placeholder-এর ফাঁদ
কাগজের ফর্মে “মোবাইল নম্বর” লেখাটি ঘরের পাশে ছাপা থাকে বলে আপনি বোঝেন কোথায় কী লিখবেন। কিন্তু ওয়েবে শুধু পাশে লিখে দিলেই হয় না। সাধারণ লেখা আর ঘরের মধ্যে ব্রাউজারের কাছে কোনো সম্পর্ক নেই — যতক্ষণ না আপনি <label> দিয়ে জোড়া দেন। জোড়ার দুটি উপায়:
for আর id দিয়ে
<label for="mobile"> আর <input id="mobile"> — label-এর for-এর মান আর ঘরের id হুবহু এক। label আর ঘর পাতার যেকোনো জায়গায় থাকতে পারে।
label-এর ভেতরে মুড়ে
<label>মোবাইল <input></label> — ঘরটি label-এর ভেতরে থাকলে আর id লাগে না। ছোট ফর্ম আর checkbox-এ খুব সুবিধার।
জোড়া দিলে দুটি বড় লাভ। প্রথমত, ক্লিক করার জায়গা বড় হয়: label-এর লেখায় চাপলেই cursor ঘরে চলে যায়, আর checkbox হলে টিক পড়ে যায়। ছোট পর্দায় আঙুল দিয়ে ছোট্ট একটি বাক্সে চাপা কঠিন — বয়স্ক মানুষ বা কাঁপা হাতের কারও জন্য আরও কঠিন। দ্বিতীয়ত, ঘরটি একটি নাম পায়: label-এর লেখাটি ঘরের accessible name হয়, তাই screen reader ঘরে এলেই বলে “মোবাইল নম্বর, সম্পাদনাযোগ্য লেখা”। ভয়েস দিয়ে ফোন চালানো মানুষ “মোবাইল নম্বর-এ চাপো” বলে ঘরে যেতে পারেন, আর ব্রাউজারের autofill-ও label থেকে ইঙ্গিত নেয়।
<p><b>ক) শুধু placeholder</b></p>
<input type="text" name="a" placeholder="আপনার নাম">
<p><b>খ) পাশে লেখা, কিন্তু জোড়া নেই</b></p>
আপনার নাম <input type="text" name="b">
<p><b>গ) label + for/id</b></p>
<label for="nm">আপনার নাম</label>
<input type="text" id="nm" name="c">
<p><b>ঘ) label-এর ভেতরে মোড়ানো</b></p>
<label><input type="checkbox" name="agree"> আমি শর্তগুলো মেনে নিচ্ছি</label>চারটি অংশেই কিছু একটা “নাম” দেখা যাচ্ছে, কিন্তু আচরণ আলাদা। (ক)-তে ঘরে একটি অক্ষর লিখুন — ধূসর “আপনার নাম” উধাও, এখন আর বোঝার উপায় নেই ঘরটি কিসের ছিল। (খ)-তে “আপনার নাম” লেখায় চাপুন — কিছুই হয় না। (গ)-তে লেখায় চাপুন — cursor ঘরে চলে যায়। (ঘ)-তে বাক্সটি নয়, লেখায় চাপুন — টিক পড়ে আর ওঠে। চেষ্টা করুন: (গ)-তে id="nm"-কে id="name1" করে দিন — for আর id আর মেলে না, লেখায় চাপলে আর কাজ হয় না। চোখে দেখতে কোনো পার্থক্য নেই — এই ভুলটিই সবচেয়ে বেশি হয়।
চোখে না দেখা মানুষের কানে এই চারটি ঘর কেমন শোনায়? “পরে” চাপুন:
মোবাইল নম্বর <input type="tel" name="mobile">
<input type="tel" name="mobile"
placeholder="মোবাইল নম্বর">
<label for="mobile">মোবাইল নম্বর</label> <input type="tel" id="mobile" name="mobile">
<label for="moblie">মোবাইল নম্বর</label> <input type="tel" id="mobile" name="mobile">
<label for="mobile">মোবাইল নম্বর</label>
<input type="tel" id="mobile" name="mobile"
aria-describedby="mobile-hint">
<small id="mobile-hint">যেমন 01712345678</small>
- শুধু পাশে লেখা। চোখে দেখা মানুষ বোঝেন, কিন্তু ব্রাউজারের কাছে “মোবাইল নম্বর” শুধু একটি সাধারণ লেখা। Tab চেপে ঘরে এলে screen reader শুধু বলে “সম্পাদনাযোগ্য লেখা” — শ্রোতাকে অনুমান করতে হয়। লেখায় চাপলেও ঘরে cursor যায় না।
- শুধু placeholder. বেশিরভাগ ব্রাউজার label না পেলে শেষ উপায় হিসেবে placeholder-কে নাম ধরে, তাই অনেক screen reader নামটা পড়ে। কিন্তু সমস্যা চোখে দেখা মানুষের: লেখা শুরু করলেই নামটা হারায়, ধূসর লেখা পড়তে কষ্ট হয়, আর অনেকে ভাবেন ঘরে আগে থেকেই কিছু লেখা আছে।
- label + for/id. এখন নামটি সব সময় চোখের সামনে, আর ব্রাউজারের accessibility tree-তে ঘরটির নাম “মোবাইল নম্বর”। লেখায় চাপলে cursor ঘরে যায়। এটাই নিয়ম — প্রতিটি ঘরের একটি দৃশ্যমান label.
- বানান ভুল।
for="moblie"আরid="mobile"মেলে না — ব্রাউজার কোনো error দেখায় না, চুপচাপ জোড়া ভেঙে যায়, ঘর আবার নামহীন। DevTools-এর Accessibility অংশে ঘরটির “Name” ফাঁকা দেখলেই বুঝবেন। (মোড়ানো label-এ এই ঝুঁকি নেই।) - label আর উদাহরণ — দুটোই। উদাহরণ বা নিয়ম জানাতে চাইলে placeholder-এ নয়, ঘরের পাশে সব সময় দেখা যায় এমন লেখায় দিন, আর
aria-describedbyদিয়ে ঘরের সাথে জুড়ুন। screen reader নামের পরে বিবরণটিও পড়ে। (শব্দগুলো screen reader ভেদে একটু আলাদা — NVDA, JAWS, VoiceOver, TalkBack নিজের ভাষায় বলে — কিন্তু তথ্যটা একই। ARIA-র বিস্তারিত পর্ব ১২-এ।)
placeholder label নয়। placeholder হলো ঘর ফাঁকা থাকা অবস্থায় দেখানো একটি ছোট ইঙ্গিত — বড়জোর একটি উদাহরণ (“যেমন rakib@example.com”). এর ওপর ভরসা করে label বাদ দিলে: লেখা শুরু করলেই নাম হারায়, জমা দেওয়ার আগে নিজের উত্তর মিলিয়ে দেখা যায় না, ধূসর লেখা প্রায়ই রঙের পার্থক্য (contrast)-এর নিয়ম মানে না, আর কিছু অনুবাদ টুল আর পুরোনো সহায়ক প্রযুক্তি এটি পড়েই না। WCAG 2.2-এর নিয়ম ৩.৩.২ (Labels or Instructions) বলে, ব্যবহারকারীর তথ্য চাইলে label বা নির্দেশনা দিতে হবে। নিরাপদ নিয়ম: দৃশ্যমান label সব সময়, placeholder ঐচ্ছিক।
৫ · button — submit, reset আর button, আর ডিফল্টের ফাঁদ
<button>-এর type attribute-এর তিনটি মান:
| type | চাপলে কী হয় | কোথায় ব্যবহার |
|---|---|---|
submit | ফর্ম জমা হয় (আগে যাচাই, তারপর পাঠানো) | “জমা দিন”, “লগইন”, “অর্ডার করুন” |
reset | সব ঘর শুরুর মানে (value attribute-এ) ফিরে যায় | খুব কম — ভুলে চাপলে সব লেখা হারায় |
button | নিজে থেকে কিছুই হয় না; JavaScript কাজ জুড়ে দেয় | “পাসওয়ার্ড দেখান”, “আরেকটি নম্বর যোগ করুন” |
এখন সেই ফাঁদ, যাতে নতুন-পুরোনো সবাই অন্তত একবার পড়েন: ফর্মের ভেতরে <button>-এ type না লিখলে সেটি submit. ধরুন আপনি “পাসওয়ার্ড দেখান” বোতাম বানালেন, শুধু লেখাটা দেখানো-লুকানোর জন্য। type লেখেননি। ব্যবহারকারী চাপলেন — আর পুরো ফর্ম জমা হয়ে গেল, অর্ধেক পূরণ অবস্থায়! নিচে নিজেই দেখুন:
<form>
<label for="pw">পাসওয়ার্ড</label>
<input type="password" id="pw" name="password" value="nodi2026">
<button id="show">দেখান</button>
<p>
<button type="reset">মুছে আবার শুরু</button>
<button type="submit">লগইন</button>
</p>
</form>
<script>
document.getElementById('show').addEventListener('click', () => {
const pw = document.getElementById('pw');
pw.type = (pw.type === 'password') ? 'text' : 'password';
});
</script>“দেখান” চাপুন — পাসওয়ার্ড দেখা যায় ঠিকই, কিন্তু নিচে লেখাও আসে ফর্ম জমা হতো → password=nodi2026. আসল সাইটে ফর্ম জমা হয়ে পাতাটাই চলে যেত। সমাধান: “দেখান” বোতামে type="button" যোগ করুন, আবার চাপুন — এবার শুধু লেখা দেখা-লুকানো হয়, জমা হয় না। আরও একটি পরীক্ষা: ঘরে কিছু নতুন লিখে “মুছে আবার শুরু” চাপুন — ঘর ফাঁকা হয় না, ফিরে যায় value-তে লেখা “nodi2026”-এ। শেষে ঘরে cursor রেখে কি-বোর্ডের Enter চাপুন — সেটিও ফর্ম জমা দেয়।
শেষ পরীক্ষাটির নাম implicit submission — এক লাইনের ঘরে Enter চাপলে ব্রাউজার ফর্মের প্রথম submit বোতামটি চাপার মতো কাজ করে। তাই “দেখান” বোতামটি type ছাড়া থাকলে আর ফর্মে প্রথমে থাকলে, Enter চাপলে আসলে সেটিই “চাপা” হয় — অদ্ভুত বাগের আরেক উৎস। নিয়ম একটাই: প্রতিটি <button>-এ type লিখুন, এমনকি submit-ও — পড়তে পরিষ্কার, ভুলের জায়গা কম।
পুরোনো কোডে দেখবেন <input type="submit" value="জমা দিন">. এটিও চলে, কিন্তু ভেতরে শুধু সাধারণ লেখা রাখা যায়। <button>-এর ভেতরে আইকন, <strong> বা <span> রাখা যায় — তাই আজ সেটিই বেশি ব্যবহৃত। আর একটি জরুরি কথা: ক্লিক করে কিছু ঘটানোর জন্য <div onclick> নয়, সব সময় আসল <button> — আসল বোতাম কি-বোর্ডের Tab-এ পৌঁছায়, Enter আর Space-এ চাপা যায়, আর screen reader বলে “বোতাম”। div-এ এগুলোর কিছুই নিজে থেকে হয় না।
৬ · fieldset আর legend — ঘরগুলোকে দলে সাজানো
লম্বা কাগজের ফর্মে অংশ থাকে: “ব্যক্তিগত তথ্য”, “বর্তমান ঠিকানা”, “স্থায়ী ঠিকানা”। দুই অংশেই “জেলা” নামে একটি ঘর থাকতে পারে — কোনটা কোন অংশের, তা বোঝায় অংশের শিরোনাম। HTML-এ এই দলের জন্য <fieldset>, আর তার শিরোনাম <legend> — যা থাকতে হয় fieldset-এর একদম প্রথম সন্তান হিসেবে।
<fieldset>
<legend>বর্তমান ঠিকানা</legend>
<label for="cur-district">জেলা</label>
<input type="text" id="cur-district" name="current_district">
</fieldset>
<fieldset>
<legend>স্থায়ী ঠিকানা</legend>
<label for="perm-district">জেলা</label>
<input type="text" id="perm-district" name="permanent_district">
</fieldset>ব্রাউজার ডিফল্টভাবে fieldset-এর চারপাশে একটি দাগ টানে আর legend-কে সেই দাগের ওপর বসায় (পুরো উদাহরণে দেখবেন)। আসল লাভ শোনায়: screen reader “জেলা” ঘরে এলে বলে “বর্তমান ঠিকানা, দল … জেলা, সম্পাদনাযোগ্য লেখা” — দুটি একই নামের ঘর আর গুলিয়ে যায় না। fieldset সবচেয়ে বেশি জরুরি radio button-এর দলে (“লিঙ্গ: পুরুষ / নারী / অন্যান্য”), যেখানে প্রশ্নটিই legend — সেটি পর্ব ৯-এ। আর fieldset-এ disabled লিখলে ভেতরের সব ঘর একসাথে বন্ধ হয়ে যায় — এটিও একটি boolean attribute.
name-এর দুটি লেখার ধাঁচ। ওপরের উদাহরণে current_district-এ underscore, আর id-তে cur-district-এ hyphen. কোনোটাই বাধ্যতামূলক নয় — name যায় সার্ভারে, তাই সার্ভারের প্রোগ্রামারের সাথে মিলিয়ে ঠিক করুন; id থাকে পাতার ভেতরে, তাই CSS-এর ধাঁচে hyphen বেশি প্রচলিত। একটি প্রজেক্টে একটি ধাঁচ মেনে চলাই আসল কথা।
৭ · autocomplete আর inputmode — ফোনে দ্রুত পূরণ
একই নাম, ইমেইল, মোবাইল নম্বর — প্রতিটি সাইটে বারবার টাইপ করা বিরক্তিকর, আর ফোনের ছোট কি-বোর্ডে ভুলও হয় বেশি। ব্রাউজার আপনার তথ্য মনে রাখে, আর ফর্ম দেখলে নিজে থেকে পূরণের পরামর্শ দেয় — একে বলে autofill. কিন্তু ব্রাউজার কীভাবে বুঝবে কোন ঘরে নাম আর কোন ঘরে ফোন নম্বর? autocomplete attribute ঠিক এটাই বলে দেয়:
| মান | ঘরটি কী | মন্তব্য |
|---|---|---|
name | পুরো নাম | নামের অংশ আলাদা হলে given-name, family-name |
email | ইমেইল ঠিকানা | type="email"-এর সাথে |
tel | ফোন নম্বর, দেশের কোডসহ | শুধু দেশের ভেতরের রূপ চাইলে tel-national |
street-address | রাস্তা-বাড়ির পুরো ঠিকানা | কয়েক লাইনের ঘরে (textarea); এক লাইনের ঘরে address-line1 |
one-time-code | SMS-এ আসা OTP কোড | কিছু ফোনের ব্রাউজার SMS থেকে কোডটি পরামর্শ হিসেবে দেখায় |
new-password / current-password | নতুন / বর্তমান পাসওয়ার্ড | পাসওয়ার্ড ম্যানেজার নতুন শক্ত পাসওয়ার্ড বানানোর প্রস্তাব দেয় |
off | পরামর্শ চাই না | শুধু সত্যিই এককালীন তথ্যে — যেমন ক্যাপচা |
এই মানগুলো বানানো নয় — HTML স্পেসিফিকেশনে একটি নির্দিষ্ট তালিকা আছে, আর সব আধুনিক ব্রাউজার সেটি বোঝে। WCAG 2.2-এর নিয়ম ১.৩.৫ (Identify Input Purpose) ব্যক্তিগত তথ্যের ঘরে ঠিক এই মানগুলো ব্যবহারের কথা বলে — কারণ পড়া বা মনে রাখায় যাঁদের অসুবিধা, তাঁদের জন্য autofill অনেক বড় সাহায্য।
inputmode — কোন কি-বোর্ড আসবে
কখনো ঘরটি আসলে লেখা নেয়, কিন্তু আপনি চান ফোনে শুধু অঙ্কের কি-বোর্ড আসুক — যেমন OTP. এর জন্য inputmode: numeric (০–৯-এর বড় প্যাড), tel, email, decimal, url, search, text, none. এটি শুধু কি-বোর্ড বদলায় — কোনো যাচাই করে না, আর কম্পিউটারের আসল কি-বোর্ডে কোনো প্রভাব নেই। inputmode এখন Baseline Widely available — প্রধান সব মোবাইল ব্রাউজারে চলে, আর না চললে সাধারণ কি-বোর্ড আসে, ক্ষতি নেই।
নিচের স্টেপারে একটি OTP ঘরের প্রতিটি অংশ ভেঙে দেখুন:
<input— একটি এক লাইনের ঘর। এর আগে একটি<label for="otp">SMS-এ পাওয়া ৬ অঙ্কের কোড</label>থাকবে — লেবেল এখানেও বাদ নয়।type="text"—numberনয়! OTP একটি “কোড”, পরিমাণ নয়: এতে যোগ-বিয়োগ হয় না, শুরুতে 0 থাকতে পারে (“042719”), আর বাড়ানো-কমানোর তীর বা মাউসের চাকা ঘুরিয়ে মান বদলে যাওয়া এখানে বিপজ্জনক।inputmode="numeric"— ফোনে বড় অঙ্কের প্যাড আসে। ঘর লেখা নিলেও ব্যবহারকারী দেখেন শুধু ০–৯. type বদলানো ছাড়াই ঠিক কি-বোর্ড।autocomplete="one-time-code"— ব্রাউজারকে জানায় “এটা SMS-এ আসা কোডের ঘর”। iPhone-এর Safari আর কিছু Android ব্রাউজার SMS এলে কি-বোর্ডের ওপরে কোডটি দেখায় — এক চাপে পূরণ। সমর্থন সব ফোনে এক নয়, কিন্তু না থাকলেও ক্ষতি নেই।name="otp" id="otp"— name দিয়ে কোডটি সার্ভারে যায়, id দিয়ে label জোড়া লাগে। দুটো আলাদা কাজ, প্রায়ই একই শব্দ।maxlength="6"— ৬টির বেশি অক্ষর লেখাই যায় না। “ঠিক ৬টি অঙ্কই চাই” — এমন কড়া যাচাই (pattern,required) পর্ব ৯-এ।
বাংলাদেশের মোবাইল নম্বর — tel, number নয়
আমাদের নম্বর ১১ অঙ্কের, শুরু 01 দিয়ে (যেমন 01712345678); আন্তর্জাতিক রূপে +880 দিয়ে, প্রথম 0 বাদ — +8801712345678. অনেকে লেখেন ফাঁকা বা হাইফেন দিয়ে: “01712-345678”. এসব type="number" একদম সামলাতে পারে না, কারণ সেটি শুধু “সংখ্যা” বোঝে — +, ফাঁকা বা হাইফেন দেখলে মানটাই বাতিল করে দেয়। HTML স্পেসিফিকেশন নিজেই বলে, যে তথ্য শুধু অঙ্ক দিয়ে লেখা কিন্তু আসলে পরিমাণ নয়, তার জন্য number ঠিক নয়। দেখুন:
<form>
<p><label>type="number":
<input type="number" name="m1" value="+880 1712-345678"></label></p>
<p><label>type="tel":
<input type="tel" name="m2" value="+880 1712-345678" autocomplete="tel"></label></p>
<p><label>SMS-এর কোড:
<input type="text" name="otp" inputmode="numeric"
autocomplete="one-time-code" maxlength="6"></label></p>
<button type="submit">যাচাই করুন</button>
</form>
<script>
for (const box of document.querySelectorAll('input')) {
console.log(box.name + ' -> "' + box.value + '"');
}
</script>প্রথম ঘরটি ফাঁকা দেখাচ্ছে, যদিও দুটিতে একই value লেখা! নিচের লেখাও তাই বলে: m1 -> "", m2 -> "+880 1712-345678", otp -> "". number ঘর “+880 1712-345678”-কে বৈধ সংখ্যা মনে করেনি, তাই মান মুছে দিয়েছে — আসল সাইটে নম্বরটি সার্ভারে যেতই না। চেষ্টা করুন: প্রথম ঘরের value করুন 01712345678 — এবার দেখা যায়। এখন ঘরের পাশের ওপরের তীরটি একবার চাপুন — নম্বর হয়ে যায় 1712345679: শুরুর শূন্য উধাও, শেষ অঙ্কও বদলে গেছে! ফোনে এই এডিটর খুললে OTP ঘরে চাপুন — অঙ্কের প্যাড আসবে।
আরও গভীরে: জমা দেওয়ার সময় ব্রাউজার স্পেসিফিকেশনের “constructing the entry list” নিয়ম চালায়: ফর্মের সব control HTML-এর ক্রমে দেখে, আর বাদ দেয় যেগুলো disabled, যেগুলোর name নেই, টিক না দেওয়া checkbox, আর যে বোতাম চাপা হয়নি সেগুলো (চাপা submit বোতামের name-value থাকলে সেটি তালিকায় ঢোকে)। তারপর ডিফল্ট enctype application/x-www-form-urlencoded অনুযায়ী অক্ষরগুলো UTF-8 বাইটে ভেঙে percent-encode করে — আর একটি পুরোনো ঐতিহ্য মেনে ফাঁকা জায়গাকে %20-এর বদলে + লেখে, যা সাধারণ URL-এর নিয়ম থেকে আলাদা। ফাইল পাঠাতে লাগে enctype="multipart/form-data" — পর্ব ৯-এ দেখবেন। এই একই তালিকা JavaScript-এ পাওয়া যায় new FormData(form) দিয়ে; JavaScript কোর্সের ফর্ম পর্বে এর ব্যবহার আছে।
৮ · সব একসাথে — একটি পূর্ণ সাইন-আপ ফর্ম
ধরুন একটি অনলাইন কোর্সের সাইটে নতুন অ্যাকাউন্ট খোলার ফর্ম বানাচ্ছেন: নাম, মোবাইল, ইমেইল, জেলা, ঠিকানা আর পাসওয়ার্ড। এই পর্বে যা শিখলেন, সব এখানে — আর দুটি জিনিস পর্ব ৯-এর আগাম ঝলক: জেলা বেছে নেওয়ার <select> আর কয়েক লাইনের <textarea>. কোনো CSS নেই — ব্রাউজারের নিজস্ব চেহারা; সুন্দর করা হবে পর্ব ৪৩-এ।
<form action="/register" method="post">
<fieldset>
<legend>নতুন অ্যাকাউন্ট খুলুন</legend>
<p><label for="fullname">পুরো নাম</label>
<input type="text" id="fullname" name="fullname" autocomplete="name"></p>
<p><label for="mobile">মোবাইল নম্বর</label>
<input type="tel" id="mobile" name="mobile" autocomplete="tel"
aria-describedby="mobile-hint">
<small id="mobile-hint">১১ অঙ্ক, যেমন 01712345678</small></p>
<p><label for="email">ইমেইল</label>
<input type="email" id="email" name="email" autocomplete="email"></p>
<p><label for="district">জেলা</label>
<select id="district" name="district">
<option value="">— বেছে নিন —</option>
<option value="dhaka">ঢাকা</option>
<option value="chattogram">চট্টগ্রাম</option>
<option value="rajshahi">রাজশাহী</option>
<option value="sylhet">সিলেট</option>
</select></p>
<p><label for="addr">ঠিকানা</label><br>
<textarea id="addr" name="address" rows="2" autocomplete="street-address"></textarea></p>
<p><label for="pass">পাসওয়ার্ড</label>
<input type="password" id="pass" name="password" autocomplete="new-password"></p>
<button type="submit">অ্যাকাউন্ট খুলুন</button>
</fieldset>
</form>প্রিভিউতে একটি দাগ-ঘেরা বাক্স, তার ওপরের দাগে বসানো “নতুন অ্যাকাউন্ট খুলুন” — এটাই fieldset আর legend. ঘরগুলো পূরণ করে জেলা বেছে “অ্যাকাউন্ট খুলুন” চাপুন — নিচে আসবে ফর্ম জমা হতো → fullname=…&mobile=…&email=…&district=dhaka&address=…&password=…. খেয়াল করুন, জেলায় গেছে dhaka — option-এর value, পর্দার “ঢাকা” লেখা নয়। প্রতিটি label-এ চেপে দেখুন cursor ঠিক ঘরে যায় কি না। চেষ্টা করুন: নামের ঘরে required শব্দটি যোগ করে খালি অবস্থায় জমা দিন — ব্রাউজার নিজেই থামাবে আর একটি বার্তা দেখাবে। এটাই পর্ব ৯-এর গল্প।
এই ছোট ফর্মে লুকিয়ে আছে অনেক সিদ্ধান্ত। method="post", কারণ এটি নতুন অ্যাকাউন্ট বানায় আর পাসওয়ার্ড পাঠায়। মোবাইলে tel, number নয়। উদাহরণটি placeholder-এ নয়, চোখের সামনে থাকা <small>-এ, aria-describedby দিয়ে জোড়া। পাসওয়ার্ডে new-password, যাতে পাসওয়ার্ড ম্যানেজার একটি শক্ত পাসওয়ার্ডের প্রস্তাব দিতে পারে। আর ঠিকানার ঘরে street-address — এক চাপে পুরো ঠিকানা।
ফর্ম ওয়েবে এসেছে বেশ আগে। ১৯৯৩ সালে NCSA Mosaic ব্রাউজার ফর্ম সমর্থন যোগ করে, আর ১৯৯৫ সালের HTML 2.0 স্ট্যান্ডার্ডে <form>, <input>, <select>, <textarea> আনুষ্ঠানিক হয় — তখন থেকেই GET আর POST. <label>, <button>, <fieldset> আর <legend> এসেছে HTML 4-এ (১৯৯৭–৯৯)। email, tel, number-এর মতো নতুন type, placeholder, autocomplete-এর বিস্তৃত মান আর built-in যাচাই এসেছে “Web Forms 2.0” নামের একটি প্রস্তাব থেকে, যা পরে HTML5-এর অংশ হয়। inputmode আরও পরে, ধীরে ধীরে সব মোবাইল ব্রাউজারে পৌঁছেছে।
৯ · AI-এর যুগে — AI-এর বানানো ফর্ম কীভাবে যাচাই করবেন
“একটা রেজিস্ট্রেশন ফর্ম বানিয়ে দাও” — AI মুহূর্তে কোড দেবে, আর দেখতেও সুন্দর লাগবে। কিন্তু ফর্ম এমন জায়গা, যেখানে চোখে না পড়া ভুলের দাম সবচেয়ে বেশি: একটি name ভুল মানে তথ্য হারানো, একটি label কম মানে কেউ ফর্মটি পূরণই করতে পারছেন না, একটি type ছাড়া বোতাম মানে অর্ধেক পূরণ অবস্থায় জমা। AI শিখেছে ইন্টারনেটের বিপুল পুরোনো কোড থেকে, তাই এই ভুলগুলো তার উত্তরে প্রায়ই থাকে।
AI সাধারণত যেসব ভুল করে
| AI-এর ভুল | কেন সমস্যা | ঠিক উপায় |
|---|---|---|
| label নেই, শুধু placeholder | লেখা শুরু করলে নাম হারায়; অনেকের কাছে ঘরটি নামহীন | প্রতিটি ঘরে দৃশ্যমান <label> |
for আর id মেলে না | জোড়া ভাঙে, error দেখা যায় না | DevTools-এ প্রতিটি ঘরের Name দেখুন |
ঘরে name নেই (শুধু id) | তথ্য সার্ভারে যায় না | পাঠানোর প্রতিটি ঘরে name |
| “দেখান”, “যোগ করুন” বোতামে type নেই | চাপলে ফর্ম জমা হয়ে যায় | type="button" |
ফোন নম্বর, OTP-তে type="number" | +880, ফাঁকা, শুরুর শূন্যে গোলমাল | type="tel"; OTP-তে inputmode="numeric" |
লগইন ফর্মে method="get" বা method নেই | পাসওয়ার্ড URL-এ, history-তে | method="post", আর সাইট HTTPS |
সব ঘরে autocomplete="off" | autofill আর পাসওয়ার্ড ম্যানেজার বন্ধ | সঠিক মান: name, email, tel… |
<div onclick> দিয়ে “বোতাম” | কি-বোর্ডে চলে না, screen reader চেনে না | আসল <button> |
শর্তগুলো আগেই লিখে দিলে প্রথম উত্তরেই ভালো কাঠামো পাবেন। শেষ লাইনটি গুরুত্বপূর্ণ: AI-কে নিজের প্রতিটি সিদ্ধান্ত ব্যাখ্যা করতে বললে তার ভুল প্রায়ই নিজে থেকেই বেরিয়ে আসে।
AI-এর দেওয়া ফর্ম হাতে পেলে — যাচাইয়ের চেকলিস্ট
পরীক্ষা ও ইন্টারভিউতে — বিশ্ববিদ্যালয়, চাকরি বা ফ্রন্ট-এন্ড ইন্টারভিউর পরীক্ষায় এ ধরনের প্রশ্ন প্রায়ই আসে:
- GET আর POST-এর পার্থক্য? — GET তথ্য URL-এর query string-এ পাঠায়, বুকমার্ক করা যায়, খোঁজার কাজে; POST পাঠায় request-এর body-তে, কিছু বদলানো বা গোপন তথ্যের কাজে।
nameআরid-এর পার্থক্য? — name সার্ভারে যাওয়া জোড়ার নাম; id পাতার ভেতরে অনন্য পরিচয়, label-এর for যার সাথে মেলে।<button>-এর ডিফল্ট type কী? — submit; তাই ফর্মের ভেতরে সাধারণ বোতামেtype="button"লাগে।- placeholder কেন label-এর বদলি নয়? — লেখা শুরু করলে হারায়, contrast কম, সবার কাছে নির্ভরযোগ্য নাম নয়।
- ফোন নম্বরে
type="number"কেন নয়? — নম্বরটি পরিমাণ নয়; +, ফাঁকা, হাইফেন বাতিল হয়, তীর ঘোরালে মান বদলায় —type="tel"ঠিক।
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন — তারপর “→ উত্তর” চাপুন। এগুলো আপনাকে ট্যাগ-মুখস্থকারী থেকে ফর্ম-নকশাকার বানাবে।
প্র ০১GET আর POST — দুটোই তো তথ্য পাঠায়। তাহলে দুটি আলাদা method কেন দরকার, আর ভুলটা বেছে নিলে আসলে কী ক্ষতি হয়?
পার্থক্যটা শুধু “তথ্য কোথায় বসে” নয় — এটা একটি প্রতিশ্রুতি। HTTP-র নিয়মে GET হলো “safe” method: এটি শুধু কিছু চায়, সার্ভারের কিছু বদলানোর কথা নয়। এই প্রতিশ্রুতির ওপর ভরসা করে পুরো ওয়েব চলে। ব্রাউজার GET-এর ফল নিশ্চিন্তে cache-এ রাখে, পেছনে ফিরলে আবার চায়; সার্চ ইঞ্জিনের crawler লাখো GET লিংকে নির্ভয়ে ঢোকে; কিছু ব্রাউজার আর টুল আপনি ক্লিক করার আগেই লিংকের পাতা আগাম এনে রাখে (prefetch).
এখন ভাবুন, কেউ “পোস্ট মুছে ফেলুন” কাজটি একটি সাধারণ GET লিংক দিয়ে বানালেন। ২০০৫ সালে ঠিক এমন একটি ঘটনা বিখ্যাত হয়েছিল: Google-এর “Web Accelerator” নামের একটি টুল দ্রুততার জন্য পাতার লিংকগুলো আগাম খুলে রাখত। কিছু ওয়েব অ্যাপে “মুছুন” লিংক ছিল GET — টুলটি সেগুলো “খুলে” রাখতে গিয়ে ব্যবহারকারীদের তথ্যই মুছে ফেলছিল। দোষ টুলের যতটা, তার চেয়ে বেশি সেই অ্যাপগুলোর, যারা GET-এর প্রতিশ্রুতি ভেঙেছিল।
উল্টো ভুলেরও দাম আছে। সার্চ ফর্ম POST দিয়ে বানালে ফলাফলের পাতা বুকমার্ক বা শেয়ার করা যায় না, পেছনে ফিরলে ব্রাউজার জিজ্ঞেস করে “ফর্মটি আবার পাঠাবেন?”, আর সার্চ ইঞ্জিনও সেই পাতাগুলো দেখতে পায় না। পরীক্ষার ফলের সাইটে কেউ বন্ধুকে ফলের লিংক পাঠাতে পারবেন না — আবার রোল নম্বর টাইপ করতে হবে।
POST-এর পর পাতা reload করলে “আবার পাঠাবেন?” প্রশ্নটি আসে, কারণ ব্রাউজার জানে POST কিছু বদলাতে পারে — দুবার অর্ডার বা দুবার টাকা পাঠানো। এর জন্য সার্ভারের দিকে একটি প্রচলিত কৌশল আছে, “Post/Redirect/Get”: POST পেয়ে কাজ সেরে সার্ভার ব্রাউজারকে একটি GET পাতায় পাঠিয়ে দেয় (“ধন্যবাদ, অর্ডার নং ১২৩”), যাতে reload করলে শুধু সেই পাতাটাই আবার আসে। আর পাসওয়ার্ড GET-এ গেলে সেটি থেকে যায় history-তে, সার্ভারের log-এ, এমনকি অন্য সাইটে যাওয়ার সময় পাঠানো ঠিকানার তথ্যেও।
মূল উপলব্ধি: method বেছে নেওয়া মানে ব্রাউজার, cache, crawler আর সার্ভারকে জানানো — “এই কাজটি কি শুধু দেখা, নাকি কিছু বদলানো?” প্রশ্নটির সৎ উত্তর দিলে অনেক অদৃশ্য সমস্যা নিজে থেকেই এড়ানো যায়।
প্র ০২placeholder দেখতে এত পরিষ্কার আর জায়গা বাঁচায় — তবু অ্যাক্সেসিবিলিটি বিশেষজ্ঞরা কেন বারবার বলেন “placeholder label নয়”?
placeholder এসেছিল HTML5-এর সাথে, একটি নির্দিষ্ট কাজের জন্য: ফাঁকা ঘরে ছোট একটি ইঙ্গিত, যেমন “01712345678”. স্পেসিফিকেশন শুরু থেকেই স্পষ্ট বলেছে, এটি label-এর বিকল্প নয়। কিন্তু নকশাকাররা দেখলেন, label বাদ দিলে ফর্মটি ছোট আর “পরিষ্কার” লাগে — আর এভাবেই ভুলটি ছড়িয়ে পড়ল। সমস্যাগুলো এক এক করে দেখা যাক।
- স্মৃতির ওপর চাপ: লেখা শুরু করলেই ইঙ্গিত হারায়। চার-পাঁচটি ঘর পূরণের পর জমা দেওয়ার আগে মিলিয়ে দেখতে গেলে বোঝা যায় না কোন ঘরে কী চাওয়া হয়েছিল। যাঁদের মনোযোগ বা স্মৃতিতে অসুবিধা, তাঁদের জন্য এটি বড় বাধা — আর ব্রাউজার autofill করে দিলে তো কোনো ঘরের নামই আর দেখা যায় না।
- কম contrast: placeholder ইচ্ছা করেই ধূসর, যাতে আসল লেখা থেকে আলাদা লাগে। কিন্তু ধূসর লেখা প্রায়ই WCAG-এর contrast-এর মাপ পূরণ করে না — রোদে ফোনে পড়া কঠিন। আবার গাঢ় করলে মানুষ ভাবেন ঘরে আগে থেকেই কিছু লেখা আছে, আর সেটি না মুছে পাশ কাটিয়ে যান।
- সবার কাছে নাম নয়: ব্রাউজার label না পেলে placeholder-কে শেষ উপায় হিসেবে নাম ধরে, কিন্তু সব সহায়ক প্রযুক্তি একরকম আচরণ করে না, আর কিছু অনুবাদ টুল placeholder অনুবাদ করে না।
- ভয়েস কন্ট্রোল: যাঁরা কণ্ঠ দিয়ে কম্পিউটার চালান, তাঁরা দৃশ্যমান লেখা দেখে বলেন “মোবাইল নম্বরে চাপো”। নাম চোখের সামনে না থাকলে কী বলবেন?
এর জবাবে একসময় “floating label” নকশা জনপ্রিয় হয় — label ঘরের ভেতরে থাকে, লিখতে শুরু করলে ছোট হয়ে ওপরে উঠে যায়। এটি placeholder-এর চেয়ে ভালো, কারণ আসল label থেকেই যায়; তবে ছোট লেখা আর নড়াচড়ার নিজস্ব সমস্যা আছে। সবচেয়ে সরল ও নির্ভরযোগ্য নকশা এখনো সেই পুরোনোটাই: ঘরের ওপরে স্পষ্ট label, প্রয়োজনে তার নিচে উদাহরণ।
মূল উপলব্ধি: ফর্মের নকশায় “কম জিনিস = পরিষ্কার” সব সময় সত্য নয়। যে তথ্য ব্যবহারকারীর পুরো কাজের সময় দরকার, সেটি পুরো সময় চোখের সামনে থাকা চাই।
প্র ০৩<button>-এর ডিফল্ট type “submit” — এত বাগের উৎস হলেও এই নিয়ম কেন বদলানো হয় না?
কারণ ওয়েবের সবচেয়ে বড় নিয়ম: পুরোনো পাতা ভাঙা যাবে না। <button> এসেছিল HTML 4-এ, আর তখনই নিয়ম লেখা হয় — type না থাকলে submit. যুক্তিটা ছিল বোধগম্য: ফর্মের ভেতরে বোতামের প্রধান কাজই জমা দেওয়া। আজ পৃথিবীতে কোটি কোটি পাতা এই নিয়মের ওপর ভরসা করে type ছাড়া <button>জমা দিন</button> লিখে রেখেছে। নিয়ম বদলালে রাতারাতি সেই সব ফর্ম জমা দেওয়া বন্ধ হয়ে যেত।
মজার ইতিহাস আছে। পুরোনো Internet Explorer-এর কিছু সংস্করণ এই নিয়ম মানত না — সেখানে type ছাড়া button-এর ডিফল্ট ছিল “button”, আর জমা দেওয়ার মানও অন্যরকম পাঠাত। ফলে একই কোড এক ব্রাউজারে ফর্ম জমা দিত, অন্যটিতে দিত না। তখনকার ডেভেলপাররা একটি শিক্ষা নিয়েছিলেন — সব সময় type লিখে দিন। WHATWG-এর HTML স্পেসিফিকেশন পরে আচরণটি স্পষ্ট করে লিখে দেয়: type না থাকলে বা অচেনা মান থাকলে submit, আর এখন সব ব্রাউজার তা মানে।
এর সাথে যোগ হয় implicit submission — এক লাইনের ঘরে Enter চাপলে ফর্মের প্রথম submit বোতাম “চাপা” হয়। এটি অনেক কাজের: কি-বোর্ড ব্যবহারকারী Enter চেপেই সার্চ করতে পারেন। কিন্তু প্রথম বোতামটি যদি type ছাড়া “ছবি মুছুন” হয়, Enter চাপলে সেটিই ঘটে! React বা Vue-এর মতো ফ্রেমওয়ার্কে কাজ করা ডেভেলপাররা প্রায়ই এই ফাঁদে পড়েন, কারণ তাঁরা বোতামকে শুধু JavaScript-এর ক্লিক হিসেবে ভাবেন, ফর্মের অংশ হিসেবে নয়।
অনেক টিম তাই কোড-পরীক্ষার টুলে (linter) একটি নিয়ম চালু রাখে: “type ছাড়া button চলবে না”। আর ব্রাউজারের ইতিহাস থেকে একটি বড় শিক্ষা — ডিফল্ট আচরণ একবার ছড়িয়ে পড়লে সেটি প্রায় চিরস্থায়ী; ভালো ডিফল্ট বেছে নেওয়া নকশার সবচেয়ে কঠিন সিদ্ধান্তগুলোর একটি।
মূল উপলব্ধি: ওয়েব প্ল্যাটফর্ম পেছনের দিকে সামঞ্জস্য রাখতে ভুল ডিফল্টও বয়ে বেড়ায়। স্পষ্ট করে লেখা — type="button" বা type="submit" — ডিফল্টের ওপর ভরসা করার চেয়ে সব সময় নিরাপদ।
প্র ০৪অনেক ব্যাংক ও অফিসের সাইট নিরাপত্তার নামে autocomplete="off" লেখে, এমনকি পাসওয়ার্ড পেস্ট করাও আটকে দেয়। এটা কি সত্যিই নিরাপত্তা বাড়ায়?
এক সময় ধারণা ছিল, ব্রাউজার তথ্য মনে না রাখলে চুরির ঝুঁকি কমে। তাই বহু সাইট লগইন ফর্মে autocomplete="off" লিখত, আর পাসওয়ার্ডের ঘরে পেস্ট আটকে দিত। কিন্তু বাস্তবে এর ফল হলো উল্টো। ব্যবহারকারী যখন প্রতিবার হাতে পাসওয়ার্ড টাইপ করতে বাধ্য হন, তখন তাঁরা ছোট, সহজ আর একই পাসওয়ার্ড সব জায়গায় ব্যবহার করেন — “dhaka123”. একটি সাইট থেকে সেটি ফাঁস হলে সব সাইট বিপদে।
পাসওয়ার্ড ম্যানেজার (ব্রাউজারের নিজের বা আলাদা অ্যাপ) প্রতিটি সাইটের জন্য লম্বা, এলোমেলো, আলাদা পাসওয়ার্ড বানায় আর নিজেই পূরণ করে। এটি আরেকটি বড় বিপদ থেকেও বাঁচায় — ভুয়া সাইট (phishing). ম্যানেজার শুধু আসল ঠিকানাতেই পাসওয়ার্ড দেয়; দেখতে হুবহু এক ভুয়া সাইটে সে চুপ থাকে, আর এই চুপ থাকাটাই সতর্কসংকেত। যুক্তরাষ্ট্রের NIST-এর ডিজিটাল পরিচয়ের নির্দেশিকা (SP 800-63B) এ কারণেই বলে, পাসওয়ার্ডের ঘরে পেস্ট করতে দেওয়া উচিত।
ব্রাউজারগুলোও এই বাস্তবতা মেনে নিয়েছে। বহু বছর আগে থেকেই প্রধান ব্রাউজারগুলো লগইন ফর্মে autocomplete="off" প্রায়ই উপেক্ষা করে এবং পাসওয়ার্ড সেভ করার প্রস্তাব দেয় — কারণ ব্যবহারকারীর নিরাপত্তা সাইটের সেই অনুরোধের চেয়ে বেশি গুরুত্বপূর্ণ। এর বদলে সাইটগুলোর জন্য সঠিক পথ হলো সঠিক মান দেওয়া: লগইনে current-password, নতুন অ্যাকাউন্টে new-password, যাতে ম্যানেজার জানে কোথায় পুরোনোটা দেবে আর কোথায় নতুন শক্ত পাসওয়ার্ড বানাবে।
অ্যাক্সেসিবিলিটির দিকও আছে। WCAG 2.1-এ যোগ হওয়া নিয়ম ১.৩.৫ বলে, ব্যক্তিগত তথ্যের ঘরের উদ্দেশ্য যন্ত্রকে জানাতে হবে — আর সেটা করা হয় ঠিক এই autocomplete মানগুলো দিয়ে। আর WCAG 2.2-এ যোগ হয়েছে নিয়ম ৩.৩.৮ (Accessible Authentication): লগইনে মানুষকে মুখস্থ বা হাতে নকল করার মতো “বুদ্ধির পরীক্ষা” দিতে বাধ্য করা যাবে না, অন্তত পেস্ট বা পাসওয়ার্ড ম্যানেজারের পথ খোলা রাখতে হবে।
মূল উপলব্ধি: নিরাপত্তার নামে ব্যবহারকারীর কাজ কঠিন করলে মানুষ আরও অনিরাপদ পথ খোঁজে। ভালো নিরাপত্তা আর ভালো ব্যবহারযোগ্যতা প্রায়ই একই দিকে হাঁটে — সঠিক autocomplete মান তার ছোট্ট উদাহরণ।
প্র ০৫type আর inputmode — দুটোই তো ফোনের কি-বোর্ড বদলায়। তাহলে দুটি আলাদা জিনিস কেন, আর কোন ঘরে কোনটা?
কারণ দুটি আলাদা প্রশ্নের উত্তর দেয়। type বলে তথ্যটা কী — আর এর সাথে আসে আচরণ: যাচাই, মানের নিয়ম, পাসওয়ার্ড ঢাকা, কিছু ক্ষেত্রে বিশেষ নিয়ন্ত্রণ (তীর, ক্যালেন্ডার)। inputmode শুধু বলে কোন কি-বোর্ড সুবিধাজনক — আর কিছু নয়। শুরুর দিকে ডেভেলপাররা ফোনে সংখ্যার কি-বোর্ড পেতে সব জায়গায় type="number" লিখতেন, আর সাথে পেতেন অনাকাঙ্ক্ষিত আচরণ। inputmode সেই দুটোকে আলাদা করেছে।
type="number" ভাবা হয়েছে পরিমাণের জন্য — বয়স, পণ্যের সংখ্যা। HTML স্পেসিফিকেশন নিজেই সতর্ক করে, যে তথ্য শুধু অঙ্কে লেখা কিন্তু সংখ্যা নয় — ক্রেডিট কার্ড নম্বর, পোস্ট কোড — তার জন্য এটি ঠিক নয়। কারণগুলো আপনি এডিটরে দেখেছেন: + বা ফাঁকা থাকলে মান বাতিল, তীর আর মাউসের চাকায় মান বদলে যাওয়া, আর বৈজ্ঞানিক রূপের “e” অক্ষরও “বৈধ”। যুক্তরাজ্যের সরকারি সাইটগুলোর নকশা-নির্দেশিকা (GOV.UK Design System) বাস্তব ব্যবহারকারীদের সমস্যা দেখে এমন ঘরে type="text" আর inputmode="numeric" ব্যবহারের পরামর্শে বদলেছে।
বাংলাদেশের বাস্তবতায় একটি ছোট নির্দেশিকা:
- মোবাইল নম্বর:
type="tel"+autocomplete="tel"— tel নিজেই ডায়াল-প্যাড আনে, তাই inputmode লাগে না। +880, ফাঁকা, হাইফেন সব নেয়; সার্ভারে পরিষ্কার করে নিন। - OTP, পিন, রোল নম্বর, NID নম্বর:
type="text"+inputmode="numeric"— অঙ্কের প্যাড, কিন্তু শুরুর শূন্য বা লম্বা নম্বর নিরাপদ। OTP-তে সাথেone-time-code. - দাম, ওজন: ভগ্নাংশ লাগলে
inputmode="decimal"(দশমিক বিন্দুসহ প্যাড); সত্যিকারের পরিমাণে সীমা-যাচাই চাইলেtype="number". - বয়স, পণ্যের সংখ্যা: এখানে number ঠিক — এটি সত্যিই পরিমাণ।
আরেকটি সূক্ষ্ম কথা: কি-বোর্ড শুধু সুবিধা, বাধ্যবাধকতা নয়। বাংলা কি-বোর্ড ব্যবহার করা কেউ বাংলা অঙ্কে (০১৭…) নম্বর লিখতে পারেন — সেগুলো সার্ভারে পৌঁছায় ইংরেজি অঙ্ক থেকে আলাদা অক্ষর হিসেবে। তাই সার্ভারে সব সময় যাচাই আর পরিষ্কার করা জরুরি — HTML-এর যাচাই শুধু প্রথম ধাপ।
মূল উপলব্ধি: “এটা কী তথ্য” আর “কীভাবে টাইপ করা সহজ” — দুটি আলাদা প্রশ্ন। type দিয়ে প্রথমটির, inputmode দিয়ে দ্বিতীয়টির সৎ উত্তর দিন।
অনুশীলন
প্রথম তিনটিতে ভাবা আর খুঁজে বের করাই আসল কাজ। চতুর্থটিতে একটি ছোট ফর্ম লিখবেন।
-
GET না POST? (ক) একটি অনলাইন দোকানে “লাল শাড়ি” খোঁজা (খ) bKash-এর মতো অ্যাপের ওয়েব সংস্করণে টাকা পাঠানো (গ) ট্রেনের সময়সূচিতে “ঢাকা থেকে রাজশাহী” দেখা (ঘ) নিউজলেটারে ইমেইল দিয়ে সাবস্ক্রাইব করা।
(ক) GET — শুধু খোঁজা; ফলের পাতা শেয়ার বা বুকমার্ক করা যাবে (
?q=লাল+শাড়ি)। (খ) POST — টাকা পাঠানো সার্ভারের অবস্থা বদলায়, আর পিনের মতো গোপন তথ্য যায়; সাথে অবশ্যই HTTPS. (গ) GET — দেখার কাজ, লিংকটি কাউকে পাঠালে তিনিও একই সময়সূচি পাবেন। (ঘ) POST — সার্ভারে নতুন কিছু যোগ হচ্ছে (তালিকায় ইমেইল); GET হলে কোনো crawler বা prefetch ভুল করে সাবস্ক্রাইব করিয়ে দিতে পারত। -
ভুল খুঁজুন: নিচের ফর্মে চারটি ভুল আছে।
<form action="/login"> <input type="text" id="user" placeholder="মোবাইল নম্বর"> <label for="pass">পাসওয়ার্ড</label> <input type="password" id="password" name="password"> <button>দেখান</button> <button type="submit">লগইন</button> </form>১. method নেই — ডিফল্ট GET, তাই পাসওয়ার্ড URL-এ যাবে;
method="post"লাগবে। ২. প্রথম ঘরে name আর label নেই — মোবাইল নম্বর সার্ভারে যাবেই না, আর placeholder লেবেলের কাজ করছে;name="mobile",type="tel", একটি<label for="user">আরautocomplete="tel"দিন। ৩. for আর id মেলে না —for="pass"কিন্তুid="password"; দুটো এক করুন (আর সাথেautocomplete="current-password"). ৪. “দেখান” বোতামে type নেই — চাপলে ফর্ম জমা হবে, আর এটি প্রথম বোতাম বলে Enter চাপলেও এটিই “চাপা” হবে;type="button"লিখুন। -
কী পাঠানো হবে? একটি ফর্মে আছে:
<input name="city" value="খুলনা">,<input id="zip" value="9100">,<input name="phone" value="01812345678" disabled>, আর<input name="note" value="">. method="get", action="/save". জমা দিলে URL কেমন হবে (বাংলা অক্ষরের সংকেত “…” লিখলেই চলবে)?/save?city=%E0%A6%96…¬e=. city যায় (সংকেত করা “খুলনা”)। zip যায় না — id আছে, কিন্তু name নেই। phone যায় না —disabledঘর তালিকা থেকে বাদ পড়ে (শুধু পড়ার জন্য অথচ পাঠাতে চাইলেreadonlyব্যবহার করতে হয়, সেটি পর্ব ৯-এ)। note যায়, কিন্তু খালি মানে —note=. খালি ঘরও name থাকলে জোড়া হিসেবে যায়। -
নিজে লিখুন — কোচিং সেন্টারে ভর্তির ফর্ম: একটি ফর্ম বানান যাতে আছে: শিক্ষার্থীর নাম, অভিভাবকের মোবাইল, ইমেইল (ঐচ্ছিক), আর “অভিভাবকের তথ্য” নামে একটি fieldset. প্রতিটি ঘরে label, name, সঠিক type আর autocomplete; একটি submit বোতাম। ওপরের যেকোনো লাইভ এডিটরে লিখে জমা দিয়ে দেখুন।
একটি সম্ভাব্য উত্তর — এখানেই চালিয়ে দেখুন:
<form action="/admission" method="post"> <p><label for="student">শিক্ষার্থীর নাম</label> <input type="text" id="student" name="student_name"></p> <fieldset> <legend>অভিভাবকের তথ্য</legend> <p><label for="g-mobile">মোবাইল নম্বর</label> <input type="tel" id="g-mobile" name="guardian_mobile" autocomplete="tel"></p> <p><label for="g-email">ইমেইল (ঐচ্ছিক)</label> <input type="email" id="g-email" name="guardian_email" autocomplete="email"></p> </fieldset> <p><button type="submit">ভর্তির আবেদন পাঠান</button></p> </form>ঘরগুলো পূরণ করে চাপলে আসবে
student_name=…&guardian_mobile=…&guardian_email=…. শিক্ষার্থীর নামেautocomplete="name"দেওয়া হয়নি, কারণ পূরণ করবেন সাধারণত অভিভাবক — তাঁর নিজের নাম autofill হলে ভুল হতো। এমন ক্ষেত্রেautocomplete="off"নয়, শুধু মানটা না দেওয়াই যথেষ্ট। চেষ্টা করুন: ইমেইলের label থেকে “(ঐচ্ছিক)” মুছে দিলে পাঠক কীভাবে বুঝতেন এটি বাধ্যতামূলক নয়? (কোনো ঘরকে বাধ্যতামূলক করারrequiredattribute পর্ব ৯-এ।)
নিজেকে যাচাই করুন
ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।
ক্রমএকটি HTML ফর্মে submit বোতাম চাপার পর ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)
- ব্যবহারকারী submit বোতাম চাপেন বা ঘরে Enter দেন
- ব্রাউজার নিজের built-in নিয়মে ঘরগুলো যাচাই করে
- name থাকা ঘরগুলো থেকে নাম=মান জোড়ার তালিকা বানায়
- method অনুযায়ী জোড়াগুলো URL-এ বা body-তে সাজায়
- action-এর ঠিকানায় request পাঠায় আর উত্তরের পাতা দেখায়
একটি ফর্মে <input id="phone" value="01912345678"> আছে, কিন্তু কোনো name attribute নেই। ফর্ম জমা দিলে এই ঘরের কী হবে?
- phone=01912345678 হিসেবে যাবে, কারণ id-ই নাম হিসেবে কাজ করে
- ব্রাউজার জমা দেওয়া থামিয়ে একটি error দেখাবে
- ঘরটি বাদ পড়বে — এর মান সার্ভারে যাবে না
- মানটি নাম ছাড়া, শুধু =01912345678 হিসেবে যাবে
একটি ওয়েবসাইটে লগইন ফর্মের (মোবাইল নম্বর আর পাসওয়ার্ড) জন্য কোন method সঠিক?
- get, কারণ এটি দ্রুত
- post
- method না লেখাই ভালো, ব্রাউজার নিজে ঠিক করবে
- dialog
একটি ফর্মের ভেতরে <button>পাসওয়ার্ড দেখান</button> লেখা আছে, কোনো type ছাড়া। ব্যবহারকারী বোতামটি চাপলে কী হবে?
- কিছুই হবে না, কারণ type নেই
- ফর্মের সব ঘর শুরুর মানে ফিরে যাবে
- শুধু JavaScript-এ লেখা কাজটি চলবে, ফর্ম জমা হবে না
- ফর্মটি জমা হয়ে যাবে
<label for="email">ইমেইল</label> লেবেলটি কোন ঘরের সাথে জোড়া লাগবে?
- যে ঘরের
id="email" - যে ঘরের
name="email" - যে ঘরের
type="email" - label-এর ঠিক পরের ঘরটি, তার id যা-ই হোক
SMS-এ আসা ৬ অঙ্কের OTP নেওয়ার ঘরের জন্য সবচেয়ে উপযুক্ত কোনটি?
- <input type="number" name="otp">
- <input type="password" name="otp">
- <input type="text" name="otp" inputmode="numeric" autocomplete="one-time-code">
- <input type="email" name="otp">
ইনপুট ঘরে শুধু placeholder="আপনার নাম" দিয়ে, কোনো label ছাড়া ফর্ম বানানোর প্রধান সমস্যা কোনটি?
- placeholder থাকলে ফর্ম জমা দেওয়া যায় না
- লেখা শুরু করলেই ইঙ্গিতটি হারিয়ে যায়, আর ঘরটি সবার কাছে নির্ভরযোগ্য নাম পায় না
- placeholder-এর লেখা সার্ভারে মান হিসেবে চলে যায়
- placeholder একটি অচল (deprecated) attribute
শব্দকোষ
লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন — অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:
মনে রাখুন
- ফর্ম পাঠায় নাম=মান জোড়া;
nameছাড়া ঘর বাদ,disabledঘরও বাদ। - GET — URL-এর query string, খোঁজা ও দেখার কাজে; POST — request-এর body, কিছু বদলানো বা গোপন তথ্যে, সাথে HTTPS.
- প্রতিটি ঘরের দৃশ্যমান label — for/id মিলিয়ে বা ভেতরে মুড়ে; placeholder শুধু ইঙ্গিত।
- ফর্মের ভেতরে
<button>-এর ডিফল্ট submit — সাধারণ বোতামেtype="button"; একই নামের ঘরের দলে fieldset + legend. - ফোন নম্বরে
tel, OTP-তেinputmode="numeric"+one-time-code; সঠিক autocomplete মান autofill আর পাসওয়ার্ড ম্যানেজারকে কাজ করতে দেয়।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পর্ব ০৯ · ফর্মের নানা কন্ট্রোল আর built-in validationপরবর্তী পর্বcheckbox থেকে ফাইল আপলোড, আর JavaScript ছাড়াই তথ্য যাচাই।
- HTML ও CSS · কোর্স হোম৫৯টি পর্বপুরো কোর্সের রোডম্যাপ — প্রথম পেজ থেকে আধুনিক রেসপন্সিভ ডিজাইন।
- কম্পিউটার ও ICT · লিংক, টেবিল আর ফর্মপাশের ট্র্যাকICT পরীক্ষার দৃষ্টিকোণ থেকে HTML ফর্মের সংক্ষিপ্ত পরিচয়।
- JavaScript · ফর্ম আর যাচাইগভীরে যানJavaScript দিয়ে ফর্মের তথ্য পড়া, FormData আর নিজের যাচাইয়ের নিয়ম।