ตัวแปร CSS - ทำไมคุณจึงควรให้ความสนใจ

ตัวแปร CSS หรือที่เรียกอีกอย่างว่าพร็อพเพอร์ตี้ที่กำหนดเองของ CSS จะมายัง Chrome 49 ซึ่งมีประโยชน์ในการลดความซ้ำซ้อนใน CSS รวมถึงสำหรับเอฟเฟกต์รันไทม์ที่มีประสิทธิภาพ เช่น การสลับธีมและการเพิ่ม/ทำให้ฟีเจอร์ CSS ในอนาคตใช้งานได้

ความยุ่งเหยิงของ CSS

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

ในช่วงที่ผ่านมา นักพัฒนาแอปหลายรายได้หันมาใช้ CSS Preprocessor เช่น SASS หรือ LESS ซึ่งแก้ปัญหานี้ผ่านการใช้ตัวแปร Preprocessor แม้ว่าเครื่องมือเหล่านี้จะช่วยเพิ่มประสิทธิภาพการทำงานของนักพัฒนาซอฟต์แวร์ได้อย่างมาก แต่ตัวแปรที่นักพัฒนาใช้นั้นพบอุปสรรคสำคัญ ซึ่งก็คือแบบคงที่ และเปลี่ยนแปลงไม่ได้ในขณะรันไทม์ การเพิ่มความสามารถในการเปลี่ยนตัวแปรขณะรันไทม์ไม่เพียงเป็นการเปิดประตูสู่สิ่งต่างๆ เช่น การกำหนดธีมของแอปพลิเคชันแบบไดนามิกเท่านั้น แต่ยังส่งผลสำคัญต่อการออกแบบที่ปรับเปลี่ยนตามอุปกรณ์และศักยภาพในการสร้างฟีเจอร์ 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 */
}

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

<!-- 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() จะมี Gott บางรายการที่ต้องระวัง ตัวแปรต้องไม่ เป็นชื่อพร็อพเพอร์ตี้ ตัวอย่างเช่น

.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