ใช้พร็อพเพอร์ตี้ interpolate-size
หรือฟังก์ชัน calc-size()
เพื่อเปิดใช้การเปลี่ยนภาพและภาพเคลื่อนไหวที่ราบรื่นจากความยาวเป็นคีย์เวิร์ดการปรับขนาดตามค่าเริ่มต้นและกลับกัน
เผยแพร่: 17 ก.ย. 2024
บทนำ
ฟีเจอร์ CSS ที่ขอกันบ่อยคือความสามารถในการทำให้ height: auto
เคลื่อนไหว คําขอที่แตกต่างออกไปเล็กน้อยคือการเปลี่ยนพร็อพเพอร์ตี้ width
แทน height
หรือเปลี่ยนไปใช้ขนาดตามธรรมชาติอื่นๆ ที่แสดงโดยคีย์เวิร์ด เช่น min-content
, max-content
และ fit-content
ตัวอย่างเช่น ในการสาธิตต่อไปนี้ ป้ายกำกับควรเคลื่อนไหวอย่างราบรื่นเป็นขนาดตามปกติเมื่อวางเมาส์เหนือไอคอน
CSS ที่ใช้มีดังนี้
nav a {
width: 80px;
overflow-x: clip;
transition: width 0.35s ease; /* 👈 Transition the width */
&:hover,
&:focus-visible {
width: max-content; /* 👈 Doesn't work with transitions */
}
}
แม้ว่าจะมีการประกาศ transition
เพื่อเปลี่ยนพร็อพเพอร์ตี้ width
และมีการประกาศ width: auto
ใน :hover
แต่การเปลี่ยนก็ไม่ราบรื่น แต่การเปลี่ยนแปลงกลับเกิดขึ้นอย่างกะทันหัน
สร้างภาพเคลื่อนไหวจากคีย์เวิร์ดการปรับขนาดตามเนื้อหาไปยังคีย์เวิร์ดการปรับขนาดตามบริบทด้วย interpolate-size
พร็อพเพอร์ตี้ interpolate-size
ของ CSS ช่วยให้คุณควบคุมได้ว่าควรอนุญาตภาพเคลื่อนไหวและการเปลี่ยนรูปแบบของคีย์เวิร์ดการปรับขนาดตามค่าเริ่มต้นของ CSS หรือไม่
ค่าเริ่มต้นคือ numeric-only
ซึ่งจะไม่เปิดใช้การประมาณ เมื่อตั้งค่าพร็อพเพอร์ตี้เป็น allow-keywords
แสดงว่าคุณเลือกใช้การหาค่าเฉลี่ยจากความยาวเป็นคีย์เวิร์ดการปรับขนาดตามค่าเริ่มต้นของ CSS ในกรณีที่เบราว์เซอร์สามารถทำให้คีย์เวิร์ดเหล่านั้นเคลื่อนไหวได้
numeric-only
: ไม่สามารถหาค่าเฉลี่ยของ<intrinsic-size-keyword>
allow-keywords
: ระบบจะหาค่าประมาณของค่า 2 ค่าได้หากค่าใดค่าหนึ่งเป็น<intrinsic-size-keyword>
และอีกค่าหนึ่งเป็น<length-percentage>
[…]
เนื่องจากพร็อพเพอร์ตี้ interpolate-size
เป็นพร็อพเพอร์ตี้ที่รับค่ามา คุณจึงประกาศพร็อพเพอร์ตี้นี้ใน :root
เพื่อเปิดใช้การเปลี่ยนจากและไปยังคีย์เวิร์ดการปรับขนาดตามเนื้อหาสำหรับทั้งเอกสารได้ นี่เป็นแนวทางที่แนะนำ
/* Opt-in the whole page to interpolate sizes to/from keywords */
:root {
interpolate-size: allow-keywords; /* 👈 */
}
ในการแสดงตัวอย่างต่อไปนี้ ระบบจะเพิ่มกฎนี้ลงในโค้ด ด้วยเหตุนี้ ภาพเคลื่อนไหวจาก width: auto
ไปยัง width: auto
จึงทำงานได้อย่างถูกต้อง (ในเบราว์เซอร์ที่รองรับ)
จํากัดการเข้าถึงของการเลือกรับโดยจํากัดตัวเลือกให้แคบลง
หากต้องการจํากัดการเลือกใช้ allow-keywords
ไว้เฉพาะที่ส่วนย่อยของเอกสาร ให้ปรับตัวเลือกจาก :root
เฉพาะองค์ประกอบที่คุณต้องการกําหนดเป้าหมาย ตัวอย่างเช่น ในกรณีที่ <header>
ของหน้าเว็บใช้ร่วมกับการเปลี่ยนประเภทเหล่านี้ไม่ได้ คุณอาจจำกัดการเลือกใช้ไว้เฉพาะองค์ประกอบ <main>
และองค์ประกอบที่สืบทอดมา ดังนี้
main { /* 👈 Scope the opt-in to only <main> and its descendants */
interpolate-size: allow-keywords;
}
เหตุใดจึงไม่อนุญาตให้มีภาพเคลื่อนไหวจากคีย์เวิร์ดการปรับขนาดและไปยังคีย์เวิร์ดการปรับขนาดโดยค่าเริ่มต้น
ความคิดเห็นที่พบบ่อยเกี่ยวกับกลไกการเลือกรับนี้คือ เบราว์เซอร์ควรอนุญาตให้ใช้การเปลี่ยนภาพและภาพเคลื่อนไหวจากคีย์เวิร์ดการปรับขนาดตามเนื้อหาเป็นความยาวโดยค่าเริ่มต้น
เราได้ศึกษาตัวเลือกในการเปิดใช้ลักษณะการทำงานนี้ระหว่างการพัฒนาฟีเจอร์ คณะทำงานพบว่าการเปิดใช้การตั้งค่านี้โดยค่าเริ่มต้นใช้งานร่วมกับเวอร์ชันเก่าไม่ได้ เนื่องจากสไตล์ชีตจำนวนมากถือว่าคีย์เวิร์ดการปรับขนาดตามค่าเริ่มต้น (เช่น auto
หรือ min-content
) ไม่สามารถเคลื่อนไหวได้ ดูรายละเอียดได้ในความคิดเห็นนี้เกี่ยวกับปัญหาของกลุ่มทํางาน CSS ที่เกี่ยวข้อง
ดังนั้นพร็อพเพอร์ตี้จึงเป็นแบบเลือกใช้ การเลือกรับทั้งเอกสารเป็นเพียงinterpolate-size: allow-sizes
การประกาศใน :root
ตามที่อธิบายไว้ก่อนหน้านี้ เนื่องจากลักษณะการสืบทอด
สร้างภาพเคลื่อนไหวจากคีย์เวิร์ดการปรับขนาดตามเนื้อหาไปยังคีย์เวิร์ดการปรับขนาดตามบริบทด้วย calc-size()
อีกวิธีในการเปิดใช้การประมาณค่าจากและไปยังคีย์เวิร์ดการปรับขนาดตามข้อมูลที่มีอยู่คือการใช้ฟังก์ชัน calc-size()
ซึ่งช่วยให้สามารถดำเนินการทางคณิตศาสตร์กับขนาดที่แท้จริงได้อย่างปลอดภัยและชัดเจน
ฟังก์ชันนี้รับอาร์กิวเมนต์ 2 รายการตามลําดับดังนี้
- พื้นฐานขนาดการคํานวณ ซึ่งอาจเป็น
<intrinsic-size-keyword>
หรือcalc-size()
ที่ฝังอยู่ก็ได้ - การคํานวณขนาดการคาดคะเน ซึ่งช่วยให้คุณทําการคํานวณโดยใช้พื้นฐานขนาดการคาดคะเนได้ หากต้องการอ้างอิงพื้นฐานขนาดการคํานวณ ให้ใช้คีย์เวิร์ด
size
ตัวอย่างเช่น
width: calc-size(auto, size); // = the auto width, unaltered
width: calc-size(min-content, size); // = the min-content width, unaltered
เมื่อเพิ่ม calc-size()
ลงในเดโมต้นฉบับ โค้ดจะมีลักษณะดังนี้
nav a {
width: 80px;
overflow-x: clip;
transition: width 0.35s ease;
&:hover,
&:focus-visible {
width: calc-size(max-content, size); /* 👈 */
}
}
ผลลัพธ์ที่แสดงจะเหมือนกับเมื่อใช้ interpolate-size
ทุกประการ ดังนั้นในกรณีนี้ คุณควรใช้ interpolate-size
สิ่งที่ calc-size()
ทำได้ดีคือความสามารถในการคํานวณ ซึ่งเป็นสิ่งที่ interpolate-size
ทําไม่ได้
width: calc-size(auto, size - 10px); // = The auto width minus 10 pixels
width: calc-size(min-content, size + 1rem); // = The min-content width plus 1rem
width: calc-size(max-content, size * .5); // = Half the max-content width
เช่น หากต้องการให้ย่อหน้าทั้งหมดในหน้าเว็บมีขนาดเป็นจำนวนที่หารด้วย 50px
ได้สนิทที่สุด ให้ใช้คำสั่งต่อไปนี้
p {
width: calc-size(fit-content, round(up, size, 50px));
height: calc-size(auto, round(up, size, 50px));
}
นอกจากนี้ calc-size()
ยังช่วยให้คุณหาค่าประมาณของ calc-size()
2 รายการได้เมื่อฐานขนาดการคํานวณของทั้ง 2 รายการเหมือนกัน การดำเนินการนี้ยังทำไม่ได้ใน interpolate-size
#element {
width: min-content; /* 👈 */
transition: width 0.35s ease;
&:hover {
width: calc-size(min-content, size + 10px); /* 👈 */
}
}
เหตุใดจึงไม่อนุญาตให้ใช้ <intrinsic-size-keyword>
ใน calc()
คำถามที่มักเกิดขึ้นกับ calc-size()
คือเหตุใดกลุ่มผู้เชี่ยวชาญ CSS จึงไม่ปรับฟังก์ชัน calc()
ให้รองรับคีย์เวิร์ดการปรับขนาดตามค่าเริ่มต้น
สาเหตุหนึ่งคือคุณไม่ได้รับอนุญาตให้ผสมคีย์เวิร์ดการปรับขนาดตามข้อมูลที่มีอยู่เมื่อทำการคำนวณ เช่น คุณอาจอยากเขียน calc(max-content - min-content)
ซึ่งดูเหมือนว่าถูกต้อง แต่จริงๆ แล้วไม่ถูกต้อง calc-size()
บังคับใช้ความถูกต้องเนื่องจากยอมรับเฉพาะ <intrinsic-size-keyword>
รายการเดียวเป็นอาร์กิวเมนต์แรก ต่างจาก calc()
อีกเหตุผลหนึ่งคือความสามารถในการรับรู้บริบท อัลกอริทึมเลย์เอาต์บางรายการมีลักษณะการทํางานพิเศษสําหรับคีย์เวิร์ดการปรับขนาดตามบริบทที่เฉพาะเจาะจง calc-size()
ได้รับการกําหนดไว้อย่างชัดเจนเพื่อแสดงขนาดที่แท้จริง ไม่ใช่ <length>
ด้วยเหตุนี้ อัลกอริทึมเหล่านั้นจึงสามารถถือว่า calc-size(<intrinsic-size-keyword>, …)
เป็น <intrinsic-size-keyword>
ได้ เพื่อคงลักษณะการทำงานพิเศษของคีย์เวิร์ดนั้นไว้
แนวทางใดที่ควรใช้
ในกรณีส่วนใหญ่ ให้ประกาศ interpolate-size: allow-keywords
ใน :root
นี่เป็นวิธีที่ง่ายที่สุดในการเปิดใช้ภาพเคลื่อนไหวจากคีย์เวิร์ดการปรับขนาดตามเนื้อหาและกลับไปยังคีย์เวิร์ดดังกล่าว เนื่องจากเป็นคำสั่งแบบบรรทัดเดียว
/* Opt-in the whole page to animating to/from intrinsic sizing keywords */
:root {
interpolate-size: allow-keywords; /* 👈 */
}
โค้ดนี้เป็นการเพิ่มประสิทธิภาพแบบเป็นขั้นเป็นตอนที่ดี เนื่องจากเบราว์เซอร์ที่ไม่รองรับจะเปลี่ยนไปใช้แบบไม่มีทรานซิชัน
เมื่อคุณต้องการควบคุมสิ่งต่างๆ อย่างละเอียดยิ่งขึ้น เช่น การทำการคำนวณ หรือต้องการใช้ลักษณะการทำงานที่ calc-size()
ทำได้เท่านั้น คุณก็ใช้ calc-size()
ได้
#specific-element {
width: 50px;
&:hover {
width: calc-size(fit-content, size + 1em); /* 👈 Only calc-size() can do this */
}
}
อย่างไรก็ตาม การใช้ calc-size()
ในโค้ดจะทำให้คุณต้องใส่ทางเลือกสำรองสำหรับเบราว์เซอร์ที่ไม่รองรับ calc-size()
เช่น การเพิ่มการประกาศขนาดเพิ่มเติม หรือกลับไปใช้การตรวจหาองค์ประกอบโดยใช้ @supports
width: fit-content;
width: calc-size(fit-content, size + 1em);
/* 👆 Browsers with no calc-size() support will ignore this second declaration,
and therefore fall back to the one on the line before it. */
ตัวอย่างเพิ่มเติม
ลองดูตัวอย่างการใช้งาน interpolate-size: allow-keywords
เพิ่มเติมที่เป็นประโยชน์
การแจ้งเตือน
เดโมต่อไปนี้เป็นเวอร์ชันแยกมาจากเดโม @starting-style
นี้ เราได้ปรับโค้ดเพื่อให้เพิ่มรายการที่มีความสูงแตกต่างกันได้
โดยทั้งหน้าจะเลือกใช้การประมาณขนาดคีย์เวิร์ด และตั้งค่า height
ในเอลิเมนต์ .item
แต่ละรายการเป็น auto
มิฉะนั้น โค้ดจะเหมือนกับก่อนแยกออกมาทุกประการ
:root {
interpolate-size: allow-keywords; /* 👈 */
}
.item {
height: auto; /* 👈 */
@starting-style {
height: 0px;
}
}
สร้างภาพเคลื่อนไหวขององค์ประกอบ <details>
Use Case ทั่วไปที่คุณต้องการใช้การอินเตอร์โพเลชันประเภทนี้คือการสร้างภาพเคลื่อนไหววิดเจ็ตการเปิดเผยหรือกล่องแอคคอร์เดียนเฉพาะขณะเปิด ใน HTML คุณใช้องค์ประกอบ <details>
interpolate-size: allow-keywords
ช่วยให้คุณทำสิ่งต่อไปนี้ได้
@supports (interpolate-size: allow-keywords) {
:root {
interpolate-size: allow-keywords;
}
details {
transition: height 0.5s ease;
height: 2.5rem;
&[open] {
height: auto;
overflow: clip; /* Clip off contents while animating */
}
}
}
แต่อย่างที่เห็น ภาพเคลื่อนไหวจะทำงานก็ต่อเมื่อวิดเจ็ตการเปิดเผยข้อมูลเปิดอยู่เท่านั้น Chrome กำลังพัฒนาแอตทริบิวต์ ::details-content
จำลองเพื่อรองรับกรณีนี้ ซึ่งจะพร้อมใช้งานใน Chrome ภายในปีนี้ (และจะกล่าวถึงในโพสต์ในอนาคต) เมื่อใช้ interpolate-size: allow-keywords
และ ::details-content
ร่วมกัน คุณจะได้ภาพเคลื่อนไหวทั้ง 2 ทิศทางดังนี้