นี่เป็นปัญหาเก่า เมื่อฉันสังเกตเห็น มันเป็นนักออกแบบ UI ที่เข้ามารบกวนฉัน ตอนนั้นฉันเพิ่งเข้าสู่ที่ทำงานส่วนหน้าและไม่เข้าใจอะไรเลย : :
นักออกแบบมาพร้อมกับโทรศัพท์มือถือของเขา: เส้นขอบเหล่านี้หนา ร่างการออกแบบของฉันคือ 1px
ฉัน:? - - - สิ่งที่ฉันเขียนคือ 1px หากคุณไม่เชื่อลองดูสิ (ขณะที่เขาพูด เขาก็หยิบโค้ด css ออกมา
ดีไซเนอร์: ไม่ถูกต้อง ในสายตาของฉัน ขอบหนากว่าแบบที่ฉันออกแบบมาก มันดูแปลก ๆ (อืม มันเป็นพิกเซลจริงๆ
ฉัน: งั้นฉันจะเปลี่ยนเป็น 0.5px แล้วคุณเข้าไปดูได้ (ฉันเปลี่ยนรหัสตอนพูดแล้ว)
นักออกแบบมองดูแล้วพยักหน้า มันดีขึ้นมากจริงๆ
ต่อมาพบว่ารหัสเดียวกันนี้เป็นปัญหาในเครื่อง Android บางเครื่อง ทำให้มองไม่เห็นบรรทัด 0.5px
มันแปลก เห็นได้ชัดว่าการเปลี่ยนเป็น 0.5px ไม่สามารถแก้ปัญหาได้ แต่เส้นขอบ 1px ดูหนากว่าแบบร่างมาก สาเหตุคืออะไร
ประสิทธิภาพของเส้นขอบ 1pxฉันใช้ css โดยตรงเพื่อตั้งค่าเส้นขอบ 1px
HTML:
<ul class=hairlines> <li>1</li> <li>2</li></ul>
ซีเอสเอส:
* { ระยะขอบ: 0; การขยาย: 0; } ul, li{ ตำแหน่ง: ระยะขอบด้านบน: 10px; -bottom: 1px solid #cccccc; // ตั้งค่าเส้นขอบเป็น 1px }ภาพหน้าจอที่ได้รับมีดังนี้:
มันดูหนากว่าแบบร่างการออกแบบมาก คุณสามารถเปรียบเทียบได้:
โซลูชันที่ 1: คลาสหลอก + การแปลงด้วยความคิดในการแก้ปัญหา แม้ว่าฉันจะไม่ได้คิดถึงเหตุผลอย่างชัดเจนในขณะนั้น แต่ฉันก็ยังพบวิธีแก้ไขที่เกี่ยวข้อง วิธีการบางอย่างที่กล่าวถึงโดยใช้ภาพเส้นขอบหรือเงากล่อง ซึ่งสามารถจำลองเอฟเฟกต์ที่ต้องการได้เช่นกัน เอฟเฟกต์เส้นขอบขนาด 1px แต่โดยส่วนตัวแล้วฉันคิดว่ามันไม่เป็นสากลและไม่ใช่วิธีแก้ปัญหาทั่วไป
ตัวเลือกสุดท้ายคือการใช้วิธีการหลอกคลาส + การแปลง: หลักการคือการลบเส้นขอบขององค์ประกอบดั้งเดิม จากนั้นใช้ :before หรือ :after เพื่อทำซ้ำเส้นขอบ และลดขนาดของการแปลงลงครึ่งหนึ่ง องค์ประกอบอยู่ในตำแหน่งที่ค่อนข้างดี และเส้นขอบใหม่อยู่ในตำแหน่งที่แน่นอน
html เช่นเดียวกับด้านบน
css เป็นดังนี้:
* { ระยะขอบ: 0; } ul, li{ list-style: none; : 10px; } .hairlines li: หลัง { เนื้อหา: ''; ตำแหน่ง: สัมบูรณ์; ซ้าย: 0; #cccccc; ความกว้าง: 100%; -webkit-transform: scaleY(0.5); -webkit-transform-origin: 0 0;ในกรณีนี้ เส้นที่ลากจะบางกว่ามาก โดยทั่วไปฉันใช้วิธีการข้างต้นเพื่อแก้ไขปัญหาเส้นขอบ 1px เป็นเวลาหนึ่งปี แต่หลังจากใช้แล้ว ฉันพบปัญหาหลายประการ:
1.ทำไมถึงมีมาตราส่วนY(0.5)? คุณได้ 0.5 นี่มาได้ยังไง? ทุกรุ่นจำเป็นต้องลดขนาดลงครึ่งหนึ่งหรือไม่ กล่าวคือ เป็นโมเดลสากลหรือไม่
2. ถ้าฉันต้องการวาดเส้นขอบทั้งสี่ของคอนเทนเนอร์พร้อมกันล่ะ?
3.รองรับขอบโค้งมนหรือไม่?
วิธีแก้ไขปัญหาสองข้อหลังสามารถพบได้โดยการแก้ไขโค้ดด้านบน (เพื่อความสะดวกในการดูเอฟเฟกต์ ฉันจึงใส่เอฟเฟกต์ที่ได้รับจากวิธีการเขียนตามปกติและเอฟเฟกต์ที่ได้รับจากการใช้คลาสหลอกเข้าด้วยกัน เพื่อที่ จะเห็นความแตกต่างได้ง่ายกว่า):
<!DOCTYPE html><html lang=en><head> <meta charset=UTF-8> <meta name=viewport content=initial-scale=1, maximum-scale=1, maximum-scale=1, ผู้ใช้ปรับขนาดได้ =no, width=device-width> <title>ปัญหาเส้นขอบ 1px บนเทอร์มินัลมือถือ</title> <style> * { ระยะขอบ: 0; padding: 0; } ul, li{ list-style: ไม่มี; } .lines { ความกว้าง: 200px; ระยะขอบ: 0 อัตโนมัติ; -top: 10px; } .hairlines { ความกว้าง: 200px; ระยะขอบ: 0 อัตโนมัติ; 3px; } .hairlines li{ ความสูง: 50px; line-height: 50px; text-align: center; : สัมบูรณ์ ซ้าย: 0; บน: 0; เส้นขอบ: 1px ทึบ #cccccc; 200%; ความสูง: 200%; -webkit-transform: มาตราส่วน (0.5); -webkit-transform-origin: ด้านบนซ้าย; <body>เส้นหนา<ul class=lines> <li>1</li> <li>2</li></ul>เส้นบาง<ul class=hairlines> <li>3</li> <li>4</li></ul></body></html>การเรนเดอร์ผลลัพธ์จะเป็นดังนี้:
เห็นได้ชัดว่าเส้นขอบด้านล่างบางกว่ามาก และใกล้กับแบบร่างการออกแบบมากขึ้น
1. เหตุใดจึงมีมาตราส่วน Y (0.5) คุณได้ 0.5 นี่มาได้ยังไง? ทุกรุ่นจำเป็นต้องลดขนาดลงครึ่งหนึ่งหรือไม่ กล่าวคือ เป็นโมเดลสากลหรือไม่ จะตอบคำถามนี้อย่างไร?
สิ่งนี้นำเรากลับไปสู่แก่นแท้ของปัญหา ทำไมมันถึงยังดูหนากว่าปกติมากแม้ว่าฉันจะเขียน 1px ใน css แล้วก็ตาม
หลังจากตรวจสอบข้อมูลแล้วปรากฎว่าพิกเซลที่ตั้งไว้ใน css ไม่ตรงกับพิกเซลของอุปกรณ์แบบหนึ่งต่อหนึ่ง ซึ่งหมายความว่าหากฉันระบุ 1px ใน css สิ่งที่ฉันเห็นบนโทรศัพท์มือถืออาจไม่ เป็นหนึ่งพิกเซล ความกว้างครอบครองโดยจุด
พิกเซลของ CSS เป็นแนวคิดที่เป็นนามธรรมและสัมพันธ์กัน ในอุปกรณ์และสภาพแวดล้อมที่แตกต่างกัน พิกเซลทางกายภาพที่แสดงจะแตกต่างกัน ในอุปกรณ์รุ่นเก่า ความหนาแน่นของพิกเซลของหน้าจอค่อนข้างต่ำ ด้วยวิธีนี้ พิกเซลขนาด 1px จึงถือเป็นพิกเซลจริง พิกเซล แต่เทคโนโลยีกำลังพัฒนาอย่างรวดเร็ว ปัจจุบัน หน้าจอโทรศัพท์มือถือมีความละเอียดสูงทั้งหมด หากขนาดไม่เปลี่ยนแปลง หน้าจอจะเต็มไปด้วยพิกเซลมากขึ้น ในเวลานี้ พิกเซล CSS (ปกติเรียกว่า Logical Pixel) จะสอดคล้องกัน พิกเซลทางกายภาพหลายพิกเซล
ความกว้างของพิกเซล CSS สอดคล้องกับฟิสิคัลพิกเซลจำนวนเท่าใด
สิ่งนี้ต้องกล่าวถึง devicePixelRatio (อัตราส่วนพิกเซลของอุปกรณ์)
devicePixelRatio = พิกเซลจริง/พิกเซลอิสระบนอุปกรณ์ ซึ่งสามารถหาได้จาก window.devicePixelRatio อัตราส่วนพิกเซลนี้สามารถอธิบายได้อย่างแน่ชัดว่าจำนวนพิกเซลทางกายภาพที่สอดคล้องกับความกว้างพิกเซลของ CSS ซึ่งจริงๆ แล้วสอดคล้องกับพิกเซลของอุปกรณ์ PixelRatio
เมื่อแอตทริบิวต์มาตราส่วนเริ่มต้นของวิวพอร์ตคือ 1 ขนาดหน้าจะเป็นปกติ แต่เมื่อมาตราส่วนเริ่มต้นคือ 0.5 หน้าจะลดลง 1 เท่า อุปกรณ์ที่มี devicePixelRatio เท่ากับ 2 เดิมจะมีความกว้างพิกเซล 1 CSS พิจารณาความกว้างของพิกเซลจริง 2 พิกเซล หลังจากลดขนาดแล้ว ความกว้างของ 1 พิกเซล CSS จะใช้พื้นที่ 1 พิกเซลของจริงเท่านั้น กล่าวคือ จะได้ 1 พิกเซลจริง
โซลูชันที่ 2: rem + วิวพอร์ตณ จุดนี้ วิธีแก้ไขมีความชัดเจน: เราสามารถรับ devicePixelRatio ของอุปกรณ์ในขณะรันไทม์ และเปลี่ยนสเกลเริ่มต้นของวิวพอร์ตเป็น 1/devicePixelRatio แบบไดนามิก ดังนั้นจึงมั่นใจได้ว่าความกว้างของ 1px คือความกว้างที่แท้จริงของ 1 พิกเซลจริง ใช้ rem ในการดัดแปลงอื่นๆ (เพราะถ้าใช้ px มันจะลดลง)
รหัสมีดังนี้:
<!DOCTYPE html><html lang=en><head> <meta charset=UTF-8> <!--<meta name=viewport content=initial-scale=1, มาตราส่วนสูงสุด=1, มาตราส่วนขั้นต่ำ=1 , user-scalable=no, width=device-width>--> <title>ปัญหาเส้นขอบ 1px บนเทอร์มินัลมือถือ</title> <script> (ฟังก์ชัน () { var clientWidth = window.screen.width; var dpr = window.devicePixelRatio; var vp = document.createElement('meta'); document.documentElement.style.fontSize = ไคลเอนต์กว้าง > '20px' : 20 * dpr * clientWidth / 360 + ' px'; vp.name = 'วิวพอร์ต'; `สเกลเริ่มต้น=${1.0 * 1 / dpr}, สเกลสูงสุด=${1.0 * 1 / dpr}, สเกลขั้นต่ำ=${1.0 * 1 / dpr}, ผู้ใช้ปรับขนาดได้=no, ความกว้าง=อุปกรณ์- width`; var m = document.getElementsByTagName('meta')[0]; m.parentNode.insertBefore(vp, m); })(); </script> <style> * { ระยะขอบ: 0; } .lines li { border: 1px solid #cccccc; ความสูง: 2.5rem; line-height: 2.5rem; 0.6rem; ระยะขอบบน: 0.5rem; } </style></head><body><ul class=lines> <li>1</li> <li>2</li></ul></ ร่างกาย></html>เอฟเฟกต์ที่ได้รับสามารถดูได้ในภาพด้านล่าง (จะชัดเจนยิ่งขึ้นเมื่อดูบนโทรศัพท์มือถือ):
จากมุมมองข้างต้น กลับมาที่คำถามเดิม 1. เพราะเหตุใดจึงมีมาตราส่วนY(0.5)? คุณได้ 0.5 นี่มาได้ยังไง? ทุกรุ่นจำเป็นต้องลดขนาดลงครึ่งหนึ่งหรือไม่ กล่าวคือ เป็นโมเดลสากลหรือไม่ ที่จริงแล้วไม่จำเป็นต้องเป็น 0.5 บนอุปกรณ์ที่มี dpr เท่ากับ 3 จริงๆ แล้วควรจะเป็น 0.3333... ซึ่งไม่เป็นสากลเพราะ dpr ของโทรศัพท์มือถือแต่ละเครื่องอาจแตกต่างกัน อย่างไรก็ตาม โดยทั่วไปแล้ว 0.5 ในวิธีที่ 1 จะเป็นเช่นนั้น อย่างน้อยก็บางกว่า 1px ดังนั้นจึงเกือบจะสามารถตอบสนองความต้องการของนักออกแบบได้
ข้างต้นคือเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการศึกษาของทุกคน ฉันหวังว่าทุกคนจะสนับสนุน VeVb Wulin Network