ตัวแปร CSS หรือที่เรียกอย่างถูกต้องว่าพร็อพเพอร์ตี้ที่กำหนดเองของ CSS จะพร้อมใช้งานใน Chrome 49 ซึ่งมีประโยชน์ในการลดการซ้ำใน CSS และเพื่อเอฟเฟกต์รันไทม์ที่มีประสิทธิภาพ เช่น การเปลี่ยนธีม และอาจขยาย/โพลีฟีลฟ์ฟีเจอร์ CSS ในอนาคต
CSS รก
เมื่อออกแบบแอปพลิเคชัน แนวทางปฏิบัติทั่วไปคือการจัดสรรชุดสีของแบรนด์ที่จะนํามาใช้ซ้ำเพื่อให้รูปลักษณ์ของแอปมีความสอดคล้องกัน แต่การเขียนค่าสีเหล่านี้ซ้ำๆ ใน CSS นั้นไม่เพียงแต่ทํางานหนักเท่านั้น แต่ยังเสี่ยงที่จะเกิดข้อผิดพลาดด้วย หากในบางครั้งจำเป็นต้องเปลี่ยนสีใดสีหนึ่ง คุณอาจไม่สนใจคำเตือนและ "ค้นหาและแทนที่" ทุกอย่าง แต่สำหรับโปรเจ็กต์ขนาดใหญ่ การดำเนินการนี้อาจเป็นอันตรายได้
ในช่วงหลังๆ นี้ นักพัฒนาซอฟต์แวร์จำนวนมากหันมาใช้โปรแกรมประมวลผลข้อมูล CSS เช่น SASS หรือ LESS ซึ่งแก้ปัญหานี้ได้โดยใช้ตัวแปรโปรแกรมประมวลผลข้อมูล แม้ว่าเครื่องมือเหล่านี้จะช่วยเพิ่มประสิทธิภาพของนักพัฒนาซอฟต์แวร์ได้เป็นอย่างมาก แต่ตัวแปรที่ใช้ก็มีข้อเสียที่สำคัญอย่างหนึ่งคือตัวแปรเป็นแบบคงที่และไม่สามารถเปลี่ยนแปลงขณะรันไทม์ได้ การเพิ่มความสามารถในการเปลี่ยนตัวแปรขณะรันไทม์ไม่เพียงเปิดโอกาสให้ทำสิ่งต่างๆ เช่น การกำหนดธีมแอปพลิเคชันแบบไดนามิกเท่านั้น แต่ยังส่งผลสำคัญต่อการออกแบบที่ปรับเปลี่ยนตามอุปกรณ์และมีโอกาสที่จะใช้ polyfill กับฟีเจอร์ CSS ในอนาคต เมื่อมีการเปิดตัว Chrome 49 ความสามารถเหล่านี้จะพร้อมใช้งานในรูปแบบพร็อพเพอร์ตี้ที่กำหนดเองของ CSS
ข้อมูลสรุปเกี่ยวกับพร็อพเพอร์ตี้ที่กำหนดเอง
พร็อพเพอร์ตี้ที่กำหนดเองจะเพิ่มฟีเจอร์ใหม่ 2 รายการลงในกล่องเครื่องมือ CSS
- ความสามารถในการกำหนดค่าที่กำหนดเองให้กับพร็อพเพอร์ตี้ที่มีชื่อที่ผู้เขียนเลือก
- ฟังก์ชัน
var()
ซึ่งช่วยให้ผู้เขียนใช้ค่าเหล่านี้ในพร็อพเพอร์ตี้อื่นๆ ได้
ต่อไปนี้เป็นตัวอย่างสั้นๆ ที่แสดงให้เห็น
:root {
--main-color: #06c;
}
#foo h1 {
color: var(--main-color);
}
--main-color
เป็นพร็อพเพอร์ตี้ที่กำหนดเองซึ่งผู้แต่งกำหนดซึ่งมีค่าเป็น #06c โปรดทราบว่าพร็อพเพอร์ตี้ที่กําหนดเองทั้งหมดจะขึ้นต้นด้วยเครื่องหมายขีดกลาง 2 ขีด
ฟังก์ชัน var()
จะดึงค่าพร็อพเพอร์ตี้ที่กำหนดเองมาแทนที่ตัวเอง ซึ่งจะส่งผลให้เกิด color: #06c;
ตราบใดที่มีการกําหนดพร็อพเพอร์ตี้ที่กําหนดเองไว้ที่ใดที่หนึ่งในสไตล์ชีต ฟังก์ชัน var
ก็ควรใช้งานได้
ไวยากรณ์อาจดูแปลกๆ ไปหน่อยในตอนแรก นักพัฒนาแอปหลายคนถามว่า "ทำไมไม่ใช้ $foo
เป็นชื่อตัวแปรไปเลย" วิธีการนี้ได้รับการเลือกมาโดยเฉพาะเพื่อให้มีความยืดหยุ่นมากที่สุดและอาจรองรับมาโคร $foo
ในอนาคต
หากต้องการทราบเรื่องราวเบื้องหลัง โปรดอ่านโพสต์นี้จาก Tab Atkins หนึ่งในผู้เขียนข้อกำหนด
ไวยากรณ์ของพร็อพเพอร์ตี้ที่กำหนดเอง
ไวยากรณ์ของพร็อพเพอร์ตี้ที่กำหนดเองนั้นเข้าใจง่าย
--header-color: #06c;
โปรดทราบว่าพร็อพเพอร์ตี้ที่กำหนดเองจะคำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ ดังนั้น --header-color
และ
--Header-Color
จึงถือเป็นพร็อพเพอร์ตี้ที่กำหนดเองที่แตกต่างกัน แม้ว่าไวยากรณ์เหล่านี้อาจดูเข้าใจง่าย แต่ไวยากรณ์ที่อนุญาตสําหรับพร็อพเพอร์ตี้ที่กําหนดเองนั้นค่อนข้างยืดหยุ่น ตัวอย่างเช่น พร็อพเพอร์ตี้ที่กำหนดเองที่ถูกต้องมีดังต่อไปนี้
--foo: if(x > 5) this.width = 10;
แม้ว่าจะไม่มีประโยชน์เมื่อใช้เป็นตัวแปร เนื่องจากจะใช้งานไม่ได้ในพร็อพเพอร์ตี้ปกติ แต่อาจมีการนำไปใช้อ่านและดำเนินการด้วย JavaScript ที่รันไทม์ ซึ่งหมายความว่าพร็อพเพอร์ตี้ที่กำหนดเองมีศักยภาพในการปลดล็อกเทคนิคที่น่าสนใจทุกประเภทที่ปัจจุบันใช้กับโปรแกรมประมวลผล CSS ไม่ได้ ดังนั้นหากคุณกำลังคิดว่า "ง่วง ฉันมี SASS แล้วใครจะสนใจ…" ลองพิจารณาอีกครั้ง ตัวแปรเหล่านี้ไม่ใช่ตัวแปรที่คุณคุ้นเคย
การแสดงผลตามลำดับขั้น
พร็อพเพอร์ตี้ที่กำหนดเองจะเป็นไปตามกฎการซ้อนทับมาตรฐาน คุณจึงกำหนดพร็อพเพอร์ตี้เดียวกันในระดับความเฉพาะเจาะจงที่แตกต่างกันได้
:root { --color: blue; }
div { --color: green; }
#alert { --color: red; }
* { color: var(--color); }
<p>I inherited blue from the root element!</p>
<div>I got green set directly on me!</div>
<div id="alert">
While I got red set directly on me!
<p>I’m red too, because of inheritance!</p>
</div>
ซึ่งหมายความว่าคุณสามารถใช้ประโยชน์จากพร็อพเพอร์ตี้ที่กำหนดเองภายในการค้นหาสื่อเพื่อช่วยในการออกแบบที่ตอบสนองตามอุปกรณ์ กรณีการใช้งานอย่างหนึ่งอาจเป็นการขยายระยะขอบรอบองค์ประกอบการแบ่งส่วนหลักเมื่อขนาดหน้าจอเพิ่มขึ้น
:root {
--gutter: 4px;
}
section {
margin: var(--gutter);
}
@media (min-width: 600px) {
:root {
--gutter: 16px;
}
}
โปรดทราบว่าข้อมูลโค้ดด้านบนใช้กับโปรแกรมประมวลผลข้อมูล CSS ในปัจจุบันไม่ได้ เนื่องจากไม่สามารถกำหนดตัวแปรภายในการค้นหาสื่อ ความสามารถนี้จะช่วยปลดล็อกศักยภาพได้มากมาย
นอกจากนี้ คุณยังอาจมีพร็อพเพอร์ตี้ที่กำหนดเองซึ่งดึงค่ามาจากพร็อพเพอร์ตี้ที่กำหนดเองอื่นๆ ได้ด้วย ซึ่งมีประโยชน์อย่างยิ่งสำหรับธีม
:root {
--primary-color: red;
--logo-text: var(--primary-color);
}
ฟังก์ชัน var()
หากต้องการเรียกข้อมูลและใช้ค่าของพร็อพเพอร์ตี้ที่กำหนดเอง คุณจะต้องฟังก์ชัน var()
ไวยากรณ์ของฟังก์ชัน var()
มีดังนี้
var(<custom-property-name> [, <declaration-value> ]? )
โดยที่ <custom-property-name>
คือชื่อพร็อพเพอร์ตี้ที่กำหนดเองของผู้เขียน เช่น --foo
และ <declaration-value>
คือค่าสำรองที่จะใช้เมื่อพร็อพเพอร์ตี้ที่กำหนดเองซึ่งอ้างอิงไม่ถูกต้อง ค่าสำรองอาจเป็นรายการที่คั่นด้วยคอมมา ซึ่งจะรวมกันเป็นค่าเดียว เช่น var(--font-stack,
"Roboto", "Helvetica");
กำหนดค่าสำรองของ "Roboto", "Helvetica"
โปรดทราบว่าค่าตัวย่อ เช่น ค่าที่ใช้สำหรับระยะขอบและระยะห่างจากขอบ จะไม่คั่นด้วยคอมมา ดังนั้นค่าสำรองที่เหมาะสมสำหรับระยะห่างจากขอบจึงมีลักษณะดังนี้
p {
padding: var(--pad, 10px 15px 20px);
}
ผู้เขียนคอมโพเนนต์สามารถใช้ค่าสำรองเหล่านี้เพื่อเขียนสไตล์ป้องกันสำหรับองค์ประกอบได้ ดังนี้
/* In the component’s style: */
.component .header {
color: var(--header-color, blue);
}
.component .text {
color: var(--text-color, black);
}
/* In the larger application’s style: */
.component {
--text-color: #080;
/* header-color isn’t set,
and so remains blue,
the fallback value */
}
เทคนิคนี้มีประโยชน์อย่างยิ่งสำหรับการกำหนดธีมให้กับ Web Component ที่ใช้ Shadow DOM เนื่องจากพร็อพเพอร์ตี้ที่กำหนดเองสามารถข้ามขอบเขตของ Shadow ได้ ผู้เขียนคอมโพเนนต์เว็บสามารถสร้างการออกแบบเริ่มต้นโดยใช้ค่าสำรอง และแสดง "ฮุก" การจัดธีมในรูปแบบพร็อพเพอร์ตี้ที่กำหนดเอง
<!-- In the web component's definition: -->
<x-foo>
#shadow
<style>
p {
background-color: var(--text-background, blue);
}
</style>
<p>
This text has a yellow background because the document styled me! Otherwise it
would be blue.
</p>
</x-foo>
/* In the larger application's style: */
x-foo {
--text-background: yellow;
}
เมื่อใช้ var()
มีข้อควรระวังบางอย่างที่ควรทราบ ตัวแปรต้องไม่ใช่ชื่อพร็อพเพอร์ตี้ ตัวอย่างเช่น
.foo {
--side: margin-top;
var(--side): 20px;
}
แต่การตั้งค่านี้ไม่เหมือนกับการตั้งค่า margin-top: 20px;
แต่การประกาศที่ 2 จะไม่ถูกต้องและระบบจะแสดงเป็นข้อผิดพลาด
ในทํานองเดียวกัน คุณไม่สามารถสร้างค่า (อย่างง่ายดาย) โดยให้ตัวแปรระบุค่าบางส่วน
.foo {
--gap: 20;
margin-top: var(--gap)px;
}
โปรดทราบว่าการตั้งค่านี้ไม่เหมือนกับการตั้งค่า margin-top: 20px;
หากต้องการสร้างค่า คุณต้องใช้สิ่งอื่น นั่นคือฟังก์ชัน calc()
การสร้างค่าด้วย calc()
หากคุณไม่เคยใช้มาก่อน ฟังก์ชัน calc()
เป็นเครื่องมือเล็กๆ ที่มีประโยชน์ซึ่งช่วยให้คุณทําการคํานวณเพื่อกําหนดค่า CSS ได้ เบราว์เซอร์สมัยใหม่ทั้งหมดรองรับ และสามารถรวมเข้ากับพร็อพเพอร์ตี้ที่กำหนดเองเพื่อสร้างค่าใหม่ได้ เช่น
.foo {
--gap: 20;
margin-top: calc(var(--gap) * 1px); /* niiiiice */
}
การใช้พร็อพเพอร์ตี้ที่กําหนดเองใน JavaScript
หากต้องการรับค่าของพร็อพเพอร์ตี้ที่กำหนดเองที่รันไทม์ ให้ใช้getPropertyValue()
วิธีของออบเจ็กต์ CSSStyleDeclaration ที่คำนวณแล้ว
/* CSS */
:root {
--primary-color: red;
}
p {
color: var(--primary-color);
}
<!-- HTML -->
<p>I’m a red paragraph!</p>
/* JS */
var styles = getComputedStyle(document.documentElement);
var value = String(styles.getPropertyValue('--primary-color')).trim();
// value = 'red'
ในทํานองเดียวกัน หากต้องการกําหนดค่าของพร็อพเพอร์ตี้ที่กําหนดเองที่รันไทม์ ให้ใช้เมธอด setProperty()
ของออบเจ็กต์ CSSStyleDeclaration
/* CSS */
:root {
--primary-color: red;
}
p {
color: var(--primary-color);
}
<!-- HTML -->
<p>Now I’m a green paragraph!</p>
/* JS */
document.documentElement.style.setProperty('--primary-color', 'green');
นอกจากนี้ คุณยังตั้งค่าพร็อพเพอร์ตี้ที่กำหนดเองให้อ้างอิงพร็อพเพอร์ตี้ที่กำหนดเองอีกรายการหนึ่งขณะรันไทม์ได้โดยใช้ฟังก์ชัน var()
ในการเรียกใช้ setProperty()
/* CSS */
:root {
--primary-color: red;
--secondary-color: blue;
}
<!-- HTML -->
<p>Sweet! I’m a blue paragraph!</p>
/* JS */
document.documentElement.style.setProperty('--primary-color', 'var(--secondary-color)');
เนื่องจากพร็อพเพอร์ตี้ที่กำหนดเองสามารถอ้างอิงถึงพร็อพเพอร์ตี้ที่กำหนดเองอื่นๆ ในสไตล์ชีต คุณจึงจินตนาการได้ว่าสิ่งนี้จะนำไปสู่เอฟเฟกต์รันไทม์ที่น่าสนใจมากมายเพียงใด
การสนับสนุนเบราว์เซอร์
ปัจจุบัน Chrome 49, Firefox 42, Safari 9.1 และ iOS Safari 9.3 รองรับพร็อพเพอร์ตี้ที่กำหนดเอง
สาธิต
ลองใช้ตัวอย่างเพื่อดูเทคนิคที่น่าสนใจทั้งหมดที่คุณใช้ประโยชน์ได้ตอนนี้ด้วยพร็อพเพอร์ตี้ที่กำหนดเอง
อ่านเพิ่มเติม
หากสนใจดูข้อมูลเพิ่มเติมเกี่ยวกับพร็อพเพอร์ตี้ที่กําหนดเอง Philip Walton จากทีม Google Analytics ได้เขียนข้อมูลเบื้องต้นเกี่ยวกับเหตุผลที่เขาตื่นเต้นกับพร็อพเพอร์ตี้ที่กําหนดเอง และคุณสามารถติดตามความคืบหน้าในเบราว์เซอร์อื่นๆ ได้ที่ chromestatus.com