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

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

ความไม่เป็นระเบียบของ CSS

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

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

นอกจากนี้ ยังอาจมีพร็อพเพอร์ตี้ที่กำหนดเองซึ่งสร้างคุณค่าจากพร็อพเพอร์ตี้อื่น พร็อพเพอร์ตี้ที่กำหนดเอง ซึ่งจะเป็นประโยชน์อย่างมากสำหรับการกำหนดธีม ดังนี้

: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 */
}

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

<!-- 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.