HTML
Basic Content Tags
div / span ใน HTML (แท็กทั่วไปที่ใช้บ่อยมาก)
บทนี้สอนผู้เริ่มต้นให้เข้าใจความต่างของ ดิฟ (div) และ สแปน (span) อย่างชัดเจน ทั้งบทบาทแบบบล็อก (block) และอินไลน์ (inline) พร้อม Lab 3 ระดับที่ตรวจอัตโนมัติใน Playground ได้จริง
1. หัวข้อนี้คืออะไร
ดิฟ (div) และ สแปน (span) คือแท็กทั่วไป (Generic Elements) ใน HTML ทั้งสองแท็กไม่ได้บอกความหมายเชิงเนื้อหา (semantic meaning) ด้วยตัวมันเอง แต่ใช้เป็นโครงครอบเพื่อจัดกลุ่มเนื้อหาและเตรียมต่อกับ CSS/JavaScript สรุปสั้น: - ดิฟ (div) มักใช้เป็นคอนเทนเนอร์ (container) แบบบล็อก (block) - สแปน (span) มักใช้ครอบข้อความบางส่วนแบบอินไลน์ (inline)
2. ทำไมหัวข้อนี้สำคัญ
- ใช้จริงแทบทุกหน้าเว็บ ทั้งงานจัดเลย์เอาต์และงานตกแต่งข้อความ
- ช่วยให้เราใส่ class หรือ id ลงจุดที่ต้องการได้แม่นขึ้น
- เป็นพื้นฐานก่อนเรียน CSS การจัดวาง และการจับ element ด้วย JavaScript
- ลดความสับสนเรื่อง block กับ inline ซึ่งมีผลกับพฤติกรรมการแสดงผลทันที
3. ตัวอย่างจากชีวิตจริง
ภาพขนาดกลาง: div ใช้ครอบเนื้อหาเป็นก้อน ส่วน span ใช้ครอบข้อความบางช่วงในบรรทัด
ลองนึกภาพหน้าข่าว 1 หน้า: - กล่องข่าวแต่ละใบ = ดิฟ (div) เพราะเป็นก้อนเนื้อหาแบบบล็อก - คำว่า "ด่วน" ในหัวข้อข่าว = สแปน (span) เพราะเป็นการไฮไลต์แค่บางคำในบรรทัดเดียวกัน ดังนั้น div มักใช้ "จัดกลุ่มเป็นก้อน" ส่วน span มักใช้ "แตะบางส่วนของข้อความ"
4. แนวคิดหลักที่ต้องเข้าใจ
- div และ span เป็น Generic Elements ไม่ได้สื่อ semantic ด้วยตัวเอง
- div เป็น block-level โดยพฤติกรรมตั้งต้น กินความกว้างบรรทัดและขึ้นบรรทัดใหม่
- span เป็น inline-level โดยพฤติกรรมตั้งต้น อยู่ต่อเนื่องในบรรทัดเดียวกัน
- ทั้งสองแท็กนิยมใช้ร่วมกับ class, id, CSS และ JavaScript
- ถ้ามีแท็ก semantic ที่เหมาะกว่า เช่น section หรือ article ควรใช้แท็กนั้นก่อน
5. การทำงานทีละขั้นตอน
ภาพขนาดเล็ก: block จะเรียงขึ้นบรรทัดใหม่ ส่วน inline จะอยู่ต่อกันในบรรทัดเดียว
- 1) เริ่มจากเลือกแท็ก semantic ก่อนเสมอ (เช่น section, article, p)
- 2) ถ้าต้องการกลุ่มเพิ่มเพื่อจัด layout หรือควบคุม style ให้ใช้ div
- 3) ถ้าต้องการตกแต่งข้อความบางช่วงในบรรทัด ให้ใช้ span
- 4) ใส่ class หรือ id เพื่อผูกกับ CSS และ JavaScript
- 5) ทดสอบผลลัพธ์ในเบราว์เซอร์ เพื่อยืนยันพฤติกรรม block/inline
6. ตัวอย่างเชิงเทคนิค / โค้ด
ตัวอย่างนี้แสดงให้เห็นทั้งการใช้ div ครอบหลาย element และ span ครอบข้อความบางส่วน พร้อม CSS ที่ทำให้เห็นพฤติกรรม block/inline ชัดเจน
div ใช้ครอบหลาย element ในก้อนเดียว และ span ใช้ครอบข้อความบางช่วงภายในย่อหน้า
<div class="course-card">
<h2>HTML Basics</h2>
<p>เริ่มจากเข้าใจ <span class="highlight">โครงสร้าง</span> ของหน้าเว็บ</p>
<p>แล้วค่อยต่อยอดไป CSS และ JavaScript</p>
</div>7. จุดที่ผู้เริ่มต้นมักสับสน
- คิดว่า div กับ span ใช้แทนกันได้ทุกกรณี
- ไม่เข้าใจความต่างระหว่าง block กับ inline
- ใช้ div เยอะเกินไปจนไม่เหลือ semantic structure
- ใช้ span ครอบเนื้อหาก้อนใหญ่ทั้งส่วน ซึ่งควรใช้ div หรือแท็ก semantic
8. เปรียบเทียบกับสิ่งที่ใกล้เคียง
ภาพขนาดกลาง: เลือก semantic tags ก่อน และใช้ div/span เมื่อบทบาทเป็น generic wrapper จริง ๆ
| แท็ก | ลักษณะ | ควรใช้เมื่อ |
|---|---|---|
| div | generic + block container | ต้องการครอบเนื้อหาเป็นก้อน เช่น card, panel, section ย่อย |
| span | generic + inline wrapper | ต้องการครอบข้อความบางคำเพื่อเน้นสี ขนาด หรือ hook style |
| section/article | semantic block | เนื้อหามีความหมายเชิงโครงสร้างชัดเจน ควรเลือกก่อน div |
| p/strong | semantic เนื้อหาในข้อความ | ย่อหน้าใช้ p, เน้นความสำคัญใช้ strong แทน span ที่ไม่มี semantic |
9. สรุปท้ายบทแบบจำง่าย
- div = กล่องครอบเนื้อหาแบบบล็อก
- span = ตัวครอบข้อความบางส่วนแบบอินไลน์
- ทั้งสองแท็กเป็น generic ไม่มี semantic meaning ในตัวเอง
- ถ้ามีแท็ก semantic ที่เหมาะกว่า ให้เลือก semantic ก่อน
- ใช้ class/id เพื่อเชื่อมกับ CSS และ JavaScript อย่างเป็นระบบ
10. Lab 1: พื้นฐาน - สร้างกล่องข้อมูลด้วย div
ชื่อ Lab: สร้างการ์ดบทเรียนด้วย div เป้าหมาย: ฝึกใช้ div ครอบหลาย element แบบ block โจทย์: ใน main ให้สร้าง div 1 ตัวที่มี class="lesson-box" แล้วภายในต้องมี h2 1 ตัวและ p 2 ตัว เงื่อนไข: ต้องมี div.lesson-box เพียง 1 ตัว, h2 1 ตัว, p 2 ตัว และ p ตัวที่สองมีข้อความ "เริ่มจากโครงสร้างก่อนสไตล์" สิ่งที่ระบบควรตรวจ: selector exists, selector count, source text, text content, browser runtime แนวทางการคิด: สร้างโครงด้วย div ก่อน แล้วเติมหัวข้อและย่อหน้าตามจำนวนที่กำหนด เฉลยตัวอย่าง: ดูในโค้ดเฉลยด้านล่าง
10. Lab 2: กลาง - ใช้ span ครอบข้อความบางคำ
ชื่อ Lab: ไฮไลต์คำสำคัญด้วย span เป้าหมาย: ฝึกใช้ span ครอบข้อความบางส่วนในบรรทัด โจทย์: ใน p#goal-text ให้ครอบคำว่า "div" และ "span" ด้วย span ที่มี class="term" เงื่อนไข: ต้องมี span.term ทั้งหมด 2 ตัว และข้อความเต็มของ p ต้องเป็น "วันนี้เราจะฝึก div และ span ในบทเดียวกัน" สิ่งที่ระบบควรตรวจ: selector count, source text, text content, browser runtime แนวทางการคิด: เขียนประโยคให้ครบก่อน แล้วค่อยครอบเฉพาะคำสำคัญด้วย span เฉลยตัวอย่าง: ดูในโค้ดเฉลยด้านล่าง
10. Lab 3: ท้าทาย - แก้โค้ด div/span ให้ถูกบริบท
ชื่อ Lab: ปรับโครงสร้างให้เหมาะกับ semantic มากขึ้น เป้าหมาย: แยกการใช้ div และ span ให้เหมาะสม พร้อมคง semantic tag ที่ควรใช้ โจทย์: โค้ดตั้งต้นใช้ div แทนโครงหลักมากเกินไป ให้แก้ดังนี้ - ต้องมี section class="article-card" ครอบทั้งบล็อก - หัวข้อใช้ h2 และมีข้อความ "แนวทางเขียน HTML" - ย่อหน้าแรกต้องมี span class="emphasis" ครอบคำว่า "semantic" - ใน section ต้องไม่มี div ลูกโดยตรง (ให้ใช้ p และ span ตามโจทย์) เงื่อนไข: section.article-card ต้องมี p จำนวน 2 ตัว และ span.emphasis จำนวน 1 ตัว สิ่งที่ระบบควรตรวจ: selector exists, selector count, source text, browser runtime แนวทางการคิด: รักษา semantic tag ให้ถูก และใช้ span เฉพาะจุดที่ต้องเน้นคำ เฉลยตัวอย่าง: ดูในโค้ดเฉลยด้านล่าง
10. Lab 4: ใช้ span เน้นคำในข้อความ
ชื่อ Lab: เน้นคำสำคัญในย่อหน้า เป้าหมาย: ใช้ span สำหรับเน้นเฉพาะคำ โดยไม่เปลี่ยนโครงสร้างหลักของเนื้อหา โจทย์: ใน section class="note-card" ให้สร้าง h2 ข้อความ "คำแนะนำการเขียน HTML" และ p 1 ย่อหน้า โดยใน p ต้องมี span class="highlight" ครอบคำว่า "semantic" เงื่อนไข: ต้องมี h2 1 ตัว, p 1 ตัว, span.highlight 1 ตัว และ span ต้องอยู่ภายใน p สิ่งที่ระบบควรตรวจ: selector exists, selector count, source text, browser runtime แนวทางการคิด: ใช้ span เฉพาะคำที่ต้องการเน้น ไม่ใช้ span ครอบทั้งย่อหน้า เฉลยตัวอย่าง: ดูในโค้ดเฉลยด้านล่าง
10. Lab 5: ใช้ div ครอบกลุ่มข้อมูลและ span สำหรับป้ายข้อความ
ชื่อ Lab: จัดกลุ่มข้อมูลด้วย div และเน้นป้ายข้อความด้วย span เป้าหมาย: ใช้ div สำหรับครอบกลุ่มย่อย และใช้ span สำหรับข้อความสั้นภายในบรรทัด โจทย์: ใน section class="profile-card" ให้มี div class="profile-meta" 1 ตัว ภายในต้องมี p 2 ตัวดังนี้: - p แรกมีข้อความ "ชื่อคอร์ส: HTML Basics" โดยคำว่า "ชื่อคอร์ส:" ต้องอยู่ใน span class="label" - p ที่สองมีข้อความ "ระดับ: Beginner" โดยคำว่า "ระดับ:" ต้องอยู่ใน span class="label" เงื่อนไข: ต้องมี div.profile-meta 1 ตัว, p 2 ตัว, span.label 2 ตัว และ span ต้องอยู่ภายใน p สิ่งที่ระบบควรตรวจ: selector exists, selector count, source text, browser runtime แนวทางการคิด: ใช้ div เพื่อรวมข้อมูลที่เป็นกลุ่มเดียวกัน และใช้ span สำหรับป้ายสั้น ๆ ในบรรทัด เฉลยตัวอย่าง: ดูในโค้ดเฉลยด้านล่าง
10. Lab 6: ท้าทาย - ซ่อมโค้ดที่ใช้ span แทน block element
ชื่อ Lab: แก้การใช้ span และ div ให้ตรงบริบท เป้าหมาย: ซ่อมโค้ดที่ใช้ span ครอบข้อความยาวและใช้ div แทน semantic ที่ควรมี โจทย์: จากโค้ดตั้งต้น ให้แก้ดังนี้ - ต้องมี section class="tip-box" ครอบทั้งบล็อก - ต้องมี h2 ข้อความ "เคล็ดลับการเขียนโค้ด" - ต้องมี p จำนวน 2 ตัว - ใน p แรก ต้องมี span class="keyword" ครอบคำว่า "semantic" - ภายใน section ต้องไม่มี span ที่ครอบทั้งบรรทัด และต้องไม่มี div ลูกโดยตรง เงื่อนไข: section.tip-box ต้องมี h2 1 ตัว, p 2 ตัว, span.keyword 1 ตัว, direct child div = 0 สิ่งที่ระบบควรตรวจ: selector exists, selector count, source text, browser runtime แนวทางการคิด: span เหมาะกับข้อความสั้นในบรรทัด ส่วนข้อความยาวควรใช้ p เฉลยตัวอย่าง: ดูในโค้ดเฉลยด้านล่าง
Lab 4 (ท้าทาย): เลือก input type ให้เหมาะกับข้อมูลติดต่อ
ชื่อ Lab: จับคู่ type ให้ตรงกับข้อมูลติดต่อ เป้าหมาย: ฝึกเลือก input type ให้เหมาะกับข้อมูลที่ผู้ใช้กรอก โจทย์: จากโค้ดตั้งต้นใน Playground ให้แก้เป็นดังนี้: input#phone ต้องเป็น type="tel", input#website ต้องเป็น type="url", input#birthday ต้องเป็น type="date" เงื่อนไข: ต้องคง form#contact-info-form และปุ่ม submit ข้อความ "บันทึกข้อมูลติดต่อ" สิ่งที่ระบบควรตรวจ: selector exists, source text, attribute value และ browser runtime แนวทางการคิด: ดูความหมายของข้อมูลก่อนว่าเป็นเบอร์โทร, เว็บไซต์ หรือวันที่ แล้วเลือก type ที่ตรงที่สุด เฉลยตัวอย่าง: ดูในส่วนเฉลยของ Lab นี้
เฉลยตัวอย่าง Lab 4
<form id="contact-info-form">
<label for="phone">เบอร์โทรศัพท์</label>
<input id="phone" name="phone" type="tel" />
<label for="website">เว็บไซต์ส่วนตัว</label>
<input id="website" name="website" type="url" />
<label for="birthday">วันเกิด</label>
<input id="birthday" name="birthday" type="date" />
<button type="submit">บันทึกข้อมูลติดต่อ</button>
</form>Lab 5 (ท้าทาย): ซ่อมฟอร์มล็อกอินให้ใช้ type ถูกต้อง
ชื่อ Lab: ปรับ type ในฟอร์มเข้าสู่ระบบ เป้าหมาย: เข้าใจว่า field แต่ละแบบในฟอร์มล็อกอินควรใช้ input type อะไร โจทย์: จากโค้ดตั้งต้นใน Playground ให้แก้เป็นดังนี้: input#username ต้องเป็น type="text", input#password ต้องเป็น type="password", input#remember ต้องเป็น type="checkbox" เงื่อนไข: ต้องคง form#login-form, ต้องมีปุ่ม submit ข้อความ "เข้าสู่ระบบ" และ checkbox ต้องมี id="remember" สิ่งที่ระบบควรตรวจ: selector exists, selector count, source text, attribute value และ browser runtime แนวทางการคิด: ข้อมูลที่ต้องซ่อนควรใช้ password ส่วนตัวเลือกเปิด/ปิดใช้ checkbox เฉลยตัวอย่าง: ดูในส่วนเฉลยของ Lab นี้
เฉลยตัวอย่าง Lab 5
<form id="login-form">
<label for="username">ชื่อผู้ใช้</label>
<input id="username" name="username" type="text" />
<label for="password">รหัสผ่าน</label>
<input id="password" name="password" type="password" />
<label>
<input id="remember" name="remember" type="checkbox" />
จดจำการเข้าสู่ระบบ
</label>
<button type="submit">เข้าสู่ระบบ</button>
</form>Lab 6 (ท้าทาย): แก้ฟอร์มสมัครคอร์สให้เลือก type ตามข้อมูล
ชื่อ Lab: เลือก type ให้ตรงกับข้อมูลการสมัคร เป้าหมาย: ฝึกวิเคราะห์ว่าข้อมูลแต่ละชนิดควรใช้ input แบบไหน โจทย์: จากโค้ดตั้งต้นใน Playground ให้แก้เป็นดังนี้: input#students ต้องเป็น type="number", input#start-date ต้องเป็น type="date", input#certificate ต้องเป็น type="checkbox" และ radio สำหรับช่วงเวลาเรียนต้องใช้ name="schedule" เหมือนกัน เงื่อนไข: ต้องคง form#course-signup และปุ่ม submit ข้อความ "สมัครคอร์ส" สิ่งที่ระบบควรตรวจ: selector exists, selector count, source text, attribute value และ browser runtime แนวทางการคิด: จำนวนใช้ number, วันใช้ date, ตัวเลือกเปิด/ปิดใช้ checkbox และตัวเลือกที่เลือกได้เพียงหนึ่งข้อควรอยู่ใน radio group เดียวกัน เฉลยตัวอย่าง: ดูในส่วนเฉลยของ Lab นี้
เฉลยตัวอย่าง Lab 6
<form id="course-signup">
<label for="students">จำนวนผู้เรียน</label>
<input id="students" name="students" type="number" min="1" />
<label for="start-date">วันเริ่มเรียน</label>
<input id="start-date" name="start-date" type="date" />
<label>
<input id="certificate" name="certificate" type="checkbox" />
ต้องการใบประกาศนียบัตร
</label>
<p>เลือกช่วงเวลาเรียน</p>
<label>
<input type="radio" name="schedule" value="morning" />
ช่วงเช้า
</label>
<label>
<input type="radio" name="schedule" value="evening" />
ช่วงเย็น
</label>
<button type="submit">สมัครคอร์ส</button>
</form>