คู่มือกลยุทธ์สำหรับคุณสมบัติที่กำหนดเอง CSS

เผยแพร่แล้ว: 2022-03-10
สรุปอย่างรวดเร็ว ↬ คุณสมบัติแบบไดนามิกให้โอกาสสำหรับความคิดสร้างสรรค์ใหม่ๆ แต่ยังมีโอกาสเพิ่มความซับซ้อนให้กับ CSS เพื่อให้ได้ประโยชน์สูงสุด เราอาจต้องใช้กลยุทธ์ในการเขียนและจัดโครงสร้าง CSS ด้วยคุณสมบัติที่กำหนดเอง

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

คุณสมบัติที่กำหนดเองมีศักยภาพมหาศาลในการเปลี่ยนแปลงวิธีที่เราเขียนและจัดโครงสร้าง CSS และวิธีที่เราใช้ JavaScript เพื่อโต้ตอบกับส่วนประกอบ UI ในระดับที่น้อยกว่า ฉันจะไม่เน้นที่ไวยากรณ์และวิธีการทำงาน (เพื่อที่ฉันแนะนำให้คุณอ่าน “ถึงเวลาที่จะเริ่มใช้คุณสมบัติที่กำหนดเอง”) แต่ฉันต้องการเจาะลึกถึงกลยุทธ์ในการใช้ประโยชน์สูงสุดจากคุณสมบัติที่กำหนดเองของ CSS

พวกมันคล้ายกับตัวแปรในตัวประมวลผลล่วงหน้าอย่างไร

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

ด้วย SCSS เราใช้สัญลักษณ์ดอลลาร์เพื่อแสดงถึงตัวแปร:

 $smashing-red: #d33a2c;

ใน Less เราใช้สัญลักษณ์ @ :

 @smashing-red: #d33a2c;

