เทคนิคการทำ Glassmorphism (เอฟเฟกต์กระจกฝ้าโปร่งแสง) ใน CSS ให้ดูสมจริง มีมิติ และมีประสิทธิภาพสูง ต้องอาศัยการผสมผสานคุณสมบัติหลัก 4 อย่างเข้าด้วยกัน ได้แก่ การเบลอฉากหลัง (Backdrop Blur), ความโปร่งใสของสี (Translucency), แสงสะท้อนขอบ (Specular Edge Highlight), และมิติความลึก (Layered Depth)
โค้ดพื้นฐาน (Core Anatomy)
CSS
.glass-panel {
/* 1. Backdrop Filter: หัวใจสำคัญของเอฟเฟกต์กระจกฝ้า */
backdrop-filter: blur(16px) saturate(180%);
-webkit-backdrop-filter: blur(16px) saturate(180%); /* รองรับ Safari */
/* 2. Semi-transparent Base: สีพื้นโปร่งแสง */
background: rgba(255, 255, 255, 0.15);
/* 3. Rim Lighting: เส้นขอบสะท้อนแสงทิศทางเดียว */
border: 1px solid rgba(255, 255, 255, 0.25);
border-radius: 16px;
/* 4. Multi-layered Shadows: เงามืดและแสงฟุ้งรอบตัว */
box-shadow:
0 8px 32px 0 rgba(0, 0, 0, 0.18),
inset 0 1px 1px 0 rgba(255, 255, 255, 0.3);
}
เทคนิคขั้นสูงเพื่อความสมจริง (Hyper-Realistic Details)
จำลองแสงตกกระทบด้วย Directional Border (Fresnel Effect)
กระจกจริงแสงจะตกกระทบขอบด้านบนมากกว่าขอบด้านล่าง การใช้ border: 1px solid สีเดียวกันทุกด้านจะทำให้ดูแบน การใช้ border-image แบบ Linear Gradient ช่วยจำลองแสงตกกระทบได้ดีขึ้น
CSS
.glass-realistic-border {
border: 1px solid transparent;
background-clip: padding-box, border-box;
background-origin: padding-box, border-box;
background-image:
linear-gradient(to bottom right, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0.05)),
linear-gradient(to bottom right, rgba(255, 255, 255, 0.6), rgba(255, 255, 255, 0.0));
}
เพิ่มความสดของสีฉากหลังด้วย saturate()
เมื่อใช้ blur() พิกเซลสีด้านหลังจะเกลี่ยเข้าหากันจนดูหม่น การใส่ saturate(180%) ควบคู่ไปกับ blur() จะดึงความสดของสีข้างหลังขึ้นมา ทำให้กระจกดูมีชีวิตชีวาแบบเดียวกับ Fluent Design ของ Windows หรือ macOS
ใส่พื้นผิวกระจกขรุขระ (Frosted Noise Texture)
กระจกฝ้าของจริงจะมี Grain เล็กๆ สามารถใช้ SVG Noise เป็น Overlay ช่วยลดปัญหา Color Banding บนหน้าจอทั่วไป
CSS
.glass-textured {
position: relative;
}
.glass-textured::before {
content: "";
position: absolute;
inset: 0;
border-radius: inherit;
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)' opacity='0.04'/%3E%3C/svg%3E");
pointer-events: none;
}
การรองรับ Fallback & Performance
การตรวจสอบเบราว์เซอร์ที่ไม่รองรับ (@supports)
บางสภาพแวดล้อมหรือเบราว์เซอร์รุ่นเก่าอาจไม่รองรับ backdrop-filter ต้องเตรียมสีทึบไว้สำรองเสมอเพื่อให้อ่านเนื้อหาออก
.glass-panel {
/* Fallback สำหรับเบราว์เซอร์ที่ไม่รองรับ */
background: rgba(30, 30, 35, 0.85);
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
.glass-panel {
background: rgba(255, 255, 255, 0.15);
backdrop-filter: blur(16px) saturate(180%);
-webkit-backdrop-filter: blur(16px) saturate(180%);
}
}
ประสิทธิภาพและการเรนเดอร์ (GPU Rendering)
- หลีกเลี่ยงการเคลื่อนไหว (Animate) ตัว
backdrop-filterโดยตรง
การทำ Transition ค่าblur()จะบังคับให้ GPU คำนวณเบลอแบบ Real-time ทุกเฟรม ส่งผลให้เฟรมเรตร่วง (Jank) รุนแรง - ทางแก้
ให้ใช้opacityบน Layer ซ้อน หรือใช้การเคลื่อนไหวเฉพาะtransformแทน - แยก Compositing Layer
หากการ์ดมีแอนิเมชัน ให้ใส่will-change: transform;เพื่อยกองค์ประกอบขึ้นไปรันบนเลเยอร์ GPU แยกต่างหาก
Accessibility (A11y) & การจัดวาง
- Contrast Ratio (เกณฑ์ WCAG 2.2)
จุดอ่อนที่สุดของ Glassmorphism คือการอ่านข้อความ (Readability) หากฉากหลังเปลี่ยนตำแหน่ง เลื่อนได้ หรือมีรูปภาพที่สว่างสลับมืด ข้อความอาจจมหาย- แก้โดยใช้ Text Shadow แบบละเอียด:
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.4); - หรือจำกัดสีพื้นหลังของกระจกให้มี Alpha ไม่ต่ำกว่า
0.2ถึง0.3
- แก้โดยใช้ Text Shadow แบบละเอียด:
- User Preferences (
prefers-reduced-transparency)
รองรับผู้ใช้ที่ตั้งค่าลดความโปร่งแสงในระดับ OS เพื่อความสบายตา
CSS
@media (prefers-reduced-transparency: reduce) {
.glass-panel {
backdrop-filter: none;
-webkit-backdrop-filter: none;
background: #1e1e24; /* ใช้สีทึบเพื่อความชัดเจนสูงสุด */
}
}