สร้างภาพเคลื่อนไหวตามขนาดภายใน

ฟีเจอร์บนเว็บ: calc-size() interpolate-size

ในอดีต การสร้างภาพเคลื่อนไหวขององค์ประกอบให้มีขนาดแบบไดนามิก เช่น block-size: auto หรือ inline-size: max-content ต้องใช้ JavaScript หรือแฮ็ก "max-height" ที่ไม่เสถียร พร็อพเพอร์ตี้ interpolate-size และฟังก์ชัน calc-size() ช่วยให้เบราว์เซอร์สามารถประมาณค่าในช่วงระหว่างความยาวคงที่และคีย์เวิร์ดการปรับขนาดภายในได้โดยตรง

ขั้นตอนการติดตั้งใช้งาน

  1. เลือกใช้การประมาณค่าในช่วงคีย์เวิร์ด: ใช้ interpolate-size: allow-keywords กับองค์ประกอบหลัก (โดยปกติคือ :root) เพื่อเปิดใช้การเปลี่ยนผ่านสำหรับพร็อพเพอร์ตี้ที่ใช้คีย์เวิร์ดภายใน
  2. กำหนดการเปลี่ยน: ตั้งค่า transition สำหรับพร็อพเพอร์ตี้การปรับขนาด (เช่น block-size, inline-size) ในองค์ประกอบเป้าหมาย
  3. ใช้คีย์เวิร์ดภายใน: เปลี่ยนพร็อพเพอร์ตี้การปรับขนาดเป็นคีย์เวิร์ดภายในที่รองรับ (auto, min-content, max-content, fit-content หรือ (สำหรับ flex-basis) content) ระหว่างการโต้ตอบ (เช่น :hover หรือคลาสสถานะ)
  4. ทำการคำนวณ (ไม่บังคับ): ใช้ calc-size() หากต้องการคำนวณทางคณิตศาสตร์กับขนาดที่แท้จริง (เช่น auto + 2rem) calc-size() ยังรองรับคีย์เวิร์ด any สำหรับการคำนวณที่ไม่ขึ้นอยู่กับพื้นฐานด้วย

ตัวอย่าง: รูปแบบการขยายทั่วไป

คุณสามารถใช้รูปแบบนี้กับคอนเทนเนอร์ใดก็ได้ (เช่น ส่วน "แสดงเพิ่มเติม" หรือเมนูการนำทาง) เพื่อเปลี่ยนระหว่างความสูงที่จำกัดกับขนาดปกติขององค์ประกอบ

/* Opt-in globally for all children */
:root {
  /* MANDATORY: Transitions to intrinsic keywords are disabled by default for compatibility */
  interpolate-size: allow-keywords;
}

.expandable-container {
  /* 1. Define a fixed initial size (or 0) and hide overflow */
  block-size: 100px;
  overflow: hidden;
  
  /* 2. Transition the sizing property */
  transition: block-size 0.4s ease-out;
}

.expandable-container.is-expanded {
  /* 3. Smoothly animate to the intrinsic natural height */
  block-size: auto;
}

ตัวอย่าง: ขนาดในบรรทัดที่แท้จริงที่คำนวณแล้ว

.badge {
  inline-size: 40px;
  overflow: hidden;
  white-space: nowrap;
  transition: inline-size 0.3s ease;
}

.badge:hover {
  /* calc-size(basis, calculation) */
  /* 'size' refers to the evaluated basis (max-content in this case) */
  inline-size: calc-size(max-content, size + 20px);
}

ตัวอย่าง: การเปลี่ยนจากขนาดที่แท้จริงเป็นขนาดคงที่

นอกจากนี้ คุณยังทำให้เคลื่อนไหวในทิศทางตรงกันข้ามได้ด้วย โดยเริ่มจากขนาดปกติและยุบเป็นความยาวที่เฉพาะเจาะจง ซึ่งมีประโยชน์สำหรับคอมโพเนนต์ที่ "ปิดได้"