คุณสมบัติที่กำหนดเองเป็นไปตามข้อตกลงที่คล้ายกันและใช้ -- คำนำหน้า:

 :root { --smashing-red: #d33a2c; } .smashing-text { color: var(--smashing-red); }

ความแตกต่างที่สำคัญอย่างหนึ่งระหว่างคุณสมบัติแบบกำหนดเองและตัวแปรในตัวประมวลผลล่วงหน้าคือ คุณสมบัติที่กำหนดเองมีไวยากรณ์ที่แตกต่างกันสำหรับการกำหนดค่าและการดึงค่านั้น เมื่อดึงค่าของคุณสมบัติที่กำหนดเอง เราใช้ฟังก์ชัน var()

เพิ่มเติมหลังกระโดด! อ่านต่อด้านล่าง↓

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

 $breakpoint: 800px; $smashing-red: #d33a2c; $smashing-things: ".smashing-text, .cats"; @media screen and (min-width: $breakpoint) { #{$smashing-things} { color: $smashing-red; } }

ตัวอย่างส่วนใหญ่ข้างต้นจะไม่ถูกต้องโดยใช้คุณสมบัติที่กำหนดเอง

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

 :root { --smashing-red: #d33a2c; } @media screen and (min-width: 800px) { .smashing-text, .cats { --margin-left: 1em; } }

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

 .smashing-text, .cats { color: var(--smashing-red); margin: 0 var(--margin-horizontal); padding: calc(var(--margin-horizontal) / 2) }

อย่างไรก็ตาม ไม่สามารถใช้ในคิวรีสื่อ หรือตัวเลือกต่างๆ รวมถึง :nth-child()

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

ไดนามิกกับสแตติก

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

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

 $background: blue; .blue { background: $background; } $background: red; .red { background: $background; }

ส่งผลให้:

 .blue { background: blue; } .red { background: red; }

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

ตัวประมวลผลล่วงหน้ามี "ขอบเขตของบล็อก" ซึ่งตัวแปรสามารถเปลี่ยนแปลงได้ชั่วคราวภายในตัวเลือก ฟังก์ชัน หรือมิกซ์อิน สิ่งนี้จะเปลี่ยนค่าของตัวแปรภายในบล็อก แต่ก็ยังคงที่ สิ่งนี้ผูกติดอยู่กับบล็อก ไม่ใช่ตัวเลือก ในตัวอย่างด้านล่าง ตัวแปร $background จะเปลี่ยนแปลงภายในบล็อก . .example มันเปลี่ยนกลับเป็นค่าเริ่มต้นนอกบล็อกแม้ว่าเราจะใช้ตัวเลือกเดียวกันก็ตาม

 $background: red; .example { $background: blue; background: $background; } .example { background: $background; }

ซึ่งจะส่งผลให้:

 .example { background: blue; } .example { background: red; }

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

นี่เป็นสิ่งที่ดีเพราะคุณสามารถเปลี่ยนค่าของคุณสมบัติที่กำหนดเองภายในแบบสอบถามสื่อด้วยตัวเลือกหลอก เช่น โฮเวอร์ หรือแม้กระทั่งกับ JavaScript

 a { --link-color: black; } a:hover, a:focus { --link-color: tomato; } @media screen and (min-width: 600px) { a { --link-color: blue; } } a { color: var(--link-color); }

เราไม่จำเป็นต้องเปลี่ยนตำแหน่งที่ใช้คุณสมบัติที่กำหนดเอง — เราเปลี่ยนค่าของคุณสมบัติที่กำหนดเองด้วย CSS ซึ่งหมายความว่าใช้คุณสมบัติที่กำหนดเองเดียวกัน เราสามารถมีค่าต่างกันในตำแหน่งหรือบริบทที่แตกต่างกันในหน้าเดียวกัน

ทั่วโลกกับท้องถิ่น

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

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

นี่คือสิ่งที่เราคุ้นเคยใน CSS เราได้พัฒนาระบบการออกแบบ หลักการตั้งชื่อและไลบรารี JavaScript ทั้งหมดเพื่อช่วยในการแยกส่วนประกอบภายในเครื่องและองค์ประกอบการออกแบบทั่วโลก คุณสมบัติที่กำหนดเองมีตัวเลือกใหม่ในการจัดการกับปัญหาเก่านี้

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

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

ตัวแปรทั่วโลกมีแนวโน้มที่จะคงที่

มีข้อยกเว้นเล็กๆ น้อยๆ สองสามข้อ แต่โดยทั่วไปแล้ว สิ่งที่ทั่วโลกส่วนใหญ่ใน CSS นั้นคงที่เช่นกัน

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

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

ตัวแปรคงที่ในเครื่องนั้นใช้ได้ (บางครั้ง)

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

ตัวแปรสแตติกในเครื่องนั้นใช้ได้อย่างสมบูรณ์ในหลายสถานการณ์ ฉันใช้ตัวแปรตัวประมวลผลล่วงหน้าในไฟล์ส่วนประกอบเป็นส่วนใหญ่เพื่อความสะดวกของนักพัฒนา

พิจารณาตัวอย่างคลาสสิกของส่วนประกอบปุ่มที่มีขนาดแตกต่างกัน

ปุ่ม

scss ของฉันอาจมีลักษณะดังนี้:

 $button-sml: 1em; $button-med: 1.5em; $button-lrg: 2em; .btn { // Visual styles } .btn-sml { font-size: $button-sml; } .btn-med { font-size: $button-med; } .btn-lrg { font-size: $button-lrg; }

เห็นได้ชัดว่า ตัวอย่างนี้จะเหมาะสมกว่าถ้าฉันใช้ตัวแปรหลายครั้งหรือได้รับค่าระยะขอบและช่องว่างภายในจากตัวแปรขนาด อย่างไรก็ตาม ความสามารถในการสร้างต้นแบบขนาดต่างๆ ได้อย่างรวดเร็วอาจเป็นเหตุผลที่เพียงพอ

เนื่องจากตัวแปรสแตติกส่วนใหญ่เป็นแบบโกลบอล ฉันชอบแยกความแตกต่างของตัวแปรสแตติกที่ใช้ภายในส่วนประกอบเท่านั้น ในการทำเช่นนี้ คุณสามารถนำหน้าตัวแปรเหล่านี้ด้วยชื่อส่วนประกอบ หรือคุณสามารถใช้คำนำหน้าอื่น เช่น c-variable-name สำหรับส่วนประกอบ หรือ l-variable-name สำหรับ local คุณสามารถใช้คำนำหน้าอะไรก็ได้ตามต้องการ หรือจะใช้คำนำหน้าตัวแปรส่วนกลางก็ได้ ไม่ว่าคุณจะเลือกอะไร การแยกความแตกต่างโดยเฉพาะอย่างยิ่งหากแปลง codebase ที่มีอยู่ไปใช้คุณสมบัติที่กำหนดเองจะเป็นประโยชน์

เมื่อใดควรใช้คุณสมบัติที่กำหนดเอง

หากใช้ตัวแปรสแตติกภายในส่วนประกอบได้ เราควรใช้คุณสมบัติที่กำหนดเองเมื่อใด การแปลงตัวแปรตัวประมวลผลล่วงหน้าที่มีอยู่เป็นคุณสมบัติที่กำหนดเองมักจะไม่สมเหตุสมผล ท้ายที่สุดแล้ว เหตุผลสำหรับคุณสมบัติที่กำหนดเองนั้นแตกต่างอย่างสิ้นเชิง คุณสมบัติที่กำหนดเองเหมาะสมเมื่อเรามีคุณสมบัติ CSS ที่เปลี่ยนแปลงโดยสัมพันธ์กับเงื่อนไขใน DOM โดยเฉพาะอย่างยิ่งเงื่อนไขแบบไดนามิก เช่น :focus , :hover , การสืบค้นสื่อ หรือ JavaScript

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

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

หมายเหตุ : คุณทราบหรือไม่ว่า $var เป็นค่าที่ถูกต้องสำหรับคุณสมบัติที่กำหนดเอง Sass เวอร์ชันล่าสุดรู้จักสิ่งนี้ ดังนั้นเราจึงจำเป็นต้องสอดแทรกตัวแปรที่กำหนดให้กับคุณสมบัติที่กำหนดเอง เช่น #{$var} สิ่งนี้บอก Sass ว่าคุณต้องการส่งออกค่าของตัวแปร แทนที่จะเป็นเพียง $var ในสไตล์ชีต สิ่งนี้จำเป็นสำหรับสถานการณ์เช่นคุณสมบัติที่กำหนดเองเท่านั้น โดยที่ชื่อตัวแปรสามารถเป็น CSS ที่ถูกต้องได้เช่นกัน

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

 $button-sml: 1em; $button-med: 1.5em; $button-lrg: 2em; .btn { --button-size: #{$button-sml}; } @media screen and (min-width: 600px) { .btn-med { --button-size: #{$button-med}; } .btn-lrg { --button-size: #{$button-lrg}; } } .btn { font-size: var(--button-size); }

ที่นี่ฉันสร้างคุณสมบัติกำหนดเองเดียว: --button-size คุณสมบัติที่กำหนดเองนี้เริ่มกำหนดขอบเขตให้กับองค์ประกอบปุ่มทั้งหมดโดยใช้คลาส btn จากนั้นฉันก็เปลี่ยนค่าของ --button-size สูงกว่า 600px สำหรับคลาส btn-med และ btn-lrg สุดท้าย ฉันใช้คุณสมบัติที่กำหนดเองนี้กับองค์ประกอบปุ่มทั้งหมดในที่เดียว

อย่าฉลาดเกินไป

ลักษณะแบบไดนามิกของคุณสมบัติที่กำหนดเองทำให้เราสร้างส่วนประกอบที่ชาญฉลาดและซับซ้อนได้

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

คุณสมบัติที่กำหนดเองจะไม่ (และไม่ควร) ได้รับการยกเว้นจากการทดลองประเภทนี้ และฉันหวังว่าจะได้เห็นตัวอย่างที่ชาญฉลาดมากมาย แต่ในระยะยาว โค้ดที่อ่านได้และบำรุงรักษาได้จะชนะนามธรรมที่ชาญฉลาดเสมอ (อย่างน้อยก็ในเวอร์ชันที่ใช้งานจริง)

ฉันได้อ่านบทความที่ยอดเยี่ยมเกี่ยวกับหัวข้อนี้ในสื่อ Free Code Camp เมื่อเร็วๆ นี้ เขียนโดย Bill Sourour และมีชื่อว่า Don't Do It At Runtime ทำในเวลาออกแบบ” แทนที่จะถอดความข้อโต้แย้งของเขา ฉันจะให้คุณอ่าน

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

ตัวอย่างหนึ่งที่แสดงให้เห็นสิ่งนี้สำหรับฉันเมื่อเร็ว ๆ นี้คือ:

 :root { --font-scale: 1.2; --font-size-1: calc(var(--font-scale) * var(--font-size-2)); --font-size-2: calc(var(--font-scale) * var(--font-size-3)); --font-size-3: calc(var(--font-scale) * var(--font-size-4)); --font-size-4: 1rem; }

สิ่งนี้สร้างมาตราส่วนแบบแยกส่วน มาตราส่วนแบบแยกส่วนคือชุดของตัวเลขที่เกี่ยวข้องกันโดยใช้อัตราส่วน มักใช้ในการออกแบบและพัฒนาเว็บเพื่อกำหนดขนาดตัวอักษรหรือระยะห่าง

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

ซึ่งหมายความว่าอัตราส่วนจะถูกคำนวณ ณ รันไทม์ และคุณสามารถเปลี่ยนได้โดยการอัปเดตเฉพาะค่าของคุณสมบัติ --font-scale ตัวอย่างเช่น:

 @media screen and (min-width: 800px) { :root { --font-scale: 1.33; } }

วิธีนี้เป็นวิธีที่ชาญฉลาด รัดกุม และเร็วกว่าการคำนวณค่าทั้งหมดอีกครั้ง หากคุณต้องการเปลี่ยนมาตราส่วน เป็นสิ่งที่ฉันจะ ไม่ ทำในรหัสการผลิต

แม้ว่าตัวอย่างข้างต้นจะมีประโยชน์สำหรับการสร้างต้นแบบ แต่ในการใช้งานจริง ฉันอยากเห็นสิ่งนี้มากกว่า:

 :root { --font-size-1: 1.728rem; --font-size-2: 1.44rem; --font-size-3: 1.2em; --font-size-4: 1em; } @media screen and (min-width: 800px) { :root { --font-size-1: 2.369rem; --font-size-2: 1.777rem; --font-size-3: 1.333rem; --font-size-4: 1rem; } }

คล้ายกับตัวอย่างในบทความของ Bill ฉันพบว่าการดูว่าค่าที่แท้จริงคืออะไร เราอ่านโค้ดมากกว่าที่เราเขียนหลายครั้ง และค่าส่วนกลาง เช่น ขนาดฟอนต์เปลี่ยนแปลงไม่บ่อยนักในการผลิต

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

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

เปลี่ยนค่าไม่ใช่ตัวแปร

เปลี่ยนค่าไม่ใช่ตัวแปรเป็นหนึ่งในกลยุทธ์ที่สำคัญที่สุดสำหรับการใช้คุณสมบัติที่กำหนดเองอย่างมีประสิทธิภาพ

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

ในตัวอย่างนี้ เรามีคุณสมบัติแบบกำหนดเองสองคุณสมบัติที่ใช้กับส่วนประกอบตัวอย่าง ฉันเปลี่ยนจากการใช้ค่า --font-size-small เป็น --font-size-large ขึ้นอยู่กับขนาดหน้าจอ

 :root { --font-size-small: 1.2em; --font-size-large: 2em; } .example { font-size: var(--font-size-small); } @media screen and (min-width: 800px) { .example { font-size: var(--font-size-large); } }

วิธีที่ดีกว่าในการทำเช่นนี้คือการกำหนดคุณสมบัติที่กำหนดเองรายการเดียวซึ่งกำหนดขอบเขตไว้ที่ส่วนประกอบ จากนั้นใช้คิวรีสื่อหรือตัวเลือกอื่นๆ เปลี่ยนค่า

 .example { --example-font-size: 1.2em; } @media screen and (min-width: 800px) { .example { --example-font-size: 2em; } }

สุดท้ายนี้ ในที่เดียว ฉันใช้ค่าของคุณสมบัติที่กำหนดเองนี้:

 .example { font-size: var(--example-font-size); }

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

การแยกระหว่างการประกาศตัวแปรและการประกาศคุณสมบัตินี้เป็นการจงใจ มีเหตุผลหลายประการ แต่ข้อดีจะชัดเจนที่สุดเมื่อคิดถึงการออกแบบที่ตอบสนอง

การออกแบบที่ตอบสนองด้วยคุณสมบัติที่กำหนดเอง

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

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

ถ้ามันเปลี่ยนแปลง มันก็เป็นตัวแปร

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

จากนั้น คุณสามารถย้ายสิ่งนี้ไปพร้อมกับกฎของสื่อ สถานะโฮเวอร์ หรือตัวเลือกไดนามิกใดๆ ที่กำหนดการเปลี่ยนแปลงค่า ไปที่ด้านบนสุดของเอกสาร

แยกตรรกะออกจากการออกแบบ

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

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

ลอจิกพับ

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

CSS ครึ่งหน้าล่างนั้นตรงไปตรงมาและมีการประกาศอย่างสูงและอ่านง่าย รู้สึกเหมือน CSS ก่อนการสืบค้นสื่อและความซับซ้อนที่จำเป็นอื่น ๆ ของ CSS สมัยใหม่

มาดูตัวอย่างง่ายๆ ของระบบกริด flexbox แบบหกคอลัมน์:

 .row { --row-display: block; } @media screen and (min-width: 600px) { .row { --row-display: flex; } }

คุณสมบัติที่กำหนดเอง --row-display เริ่มแรกตั้งค่าให้ block สูงกว่า 600px โหมดการแสดงผลถูกตั้งค่าเป็น flex

ครึ่งหน้าล่างอาจมีลักษณะดังนี้:

 .row { display: var(--row-display); flex-direction: row; flex-wrap: nowrap; } .col-1, .col-2, .col-3, .col-4, .col-5, .col-6 { flex-grow: 0; flex-shrink: 0; } .col-1 { flex-basis: 16.66%; } .col-2 { flex-basis: 33.33%; } .col-3 { flex-basis: 50%; } .col-4 { flex-basis: 66.66%; } .col-5 { flex-basis: 83.33%; } .col-6 { flex-basis: 100%; }

เรารู้ทันทีว่า --row-display เป็นค่าที่เปลี่ยนแปลง ในขั้นต้น จะเป็น block ดังนั้นค่า flex จะถูกละเว้น

ตัวอย่างนี้ค่อนข้างง่าย แต่ถ้าเราขยายให้รวมคอลัมน์ความกว้างที่ยืดหยุ่นได้ซึ่งเติมพื้นที่ที่เหลือ ก็มีแนวโน้มว่าจะต้องแปลงค่า flex-grow , flex-shrink และ flex-basis เป็นคุณสมบัติที่กำหนดเอง คุณสามารถลองทำสิ่งนี้หรือดูตัวอย่างโดยละเอียดเพิ่มเติมได้ที่นี่

คุณสมบัติที่กำหนดเองสำหรับธีม

ฉันมักจะโต้แย้งกับการใช้คุณสมบัติที่กำหนดเองสำหรับตัวแปรไดนามิกทั่วโลก และหวังว่าจะเป็นนัยว่าการแนบคุณสมบัติที่กำหนดเองเข้ากับตัวเลือก :root นั้นในหลายกรณีถือว่าเป็นอันตราย แต่กฎทุกข้อมีข้อยกเว้น และสำหรับคุณสมบัติที่กำหนดเอง มันคือการกำหนดธีม

การใช้คุณสมบัติที่กำหนดเองทั่วโลกอย่างจำกัดจะทำให้การสร้างธีมง่ายขึ้นมาก

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

แอป Google Keep

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

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

ใช้ประโยชน์จากคุณสมบัติไดนามิกทั่วโลก

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

 :root { --THEME-COLOR: var(--user-theme-color, #d33a2c); }

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

หลีกเลี่ยงการตั้งค่า Global Dynamic Properties โดยตรง

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

ตัวอย่างข้างต้นตั้งค่าของ --THEME-COLOR เป็นค่า --user-theme-color หากมี หากไม่ได้ตั้งค่า --user-theme-color ค่าของ #d33a2c จะถูกนำมาใช้ ด้วยวิธีนี้ เราไม่จำเป็นต้องจัดเตรียมทางเลือกสำรองทุกครั้งที่ใช้ --THEME-COLOR

คุณอาจคาดหวังในตัวอย่างด้านล่างว่าพื้นหลังจะถูกตั้งค่าเป็น green อย่างไรก็ตาม ค่าของ --user-theme-color ยังไม่ได้ตั้งค่าบนองค์ประกอบรูท ดังนั้นค่าของ --THEME-COLOR จึงไม่เปลี่ยนแปลง

 :root { --THEME-COLOR: var(--user-theme-color, #d33a2c); } body { --user-theme-color: green; background: var(--THEME-COLOR); }

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

หากเราต้องการเปิดเผยคุณสมบัติเฉพาะสำหรับการสืบทอด เราสามารถแทนที่ :root ตัวเลือกด้วยตัวเลือก * :

 * { --THEME-COLOR: var(--user-theme-color, #d33a2c); } body { --user-theme-color: green; background: var(--THEME-COLOR); }

ตอนนี้ ค่าของ --THEME-COLOR จะถูกคำนวณใหม่สำหรับทุกองค์ประกอบ ดังนั้นจึงสามารถใช้ค่าท้องถิ่นของ --user-theme-color ได้ กล่าวคือ สีพื้นหลังในตัวอย่างนี้จะเป็น green

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

กำลังอัปเดตคุณสมบัติที่กำหนดเองด้วย JavaScript

หากคุณต้องการตั้งค่าคุณสมบัติที่กำหนดเองโดยใช้ JavaScript มี API ที่ค่อนข้างเรียบง่ายและมีลักษณะดังนี้:

 const elm = document.documentElement; elm.style.setProperty('--USER-THEME-COLOR', 'tomato');

ที่นี่ฉันกำลังตั้งค่า --USER-THEME-COLOR บนองค์ประกอบเอกสารหรือกล่าวอีกนัยหนึ่งคือองค์ประกอบ :root ที่องค์ประกอบทั้งหมดจะสืบทอดมา

นี่ไม่ใช่ API ใหม่ มันเป็นวิธี JavaScript เดียวกันสำหรับการอัปเดตสไตล์บนองค์ประกอบ นี่คือรูปแบบอินไลน์ ดังนั้นพวกมันจะมีความจำเพาะที่สูงกว่า CSS ปกติ

ซึ่งหมายความว่าง่ายต่อการใช้การปรับแต่งในเครื่อง:

 .note { --note-color: #eaeaea; } .note { background: var(--note-color); }

ที่นี่ฉันตั้งค่าเริ่มต้นสำหรับ --note-color และกำหนดขอบเขตเป็นองค์ประกอบ . .note ฉันแยกการประกาศตัวแปรแยกจากการประกาศคุณสมบัติ แม้ในตัวอย่างง่ายๆ นี้

 const elm = document.querySelector('#note-uid'); elm.style.setProperty('--note-color', 'yellow');

จากนั้นฉันกำหนดเป้าหมายอินสแตนซ์เฉพาะขององค์ประกอบ .note และเปลี่ยนค่าของคุณสมบัติที่กำหนดเอง --note-color สำหรับองค์ประกอบนั้นเท่านั้น ตอนนี้จะมีความจำเพาะสูงกว่าค่าเริ่มต้น

คุณสามารถดูว่าสิ่งนี้ทำงานอย่างไรกับตัวอย่างนี้โดยใช้ React การกำหนดค่าตามความชอบของผู้ใช้เหล่านี้สามารถบันทึกในที่จัดเก็บในตัวเครื่องหรือในฐานข้อมูลในกรณีของแอพพลิเคชั่นขนาดใหญ่

การจัดการสีด้วยคุณสมบัติที่กำหนดเอง

นอกจากค่าฐานสิบหกและสีที่มีชื่อแล้ว CSS ยังมีฟังก์ชันสี เช่น rgb() และ hsl() สิ่งเหล่านี้ช่วยให้เราสามารถระบุองค์ประกอบแต่ละส่วนของสีได้ เช่น เฉดสีหรือความสว่าง คุณสมบัติที่กำหนดเองสามารถใช้ร่วมกับฟังก์ชันสีได้

 :root { --hue: 25; } body { background: hsl(var(--hue), 80%, 50%); }

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

 darken($base-color, 10%); lighten($base-color, 10%); desaturate($base-color, 20%);

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

เราได้เห็นแล้วว่าคุณสมบัติที่กำหนดเองสามารถใช้ได้ในฟังก์ชันสีที่มีอยู่ เช่น rgb() และ hsl() แต่ก็สามารถใช้ใน calc() ได้เช่นกัน ซึ่งหมายความว่าเราสามารถแปลงจำนวนจริงเป็นเปอร์เซ็นต์ได้โดยการคูณมัน เช่น calc(50 * 1%) = 50%

 :root { --lightness: 50; } body { background: hsl(25, 80%, calc(var(--lightness) * 1%)); }

เหตุผลที่เราต้องการจัดเก็บค่าความสว่างเป็นจำนวนจริงคือเพื่อให้เราสามารถจัดการกับการคำนวณด้วยการ calc ก่อนที่จะแปลงเป็นเปอร์เซ็นต์ ตัวอย่างเช่น ถ้าฉันต้องการทำให้สีมืดลง 20% ฉันสามารถคูณความสว่างของสีด้วย 0.8 เราสามารถทำให้อ่านง่ายขึ้นเล็กน้อยโดยแยกการคำนวณความสว่างออกเป็นคุณสมบัติที่กำหนดเองที่มีขอบเขตในเครื่อง:

 :root { --lightness: 50; } body { --lightness: calc(var(--lightness * 0.8)); background: hsl(25, 80%, calc(var(--lightness) * 1%)); }

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

ลดความซับซ้อนของธีม

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

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

คุณสมบัติที่กำหนดเองยังช่วยให้สามารถย้ายความซับซ้อนของธีมไปยัง CSS และความซับซ้อนนี้อาจส่งผลเสียต่อความสามารถในการบำรุงรักษา CSS ของคุณ ดังนั้นอย่าลืมทำให้ง่ายในทุกที่ที่ทำได้

ใช้คุณสมบัติที่กำหนดเองวันนี้

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

ฉันใช้เครื่องมือที่เรียกว่า postcss-css-variables เพื่อแปลงคุณสมบัติส่วนใหญ่ของคุณสมบัติที่กำหนดเองให้เป็นการแสดงโค้ดแบบคงที่ เครื่องมืออื่นที่คล้ายคลึงกันจะละเว้นคุณสมบัติที่กำหนดเองภายในการสืบค้นสื่อหรือตัวเลือกที่ซับซ้อน โดยถือว่าคุณสมบัติที่กำหนดเองเหมือนกับตัวแปรตัวประมวลผลล่วงหน้า

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

กำลังโหลดสไตล์ชีตที่ถูกต้อง

คุณสามารถใช้ postCSS ได้หลายวิธี ฉันใช้กระบวนการ gulp เพื่อรวบรวมสไตล์ชีตที่แยกจากกันสำหรับเบราว์เซอร์ที่ใหม่กว่าและเก่ากว่า งาน gulp รุ่นง่ายของฉันมีลักษณะดังนี้:

 import gulp from "gulp"; import sass from "gulp-sass"; import postcss from "gulp-postcss"; import rename from "gulp-rename"; import cssvariables from "postcss-css-variables"; import autoprefixer from "autoprefixer"; import cssnano from "cssnano"; gulp.task("css-no-vars", () => gulp .src("./src/css/*.scss") .pipe(sass().on("error", sass.logError)) .pipe(postcss([cssvariables(), cssnano()])) .pipe(rename({ extname: ".no-vars.css" })) .pipe(gulp.dest("./dist/css")) ); gulp.task("css", () => gulp .src("./src/css/*.scss") .pipe(sass().on("error", sass.logError)) .pipe(postcss([cssnano()])) .pipe(rename({ extname: ".css" })) .pipe(gulp.dest("./dist/css")) );

สิ่งนี้ส่งผลให้ไฟล์ CSS สองไฟล์: ไฟล์ปกติที่มีคุณสมบัติที่กำหนดเอง ( styles.css ) และอีกไฟล์สำหรับเบราว์เซอร์รุ่นเก่า ( styles.no-vars.css ) ฉันต้องการให้ IE10 และ 11 ให้บริการ styles.no-vars.css และเบราว์เซอร์อื่นๆ เพื่อรับไฟล์ CSS ปกติ

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

การแสดงสไตล์ชีตอื่นอย่างชาญฉลาดและการหลีกเลี่ยงเนื้อหาที่ไม่ได้จัดสไตล์อย่างรวดเร็วไม่ใช่เรื่องง่าย หากคุณไม่ต้องการคุณสมบัติไดนามิกของคุณสมบัติแบบกำหนดเอง คุณสามารถพิจารณาให้บริการเบราว์เซอร์ styles.no-vars.css และใช้คุณสมบัติแบบกำหนดเองเป็นเครื่องมือในการพัฒนา

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

 <head> <style> /* inlined critical CSS */ </style> <script> loadCSS('non-critical.css'); </script> </head>

เราสามารถขยายให้โหลดได้ทั้ง styles.css หรือ styles.no-vars.css ขึ้นอยู่กับว่าเบราว์เซอร์รองรับคุณสมบัติที่กำหนดเองหรือไม่ เราสามารถตรวจพบการสนับสนุนเช่นนี้:

 if ( window.CSS && CSS.supports('color', 'var(--test)') ) { loadCSS('styles.css'); } else { loadCSS('styles.no-vars.css'); }

บทสรุป

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

เป็นการทำความเข้าใจความแตกต่างระหว่างตัวแปรไดนามิกและสแตติกใน CSS รวมถึงกฎง่ายๆ สองสามข้อ:

  1. แยกตรรกะออกจากการออกแบบ
  2. หากคุณสมบัติ CSS เปลี่ยนไป ให้พิจารณาใช้คุณสมบัติที่กำหนดเอง
  3. เปลี่ยนค่าของคุณสมบัติแบบกำหนดเอง ไม่ใช่คุณสมบัติแบบกำหนดเองที่ใช้
  4. ตัวแปรส่วนกลางมักจะเป็นแบบคงที่

If you follow these conventions, you will find that working with custom properties is a whole lot easier than you think. This might even change how you approach CSS in general.

อ่านเพิ่มเติม

  • “It's Time To Start Using Custom Properties,” Serg Hospodarets
    A general introduction to the syntax and the features of custom properties.
  • “Pragmatic, Practical, And Progressive Theming With Custom Properties,” Harry Roberts
    More useful information on theming.
  • Custom Properties Collection, Mike Riethmuller on CodePen
    A number of different examples you can experiment with.