แอนิเมชันเปิดและปิดโมดัล
ทำให้การปรากฏและหายไปของโมดัลเคลื่อนไหวด้วยยูทิลิตีการเปลี่ยนผ่านของ Tailwind ร่วมกับการสลับคลาสด้วย JavaScript เพื่อประสบการณ์ผู้ใช้ที่ราบรื่น
แอนิเมชันเปิดและปิดโมดัล เป็นบทเรียน Tailwind CSS Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Tailwind CSS Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Tailwind CSS Academy มีบทเรียนทั้งหมด 4 บทเรียน
เหตุใดจึงควรสร้างภาพเคลื่อนไหวให้ modal
การทำให้โมดัลมีแอนิเมชันตอนเปิดและปิดมีประโยชน์ด้านการใช้งานมากกว่าความสวยงามเพียงอย่างเดียว การปรากฏขึ้นอย่างฉับพลันอาจทำให้ผู้ใช้ตกใจ การค่อย ๆ จางเข้ามาอย่างนุ่มนวลช่วยให้ผู้ใช้เข้าใจบริบทของการปรากฏโมดัลและที่มาของโมดัลได้ดีขึ้น ส่วนแอนิเมชันตอนปิดจะสื่อว่าการโต้ตอบเสร็จสิ้นแล้ว และผู้ใช้กำลังกลับไปยังหน้าเดิม
เครื่องมือช่วยทำทรานซิชัน ของเทลวินด์ช่วยให้การทำให้ความทึบและขนาดเคลื่อนไหวไปพร้อมกันเป็นเรื่องง่าย ทำให้เกิดเอฟเฟกต์จางเข้าและปรับขนาดที่ดูประณีต สอดคล้องกับรูปแบบส่วนติดต่อผู้ใช้บนอุปกรณ์เคลื่อนที่แบบเนทีฟ
แอนิเมชันพื้นหลังจางเข้า
พื้นหลังควร ค่อย ๆ จางเข้า เมื่อโมดัลเปิด และ ค่อย ๆ จางออก เมื่อโมดัลปิด เพิ่ม transition-opacity duration-300 ให้กับองค์ประกอบพื้นหลัง จากนั้นสลับ opacity-0 (ซ่อนอยู่) และ opacity-100 (มองเห็นได้) ด้วย JavaScript
พื้นหลังต้องคงอยู่ใน DOM (ไม่ใช้ hidden) เพื่อให้การจางทำงานได้ โดยเริ่มต้นด้วย opacity-0 pointer-events-none แล้วสลับเป็น opacity-100 pointer-events-auto
<!-- Backdrop with fade -->
<div
id="backdrop"
onclick="closeModal()"
class="fixed inset-0 bg-black/50 z-40
transition-opacity duration-300
opacity-0 pointer-events-none">
</div>
<script>
function openModal() {
document.getElementById('backdrop').classList.remove('opacity-0', 'pointer-events-none');
document.getElementById('backdrop').classList.add('opacity-100', 'pointer-events-auto');
}
function closeModal() {
document.getElementById('backdrop').classList.remove('opacity-100', 'pointer-events-auto');
document.getElementById('backdrop').classList.add('opacity-0', 'pointer-events-none');
}
</script>การปรากฏของไดอะล็อกด้วยการขยายและจางเข้า
แอนิเมชันตอนเปิดโมดัลที่ใช้กันมากที่สุดคือ การขยายพร้อมการจางเข้า โดยเริ่มจากไดอะล็อกที่มีขนาดเล็กลงเล็กน้อยและโปร่งใส จากนั้นขยายจนเต็มขนาดพร้อมกับเปลี่ยนเป็นทึบ ลักษณะนี้เลียนแบบการปรากฏของโมดัลใน iOS และแอนดรอยด์
เพิ่ม transition-all duration-300 ให้กับแผงไดอะล็อก สลับจาก scale-95 opacity-0 (สถานะซ่อนเริ่มต้น) เป็น scale-100 opacity-100 (สถานะที่มองเห็นได้) ระยะเวลา 300 มิลลิวินาทีที่สั้นช่วยให้แอนิเมชันฉับไว
<!-- Dialog panel -->
<div
id="dialog"
class="bg-white rounded-2xl shadow-2xl w-full max-w-md
transition-all duration-300
scale-95 opacity-0 pointer-events-none">
<!-- content -->
</div>
<script>
function openModal() {
const d = document.getElementById('dialog');
d.classList.remove('scale-95', 'opacity-0', 'pointer-events-none');
d.classList.add('scale-100', 'opacity-100', 'pointer-events-auto');
}
function closeModal() {
const d = document.getElementById('dialog');
d.classList.remove('scale-100', 'opacity-100', 'pointer-events-auto');
d.classList.add('scale-95', 'opacity-0', 'pointer-events-none');
}
</script>แอนิเมชันเลื่อนขึ้นสำหรับชีตบนอุปกรณ์เคลื่อนที่
บนอุปกรณ์เคลื่อนที่ ชีตด้านล่างจะเลื่อนขึ้นจากด้านล่างของหน้าจอ แทนที่จะปรากฏตรงกลาง วิธีนี้ใช้งานได้สะดวกกว่าสำหรับการควบคุมด้วยนิ้วโป้ง ใช้ fixed bottom-0 inset-x-0 เพื่อยึดแผงไว้ด้านล่าง และใช้ translate-y-full เป็นสถานะซ่อนเริ่มต้น จากนั้นสลับเป็น translate-y-0
เพิ่มที่จับสำหรับลาก (w-10 h-1 rounded-full bg-gray-300 mx-auto mt-3) ไว้ด้านบน เพื่อบอกผู้ใช้ว่าสามารถปัดได้
<div
id="sheet"
class="fixed bottom-0 inset-x-0 z-50 bg-white rounded-t-2xl shadow-2xl
transition-transform duration-300 ease-out
translate-y-full">
<!-- Drag handle -->
<div class="w-10 h-1 rounded-full bg-gray-300 mx-auto mt-3"></div>
<div class="px-6 py-5">
<h2 class="text-lg font-semibold text-gray-900">Share</h2>
<p class="mt-2 text-sm text-gray-600">Choose how you want to share this item.</p>
</div>
<div class="flex justify-end gap-3 px-6 pb-6">
<button onclick="closeSheet()" class="px-4 py-2 text-sm font-semibold border border-gray-300 rounded-lg">Cancel</button>
<button class="px-4 py-2 text-sm font-semibold text-white bg-blue-600 rounded-lg">Share</button>
</div>
</div>ฟังก์ชันการผ่อนจังหวะสำหรับแอนิเมชันที่ลื่นไหล
ฟังก์ชันจับเวลากำหนดว่าแอนิเมชันจะเร่งและช้าลงอย่างไร เทลวินด์มีเครื่องมือช่วยกำหนดการผ่อนจังหวะสี่แบบ ได้แก่ ease-linear, ease-in, ease-out และ ease-in-out
สำหรับการปรากฏของโมดัล ให้ใช้ ease-out — องค์ประกอบจะเริ่มต้นอย่างรวดเร็ว แล้วช้าลงเมื่อเข้าใกล้ตำแหน่งสุดท้าย ทำให้รู้สึกเป็นธรรมชาติและน่าพึงพอใจ สำหรับการปิด ให้ใช้ ease-in — องค์ประกอบจะเร่งความเร็วขณะเคลื่อนออก ทำให้รู้สึกว่าการปิดมีจุดประสงค์ ส่วน ease-in-out เหมาะกับทรานซิชันที่ย้อนกลับได้ เช่น การสลับสถานะ
<!-- Entrance: fast start, slow end -->
<div class="transition-all duration-300 ease-out
scale-95 opacity-0">
Modal entering
</div>
<!-- Exit: slow start, fast end -->
<div class="transition-all duration-200 ease-in
scale-95 opacity-0">
Modal exiting
</div>รอให้แอนิเมชันตอนปิดทำงานเสร็จ
ข้อผิดพลาดที่พบบ่อยคือการนำโมดัลออกจาก DOM (หรือซ่อนด้วย hidden) ทันทีที่เริ่มสั่งปิด การทำเช่นนี้จะตัดแอนิเมชันตอนปิดออก ให้รอจนแอนิเมชันทำงานเสร็จโดยใช้อีเวนต์ transitionend ก่อนซ่อนองค์ประกอบแทน
รับฟังอีเวนต์ด้วย { once: true } เพื่อให้ตัวจัดการทำงานเพียงครั้งเดียวต่อทรานซิชัน และไม่ถูกสะสมซ้ำ หลังจากทรานซิชันเสร็จ ให้เพิ่ม hidden หรือ pointer-events-none เพื่อป้องกันไม่ให้ผู้ใช้โต้ตอบกับองค์ประกอบที่มองไม่เห็น
<script>
function closeModal() {
const dialog = document.getElementById('dialog');
const backdrop = document.getElementById('backdrop');
// Start exit animation
dialog.classList.remove('scale-100', 'opacity-100');
dialog.classList.add('scale-95', 'opacity-0');
backdrop.classList.remove('opacity-100');
backdrop.classList.add('opacity-0');
// Wait for animation to finish, then hide
dialog.addEventListener('transitionend', () => {
dialog.classList.add('pointer-events-none');
backdrop.classList.add('pointer-events-none');
document.body.classList.remove('overflow-hidden');
}, { once: true });
}
</script>แอนิเมชันต่อเนื่องของพื้นหลังและไดอะล็อก
การเปิดทั้งพื้นหลังและไดอะล็อกในเวลาเดียวกันพอดีอาจให้ความรู้สึกฉับพลันเกินไป แอนิเมชันต่อเนื่องจะเปิดพื้นหลังก่อน แล้วจึงเปิดไดอะล็อกหลังจากนั้นเสี้ยววินาที ทำให้เกิดเอฟเฟกต์การเปิดเผยเป็นชั้น ๆ
ทำได้โดยเพิ่มคลาส delay-100 ให้กับองค์ประกอบไดอะล็อก เพื่อให้ทรานซิชันเริ่มหลังพื้นหลัง 100 มิลลิวินาที เมื่อลำดับการปิดเริ่มขึ้น ให้ลบการหน่วงเวลาออกเพื่อให้ปิดได้รวดเร็ว
<!-- Backdrop: starts immediately -->
<div id="backdrop"
class="fixed inset-0 bg-black/50 z-40
transition-opacity duration-300
opacity-0 pointer-events-none">
</div>
<!-- Dialog: starts 100ms after backdrop -->
<div id="dialog"
class="bg-white rounded-2xl shadow-2xl w-full max-w-md
transition-all duration-300 delay-100
scale-90 opacity-0 pointer-events-none">
<!-- content -->
</div>
<!-- On open: add opacity-100 to backdrop, then scale-100/opacity-100 to dialog (delay-100 handles the stagger) -->
<!-- On close: remove delay-100 from dialog before starting the exit --></i>โมดัลแจ้งเตือนแบบซูมเข้า
สำหรับการแจ้งเตือนสำคัญ (ข้อผิดพลาดและการยืนยันการทำลายข้อมูล) เอฟเฟกต์ ซูมเข้าดึงดูดความสนใจได้มากกว่าการขยายอย่างนุ่มนวล เริ่มไดอะล็อกที่ scale-50 แล้วทำแอนิเมชันไปที่ scale-100 ด้วย duration-150 ที่รวดเร็ว เพื่อให้เกิดการปรากฏแบบเด้งขึ้นอย่างฉับไวและสะดุดตา
ควรใช้เทคนิคนี้อย่างพอเหมาะ — การใช้แอนิเมชันที่หวือหวาเกินไปจะทำให้ผู้ใช้ชินชา ควรสงวนการซูมเข้าไว้สำหรับข้อความแจ้งเตือนที่สำคัญจริง ๆ ซึ่งต้องการความสนใจจากผู้ใช้อย่างเต็มที่
<!-- Zoom-in alert -->
<div
id="alert-dialog"
class="bg-white rounded-2xl shadow-2xl w-full max-w-sm
transition-all duration-150 ease-out
scale-50 opacity-0">
<div class="p-6 text-center">
<div class="mx-auto w-14 h-14 rounded-full bg-red-100 flex items-center justify-center">
<svg class="w-7 h-7 text-red-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"/>
</svg>
</div>
<h2 class="mt-4 text-lg font-bold text-gray-900">Critical Error</h2>
<p class="mt-2 text-sm text-gray-500">Your session has expired. Please log in again.</p>
<button class="mt-5 w-full py-2.5 bg-blue-600 text-white font-semibold rounded-lg">Sign In Again</button>
</div>
</div>การทำแอนิเมชันด้วยคลาส CSS เทียบกับสไตล์แบบอินไลน์
การทำแอนิเมชันโมดัลในเทลวินด์มีสองแนวทาง ได้แก่ การสลับคลาส (ที่เรากำลังใช้อยู่) และ การปรับแต่งสไตล์แบบอินไลน์ด้วย JavaScript การสลับคลาสเป็นแนวทางของเทลวินด์ เพราะช่วยแยกสไตล์ในคลาส HTML ออกจากพฤติกรรมใน JavaScript ได้อย่างเป็นระเบียบ
การปรับแต่งสไตล์แบบอินไลน์ (element.style.opacity = '0') ทำลายแนวทางที่เน้นเครื่องมือช่วยเป็นหลัก และทำให้ตรวจสอบสไตล์ได้ยากขึ้น ควรใช้การสลับคลาส เว้นแต่จำเป็นต้องใช้ค่าที่เปลี่ยนแปลงแบบไดนามิกและไม่สามารถกำหนดไว้ล่วงหน้าได้ เช่น ตำแหน่งที่ทำแอนิเมชันตามพิกัดการโต้ตอบของผู้ใช้
// Class toggling (Tailwind approach) — preferred
function openModal() {
dialog.classList.remove('scale-95', 'opacity-0');
dialog.classList.add('scale-100', 'opacity-100');
}
// Inline style approach — avoid unless necessary
function openModalInline() {
dialog.style.transform = 'scale(1)';
dialog.style.opacity = '1';
// Hard to maintain, not visible in HTML
}เคารพการตั้งค่าลดการเคลื่อนไหว
ผู้ใช้บางรายมีอาการเมารถหรือเวียนศีรษะจากแอนิเมชันของส่วนติดต่อผู้ใช้ CSS และเทลวินด์ต่างรองรับคิวรีสื่อ prefers-reduced-motion ให้ใช้ motion-reduce:transition-none และ motion-reduce:transform-none กับองค์ประกอบที่มีแอนิเมชัน เพื่อปิดทรานซิชันสำหรับผู้ใช้ที่ขอให้ลดการเคลื่อนไหวในการตั้งค่า OS
นี่เป็นข้อกำหนดด้านการเข้าถึงที่มักถูกมองข้าม การเพิ่มเครื่องมือช่วยเหล่านี้ทำให้มั่นใจได้ว่าโมดัลที่มีแอนิเมชันจะไม่ทำให้ผู้ใช้รู้สึกไม่สบายหรือกระตุ้นปัญหาความไวต่อการเคลื่อนไหว
<div
id="dialog"
class="bg-white rounded-2xl shadow-2xl w-full max-w-md
transition-all duration-300 ease-out
motion-reduce:transition-none
scale-95 opacity-0">
<!-- dialog content -->
</div>แอนิเมชันการแจ้งเตือนแบบโทสต์
การแจ้งเตือนแบบโทสต์คือข้อความชั่วคราวที่ไม่ขัดขวางการใช้งาน และเลื่อนเข้ามาจากมุมด้านบนหรือด้านล่างของหน้าจอ ใช้ fixed bottom-4 right-4 z-50 สำหรับกำหนดตำแหน่ง และเริ่มแอนิเมชันด้วย translate-y-2 opacity-0 จากนั้นเปลี่ยนเป็น translate-y-0 opacity-100
ให้โทสต์ปิดตัวเองโดยอัตโนมัติหลังจากผ่านไปไม่กี่วินาทีด้วย setTimeout เครื่องมือช่วย transition-all duration-300 ของเทลวินด์จะจัดการทั้งการปรากฏและการจางออกตอนปิดโดยอัตโนมัติได้อย่างลื่นไหล
<!-- Toast element -->
<div
id="toast"
class="fixed bottom-4 right-4 z-50
flex items-center gap-3 px-4 py-3 bg-gray-900 text-white text-sm rounded-xl shadow-xl
transition-all duration-300
translate-y-2 opacity-0 pointer-events-none">
<svg class="w-4 h-4 text-green-400" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/>
</svg>
Changes saved successfully!
</div>
<script>
function showToast() {
const t = document.getElementById('toast');
t.classList.remove('translate-y-2', 'opacity-0', 'pointer-events-none');
t.classList.add('translate-y-0', 'opacity-100');
setTimeout(() => {
t.classList.remove('translate-y-0', 'opacity-100');
t.classList.add('translate-y-2', 'opacity-0', 'pointer-events-none');
}, 3000);
}
</script>ตรวจสอบความเข้าใจอย่างรวดเร็ว
ทดสอบความเข้าใจแนวคิดการใช้ CSS ของเทลวินด์จากบทเรียนนี้
ทบทวนบทเรียน
ในบทเรียนนี้ คุณได้เรียนรู้ว่า แอนิเมชันโมดัลทำงานโดยสลับคลาสเครื่องมือช่วยกำหนดความทึบและขนาด (scale-95 opacity-0 เป็น scale-100 opacity-100) ร่วมกับ transition-all duration-300; แอนิเมชันตอนปิดต้องรอ transitionend ก่อนซ่อนองค์ประกอบ และ การรองรับการเข้าถึงสำหรับการเคลื่อนไหวจัดการด้วย motion-reduce:transition-none เพื่อเคารพการตั้งค่า prefers-reduced-motion ของ OS ต่อไป เราจะสร้างเมนูแบบเลื่อนลง
เรียนรู้ HTML ด้วย AI tutor — ฟรี
เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป
- คอร์ส
- 30
- บทเรียน
- 120
คำถามที่พบบ่อย
บทเรียน “แอนิเมชันเปิดและปิดโมดัล” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “แอนิเมชันเปิดและปิดโมดัล” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Tailwind CSS Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Tailwind CSS Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “แอนิเมชันเปิดและปิดโมดัล”
ทำให้การปรากฏและหายไปของโมดัลเคลื่อนไหวด้วยยูทิลิตีการเปลี่ยนผ่านของ Tailwind ร่วมกับการสลับคลาสด้วย JavaScript เพื่อประสบการณ์ผู้ใช้ที่ราบรื่น คุณปฏิบัติ Tailwind CSS Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Tailwind CSS Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Tailwind CSS Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน
บทเรียน “แอนิเมชันเปิดและปิดโมดัล” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Tailwind CSS Academy นี้ได้ไหม
ได้ บทเรียน Tailwind CSS Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- โครงสร้างกล่องโต้ตอบโมดัล
- แอนิเมชันเปิดและปิดโมดัล
- องค์ประกอบเมนูแบบเลื่อนลง
- โมดัลและเมนูแบบเลื่อนลงที่เข้าถึงได้