.collapsible-alert {
  /* 1. Start with the natural content height */
  block-size: auto;
  overflow: hidden;
  transition: block-size 0.5s ease-in-out, opacity 0.5s ease;
}

.collapsible-alert.is-dismissed {
  /* 2. Smoothly collapse to zero */
  block-size: 0;
  opacity: 0;
  pointer-events: none;
}

/* MANDATORY Copy-Paste Safety: Disable sizing animations for sensitive users */
@media (prefers-reduced-motion: reduce) {
  .expandable-container,
  .badge,
  .collapsible-alert {
    transition: none !important;
  }
}
// MANDATORY Accessibility Synchronization: Ensure elements collapsed to zero dimensions are removed from the assistive technology tree, and sync aria-expanded states on triggers.
const alertElement = document.querySelector('.collapsible-alert');
alertElement.addEventListener('transitionend', (e) => {
  if (e.propertyName === 'block-size' && alertElement.classList.contains('is-dismissed')) {
    alertElement.hidden = true;
  }
});

// Example trigger syncer
const triggerBtn = document.querySelector('.accordion-trigger');
triggerBtn?.addEventListener('click', () => {
  const isExpanded = triggerBtn.getAttribute('aria-expanded') === 'true';
  triggerBtn.setAttribute('aria-expanded', !isExpanded);
});

ข้อจำกัดที่สำคัญ

  • ข้อจำกัดคีย์เวิร์ดต่อคีย์เวิร์ด: คุณไม่สามารถสร้างภาพเคลื่อนไหวระหว่างคีย์เวิร์ด 2 คำที่แตกต่างกันโดยตรง (เช่น จาก min-content เป็น max-content) ปลายด้านหนึ่งของการเปลี่ยนต้องมีความยาวหรือเปอร์เซ็นต์คงที่ (เช่น 0 เป็น auto)
  • ไวยากรณ์ calc-size: ภายใน calc-size() คุณไม่สามารถผสมคีย์เวิร์ดภายในที่แตกต่างกันในนิพจน์เดียวกันได้ อาร์กิวเมนต์แรก (ฐาน) จะกำหนดว่า size แสดงถึงอะไร
  • ข้อกำหนดในการเลือกใช้: การเปลี่ยนไปใช้คีย์เวิร์ดภายในจะปิดอยู่โดยค่าเริ่มต้น (numeric-only) เพื่อรักษาความเข้ากันได้แบบย้อนหลัง คุณต้องใช้ interpolate-size: allow-keywords กับองค์ประกอบหรือระดับบนสุด calc-size() ทำหน้าที่เป็นการลบล้างต่อพร็อพเพอร์ตี้ โดยจะเปิดใช้การประมาณค่าในช่วงโดยอัตโนมัติเมื่อใดก็ตามที่มีการใช้งาน

กลยุทธ์สำรอง

interpolate-size และ calc-size() เป็นการเพิ่มประสิทธิภาพแบบต่อเนื่อง เบราว์เซอร์ที่ไม่รองรับจะข้ามไปยังขนาดเป้าหมายทันที

  • การลดลงอย่างค่อยเป็นค่อยไป: สำหรับการเปลี่ยน block-size: auto แบบง่ายๆ เบราว์เซอร์มาตรฐานจะสลับขนาดทันที ซึ่งใช้งานได้แต่ไม่ราบรื่นนัก
  • คีย์เวิร์ดสำรองที่กำหนดเอง: เมื่อใช้ calc-size() ให้ระบุคีย์เวิร์ดสำรองมาตรฐานสำหรับเบราว์เซอร์รุ่นเก่าเสมอ เนื่องจากเบราว์เซอร์เหล่านั้นจะทิ้งการประกาศ calc-size() ทั้งหมด
.card {
  block-size: auto; /* Fallback for older browsers */
  block-size: calc-size(auto, size); /* Modern browsers use this */
  transition: block-size 0.3s ease;
}