ที่ผ่านมาเรามักหยิบ JavaScript หรือ library มาช่วยทำเรื่องเล็ก ๆ บนหน้าเว็บ ทั้งที่ HTML มี tag หรือ attribute ทำให้อยู่แล้ว โพสต์นี้รวมมาไว้ 10 ข้อ พร้อมสถานะการรองรับของเบราว์เซอร์ ณ ตุลาคม 2569
1. loading="lazy" ชะลอโหลดรูปที่ยังไม่โผล่บนจอ
ใส่ loading="lazy" ใน <img> แล้วเบราว์เซอร์จะยังไม่โหลดรูปนั้น จนกว่าผู้ใช้เลื่อนลงมาใกล้ หน้าที่มีรูปเยอะ ๆ จะเปิดเร็วขึ้นและเปลืองเน็ตน้อยลง
<img src="image.jpg" loading="lazy" width="800" height="600" alt="คำอธิบายรูป">
ใส่ width กับ height ไว้ด้วย เบราว์เซอร์จะกันที่ให้รูปไว้ก่อน หน้าเว็บจะไม่กระตุกตอนรูปโหลดเสร็จ และอย่าใส่ loading="lazy" ให้รูปที่เห็นทันทีตอนเปิดหน้า เช่นรูป banner ด้านบน เพราะจะทำให้รูปหลักขึ้นช้าลง (web.dev)
ตอนเขียนโพสต์นี้ครั้งแรก Safari ยังไม่รองรับ ตอนนี้รองรับแล้วตั้งแต่ Safari 15.4 (มี.ค. 65) ส่วน <iframe loading="lazy"> รองรับตั้งแต่ Safari 16.4 ดูตารางได้ที่ Can I use ทั้งของ รูป และ iframe เราจึงไม่ต้องใช้ library เสริมแล้ว
อ่านเพิ่มเรื่อง lazy loading ได้ที่ MDN
2. ลิงก์ <a> ส่งอีเมล โทรออก และส่ง SMS ได้
href ใน <a> ไม่จำเป็นต้องเป็นลิงก์เว็บ ใส่ scheme ด้านล่างนำหน้าแทนได้ (MDN)
mailto: เปิดโปรแกรมอีเมลพร้อมหัวเรื่อง
<a href="mailto:[email protected]?subject=Project%20inquiry&body=Hi">
ส่งอีเมลหาเรา
</a>
ช่องว่างและภาษาไทยใน subject กับ body ต้อง encode ก่อน (RFC 6068) ถ้าสร้างลิงก์ใน Blade ใช้ rawurlencode() ได้เลย
<a href="mailto:[email protected]?subject={{ rawurlencode('สอบถามโปรเจกต์') }}">
ส่งอีเมลหาเรา
</a>
tel: โทรออก
<a href="tel:+66812345678">
081-234-5678
</a>
ใส่เบอร์แบบมีรหัสประเทศ (+66 แล้วตัด 0 ตัวหน้า) จะโทรได้ถูกไม่ว่าผู้ใช้อยู่ประเทศไหน
sms: ส่ง SMS
<a href="sms:+66812345678?body=Hello">
ส่ง SMS หาเรา
</a>
tel: กับ sms: เหมาะกับผู้ใช้บนมือถือ กดแล้วเปิดแอปโทรศัพท์หรือแอปข้อความพร้อมเบอร์ให้เลย บนคอมพิวเตอร์จะเปิดโปรแกรมที่โทรได้แทน เช่น FaceTime ส่วน ?body= ของ SMS เขียนตาม RFC 5724 แต่แอปข้อความแต่ละเครื่องอ่านไม่เหมือนกัน ลองกดบนทั้ง iPhone และ Android จริงก่อนขึ้นเว็บ
3. <ol start> เริ่มนับเลขจากเลขไหนก็ได้
ใส่ start ใน <ol> เพื่อบอกว่าให้เริ่มนับจากเลขอะไร เหมาะกับรายการที่ต่อจากหน้าก่อน หรือแบ่งเป็นหลายช่วง
<ol start="5">
<li>Laravel</li>
<li>PHP</li>
<li>Tailwind</li>
<li>CSS</li>
<li>Javascript</li>
</ol>

