CSS
Transitions & Animations
transform
transform ใช้เปลี่ยนลักษณะการแสดงผลของ element — ขยับ (translate), ขยาย/ย่อ (scale), หมุน (rotate) — โดยไม่กระทบ layout ของ element อื่นรอบข้าง
หัวข้อนี้คืออะไร
transform คือ CSS property ที่ใช้เปลี่ยนลักษณะการแสดงผลของ element โดยไม่แตะ layout จริง สิ่งที่ทำได้หลักๆ มี 3 แบบ: translate() — ขยับตำแหน่งเชิงภาพ เช่น ขยับขึ้น ขยับขวา scale() — ขยายหรือย่อขนาด เช่น ขยายเป็น 1.1 เท่า หรือย่อเป็น 0.8 เท่า rotate() — หมุน element เช่น หมุน 45 องศา สิ่งสำคัญที่ต้องเข้าใจทันที: transform ส่งผลต่อการแสดงผลเท่านั้น — element ที่ถูก translate ยังคงกินพื้นที่ใน layout ที่ตำแหน่งเดิม element อื่นข้างๆ จะไม่ขยับตาม ต่างจากการเปลี่ยน margin หรือ top/left
- translate() — ขยับตำแหน่งเชิงภาพ เช่น translateX(20px) ขยับขวา 20px, translateY(-10px) ขยับขึ้น 10px
- scale() — ขยาย/ย่อขนาด เช่น scale(1.1) ขยาย 10%, scale(0.8) ย่อเหลือ 80%
- rotate() — หมุน เช่น rotate(45deg) หมุนตามเข็ม 45 องศา, rotate(-90deg) หมุนทวนเข็ม 90 องศา
- ใช้หลาย function ร่วมกันได้ เช่น transform: translateY(-4px) scale(1.02)
ทำไมหัวข้อนี้สำคัญ
transform เป็นเครื่องมือหลักในการสร้าง UI effect ที่ดูมีคุณภาพ เพราะ: ไม่กระทบ layout — การ้ใช้ transform แทน margin หรือ top/left ทำให้ element รอบข้างไม่ขยับ ไม่เกิด reflow ของหน้าเพจ ประสิทธิภาพสูง — browser สามารถ animate transform บน GPU ได้ ทำให้ลื่นกว่าการ animate ค่า layout อย่าง width, height, margin ใช้ร่วมกับ transition ได้ดีมาก — transform + transition คือคู่ที่พบบ่อยที่สุดใน UI interaction เช่น ปุ่มที่ขยายเมื่อ hover, การ์ดที่ยกขึ้นเมื่อชี้ ผลลัพธ์ที่เห็นใน UI จริง: ปุ่มที่ขยายเล็กน้อยเมื่อ hover — scale(1.05) การ์ดที่ลอยขึ้นเมื่อชี้ — translateY(-4px) ไอคอนที่หมุนเมื่อกด — rotate(180deg) บน dropdown arrow
ตัวอย่างจากชีวิตจริง
ลองนึกถึงกระจกขยาย: ตัวกระจกยังอยู่ที่เดิม — แต่ภาพที่เห็นผ่านกระจกดูขยายใหญ่ขึ้น นั่นคือ scale() บน element ไม่ได้ทำให้ element จริงใหญ่ขึ้น แค่ภาพที่เห็นใหญ่ขึ้น หรือนึกถึงหนังสือที่วางบนโต๊ะ: ถ้าเราเลื่อนหนังสือออกไปขวา 20px (translate) พื้นที่ที่หนังสือเคยนอนอยู่ก็ยังถูกจอง เพราะ layout ไม่ได้เปลี่ยน บน UI จริง: Tooltip ที่ค่อยๆ เลื่อนขึ้นมาเมื่อปรากฏ — translateY(-8px) ไอคอน chevron ที่หมุน 180° เมื่อ accordion เปิด — rotate(180deg) thumbnail รูปที่ขยายนิดๆ เมื่อ hover — scale(1.05) ปุ่มที่ "กด" ลงเล็กน้อยเมื่อ active — scale(0.97)
แนวคิดหลักที่ต้องเข้าใจ
translate, scale, rotate แต่ละแบบทำงานอย่างไร — hover ที่แต่ละ box เพื่อดูผล:
| Function | ตัวอย่าง | ความหมาย |
|---|---|---|
| translateX(n) | translateX(20px) | ขยับแนวนอน ค่าบวก = ขวา, ค่าลบ = ซ้าย |
| translateY(n) | translateY(-8px) | ขยับแนวตั้ง ค่าลบ = ขึ้น, ค่าบวก = ลง |
| translate(x, y) | translate(10px, -4px) | ขยับทั้งแนวนอนและแนวตั้งพร้อมกัน |
| scale(n) | scale(1.1) | ขยาย/ย่อเท่ากันทุกทิศทาง เช่น 1.1 = ขยาย 10% |
| scaleX(n) / scaleY(n) | scaleX(1.5) | ขยาย/ย่อเฉพาะแนวนอนหรือแนวตั้ง |
| rotate(deg) | rotate(45deg) | หมุนตามเข็มนาฬิกา ค่าลบ = ทวนเข็ม |
การทำงานทีละขั้นตอน
วิธีคิดเมื่อต้องการใช้ transform กับ hover effect:
- 1. ถามว่าต้องการทำอะไร — ขยับ? ใช้ translate / ขยาย? ใช้ scale / หมุน? ใช้ rotate
- 2. เพิ่ม transition บน element ก่อน — เช่น transition: transform 0.25s ease เพื่อให้ effect ลื่นไหล (วางบน element ปกติ ไม่ใช่บน :hover)
- 3. กำหนด transform บน :hover — เช่น .btn:hover { transform: scale(1.05); }
- 4. ถ้าต้องการ effect หลายแบบพร้อมกัน — เขียนใน property เดียว เช่น transform: translateY(-4px) scale(1.02)
- 5. ระวัง transform-origin — จุดหมุนหรือจุดขยายเริ่มต้นอยู่ที่ center (50% 50%) สามารถเปลี่ยนได้ด้วย transform-origin
ตัวอย่างเชิงเทคนิค — transform ร่วมกับ transition
transform มักใช้คู่กับ transition เพื่อสร้าง hover effect ที่ดูลื่นไหล — ลองแก้โค้ดและ hover เพื่อดูผล:
จุดที่ผู้เริ่มต้นมักสับสน
- transform ไม่เปลี่ยน layout — element ที่ translate ไปทางขวา 50px ยังกินพื้นที่ใน layout ที่ตำแหน่งเดิม element ข้างๆ จะไม่ขยับตาม ต่างจาก margin-left: 50px
- เขียน transform หลายค่าต้องอยู่ใน property เดียว — ถ้าเขียน transform: scale(1.1); แล้วตามด้วย transform: rotate(45deg); ค่าหลังจะทับค่าแรก ต้องเขียน transform: scale(1.1) rotate(45deg); รวมกัน
- ลำดับของ transform function มีผล — transform: rotate(45deg) translateX(100px) ให้ผลต่างจาก transform: translateX(100px) rotate(45deg) เพราะแกนหมุนเปลี่ยน
- transform-origin กำหนดจุดอ้างอิง — ค่าเริ่มต้นคือ center (50% 50%) ถ้า rotate แล้วหมุนไม่ตรงจุดที่ต้องการ ให้ตรวจ transform-origin ก่อน
เปรียบเทียบ transform กับการเปลี่ยน layout โดยตรง
เมื่อต้องการขยับ element ทำไมถึงใช้ transform แทน margin หรือ position?
| วิธี | กระทบ layout? | animate ได้ลื่น? | เหมาะกับ |
|---|---|---|---|
| transform: translateX() | ไม่ (visual only) | ใช่ (GPU) | hover effect, motion, interaction |
| margin-left / margin-top | ใช่ (reflow) | ได้แต่ช้ากว่า | spacing ถาวร ไม่ใช่ animation |
| position + top/left | ใช่ (positioned element) | ได้แต่ช้ากว่า | absolute positioning ถาวร |
| transform: scale() | ไม่ (visual only) | ใช่ (GPU) | hover enlarge, emphasis |
| width / height | ใช่ (reflow) | ช้า, เกิด reflow | ขนาดจริงที่ต้องการเปลี่ยน |
สรุปท้ายบทแบบจำง่าย
transform = "เปลี่ยนลักษณะที่เห็น โดยไม่แตะ layout" 3 function หลัก:
- translate() — ขยับตำแหน่งเชิงภาพ เช่น translateY(-4px) ยกขึ้นเล็กน้อย
- scale() — ขยาย/ย่อ เช่น scale(1.05) ขยาย 5% เมื่อ hover
- rotate() — หมุน เช่น rotate(180deg) พลิกไอคอน arrow
- ใช้คู่กับ transition เสมอ — transition: transform 0.25s ease ทำให้ effect ลื่นไหล
- รวมหลาย function ได้ในบรรทัดเดียว เช่น transform: translateY(-4px) scale(1.02)
Lab 1 — ขยับ element ด้วย translate
โจทย์: .box ด้านล่างยังไม่มีการขยับเมื่อ hover เพิ่ม transition และ transform ให้ .box ขยับขึ้น 20px เมื่อ hover: - เพิ่ม transition: transform 0.3s ease; บน .box - เพิ่ม transform: translateY(-20px); บน .box:hover
Lab 2 — ขยายและหมุน element
โจทย์: .icon เป็นวงกลมที่มีไอคอน ▼ อยู่ข้างใน เพิ่ม effect ให้ .icon เมื่อ hover: - ขยายเป็น 1.15 เท่า (scale) - หมุน 180 องศา (rotate) - มี transition ที่นุ่มนวล
Lab 3 — รวม transform หลายแบบเข้าด้วยกัน
โจทย์: .card ด้านล่างต้องการ hover effect ที่รวม 2 อย่างพร้อมกัน: 1. ยกขึ้น 8px (translateY) 2. ขยาย 2% (scale) พร้อมกับมี transition ที่ smooth — เขียน transform ทั้ง 2 แบบในบรรทัดเดียว