ถ้าอยากนับถอยหลัง ใส่ reversed เพิ่มได้ (MDN)
4. <meter> แสดงระดับค่าโดยไม่ต้องเขียน JavaScript หรือ CSS
<meter> แสดงค่าที่วัดได้ในช่วงที่รู้ขอบเขต เช่นพื้นที่ดิสก์ที่ใช้ไป หรือคะแนนสอบ low กับ high แบ่งช่วงเป็นต่ำ กลาง สูง ส่วน optimum บอกว่าช่วงไหนคือค่าที่ดี แล้วเบราว์เซอร์จะเปลี่ยนสีแถบให้เอง (MDN)
<label for="value1">Low</label>
<meter id="value1" min="0" max="100" low="30" high="75" optimum="80" value="25"></meter>
<label for="value2">Medium</label>
<meter id="value2" min="0" max="100" low="30" high="75" optimum="80" value="50"></meter>
<label for="value3">High</label>
<meter id="value3" min="0" max="100" low="30" high="75" optimum="80" value="80"></meter>
body {
padding: 40px 20px;
}
label {
display: block;
margin-top: 15px;
}
meter {
width: 300px;
height: 20px;
}

ตัวอย่างนี้ตั้ง optimum ไว้ที่ 80 ซึ่งอยู่ในช่วงสูง ค่า 80 จึงเป็นสีเขียว ค่า 50 อยู่ช่วงกลางเป็นสีเหลือง และค่า 25 ต่ำกว่า low เป็นสีแดง ถ้าจะแสดงความคืบหน้าของงาน เช่นอัปโหลดไฟล์ ให้ใช้ <progress> แทน
5. <datalist> ทำช่องค้นหาที่มีตัวเลือกให้
ผูก <input list="…"> เข้ากับ <datalist id="…"> แล้วช่องกรอกจะมีรายการให้เลือกตอนพิมพ์ เหมาะกับฟอร์มที่มีค่าไม่มากและเรารู้ค่าที่น่าจะกรอกอยู่แล้ว
<div class="wrapper">
<h1>Native HTML Search</h1>
<input list="items">
<datalist id="items">
<option value="Laravel">
<option value="PHP">
<option value="Tailwind CSS">
<option value="CSS">
<option value="Javascript">
<option value="Alpine JS">
</datalist>
</div>
.wrapper {
padding-top: 30px;
text-align: center;
}
h1 {
font-weight: normal;
}
input {
padding: 10px;
font-size: 1.2em;
}

<datalist> เป็นแค่คำแนะนำ ผู้ใช้ยังพิมพ์ค่าอื่นที่ไม่อยู่ในรายการได้ ถ้าต้องบังคับให้เลือกจากรายการเท่านั้นให้ใช้ <select> และ Firefox บน Android ยังไม่แสดงรายการ (Can I use) ช่องกรอกจึงกลายเป็นช่องข้อความธรรมดา
6. <fieldset disabled> ปิดทุกช่องในกลุ่มทีเดียว
<fieldset> รวมช่องในฟอร์มเป็นกลุ่มเดียวกัน ใส่ disabled ที่ <fieldset> แล้วทุกช่องข้างในจะกดไม่ได้ ไม่ต้องไล่ใส่ทีละตัว
<form>
<fieldset disabled>
<legend>ที่อยู่จัดส่ง</legend>
<input type="text" name="address">
<select name="province">
<option>กรุงเทพมหานคร</option>
<option>เชียงใหม่</option>
</select>
<textarea name="note"></textarea>
<label><input type="checkbox" name="gift"> ห่อของขวัญ</label>
</fieldset>
</form>
ช่องที่ disabled จะไม่ส่งค่าไปกับฟอร์ม (MDN) ถ้ายังอยากให้ค่าส่งไปด้วยแต่ห้ามแก้ ใส่ readonly ที่ <input> แทน ส่วนช่องที่อยู่ใน <legend> จะไม่โดนปิดไปด้วย
7. target="_blank" ไม่ต้องใส่ rel="noopener" เองแล้ว
เดิมหน้าที่เปิดจากลิงก์ target="_blank" เข้าถึงหน้าเราได้ผ่าน window.opener เว็บปลายทางจึงสั่งเปลี่ยนหน้าเดิมของเราไปเป็นหน้าหลอกได้ เราเลยต้องใส่ rel="noopener" กันไว้ทุกลิงก์
ตอนนี้เบราว์เซอร์ทำให้ target="_blank" ทำงานเหมือนใส่ rel="noopener" ให้เองแล้ว (MDN) ตั้งแต่ Chrome 88, Firefox 79 และ Safari 12.1 (Can I use) ใส่ไว้ก็ไม่เสียหาย แต่ไม่ต้องไล่เติมในโค้ดเก่า
<a href="https://phattarachai.dev/" target="_blank" rel="noreferrer">
phattarachai.dev (เปิดในแท็บใหม่)
</a>
ถ้าไม่อยากให้เว็บปลายทางรู้ว่าผู้ใช้มาจากหน้าไหน ใส่ rel="noreferrer" ซึ่งรวมผลของ noopener ไว้ด้วย (MDN) และบอกผู้ใช้ในข้อความลิงก์ว่าจะเปิดแท็บใหม่
8. <details name> ทำ accordion ที่เปิดได้ทีละอัน
<details> กับ <summary> ทำกล่องที่กดเปิดปิดได้อยู่แล้ว ถ้าใส่ name เดียวกันให้หลายกล่อง เปิดกล่องหนึ่งแล้วกล่องอื่นในกลุ่มจะปิดเอง ได้ accordion แบบหน้า FAQ โดยไม่ต้องเขียน JavaScript (MDN)
<details name="faq" open>
<summary>จัดส่งกี่วัน</summary>
<p>กรุงเทพฯ 1-2 วัน ต่างจังหวัด 2-3 วัน</p>
</details>
<details name="faq">
<summary>ชำระเงินทางไหนได้บ้าง</summary>
<p>โอนผ่านธนาคาร หรือสแกน QR พร้อมเพย์</p>
</details>
<details name="faq">
<summary>เปลี่ยนสินค้าได้ไหม</summary>
<p>เปลี่ยนได้ภายใน 7 วันหลังได้รับของ</p>
</details>
name ใช้ได้ตั้งแต่ Chrome 120, Firefox 130 และ Safari 17.2 (Can I use) เบราว์เซอร์รุ่นเก่ากว่านั้นก็ยังเปิดปิดได้ตามปกติ แค่เปิดพร้อมกันได้หลายกล่อง
9. <mark> ไฮไลต์ข้อความ
ใช้ <mark> ครอบข้อความที่อยากเน้น เบราว์เซอร์จะแสดงเป็นพื้นสีเหลือง
<p>ตัวอย่างข้อความที่ต้องการ<mark>ไฮไลต์</mark>บน HTML</p>
ตัวอย่างหน้าตาด้านล่างใช้ปากกาไฮไลต์ของเว็บนี้แทน <mark> จริง
ตัวอย่างข้อความที่ต้องการไฮไลต์บน HTML
10. download ให้ลิงก์ดาวน์โหลดไฟล์แทนเปิดดู
ใส่ download ใน <a> เพื่อบอกเบราว์เซอร์ให้ดาวน์โหลดไฟล์ แทนที่จะเปิดไฟล์ขึ้นมาดู ใส่ชื่อไฟล์เป็นค่าของ download ได้ด้วย
<a href="/files/report-2569.pdf" download="รายงานประจำปี.pdf">
ดาวน์โหลดรายงาน
</a>
download ใช้ได้เฉพาะไฟล์ที่อยู่โดเมนเดียวกับหน้าเว็บ หรือ URL แบบ blob: กับ data: (MDN) ถ้าไฟล์อยู่ที่อื่น เช่นบน S3 ใน Laravel ให้ส่งไฟล์ผ่าน route ของเราด้วย Storage::download() แทน และถ้า server ส่ง header Content-Disposition ที่มีชื่อไฟล์มา เบราว์เซอร์จะใช้ชื่อนั้นแทนชื่อใน download




