Это старая проблема. Когда я впервые заметил ее, меня беспокоил UI-дизайнер. Ну, я тогда только зашел во фронтенд и ничего не понимал. :
Подошел дизайнер со своим мобильным телефоном: Рамки толстые, мой эскиз — 1 пиксель.
Я:? ? ? ? Я написал 1px. Если не верите, посмотрите. (Пока он говорил, он вынул css-код
Дизайнер: Это неправильно. На мой взгляд, граница намного толще, чем у меня. Это выглядит странно (эммм, она действительно пиксельная.
Я: Тогда я изменю его на 0,5 пикселей, и вы сможете посмотреть (я изменил код во время разговора).
Дизайнер посмотрел на это и кивнул, это действительно было намного лучше.
Позже было обнаружено, что тот же код был проблематичным на некоторых машинах Android, из-за чего линия 0,5 пикселя была невидимой.
Это странно. Очевидно, что изменение размера на 0,5 пикселя не решит проблему, но граница в 1 пиксель выглядит намного толще, чем в черновом варианте. В чем причина?
Производительность границы в 1 пиксельЯ напрямую использую CSS, чтобы установить границу в 1 пиксель.
HTML:
<ul class=hairlines> <li>1</li> <li>2</li></ul>
CSS:
* { поля: 0; заполнение: 0; } ul, li {стиль списка: нет } .hairlines { ширина: 300 пикселей; поле: 100 пикселей авто; } .hairlines li { позиция: относительная; граница; -bottom: 1px Solid #cccccc // Установите границу на 1 пиксель }Полученный скриншот выглядит следующим образом:
Он выглядит намного толще, чем эскизный проект. Эскизный вариант должен выглядеть так. Вы можете сравнить:
Решение 1. Псевдокласс + преобразованиеС менталитетом решения проблемы, хотя в то время я еще не задумывался о причине, я все же нашел подходящие решения, используя border-image или box-shadow, которые также могут имитировать желаемый эффект. Эффект границы в 1 пиксель, но лично я считаю, что это не универсальное и не традиционное решение.
Окончательный выбор заключался в использовании метода псевдокласса + преобразования: принцип состоит в том, чтобы удалить границу исходного элемента, затем использовать :before или :after, чтобы переделать границу, и уменьшить масштаб преобразования вдвое. элемент позиционируется относительно, а новая граница позиционируется абсолютно.
html то же, что и выше
CSS выглядит следующим образом:
* { поля: 0; заполнение: 0; } ul, li {стиль списка: нет; .hairlines { ширина: 300 пикселей; поле: 100 пикселей авто; } .hairlines li { позиция: относительная; граница: нет; : 10 пикселей; } .hairlines li:after {content: ''; положение: слева: 0; внизу: 0; #cccccc; ширина: 100%; высота: 1 пиксель; -webkit-transform: масштабY(0,5); -webkit-transform-origin: 0 0;В этом случае нарисованные линии действительно намного тоньше. Обычно я использовал описанный выше метод для решения проблемы границы в 1 пиксель в течение года, но после его использования обнаружил несколько проблем:
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, максимальный масштаб=1, минимальный масштаб=1, масштабируется пользователем =no, width=device-width> <title>Проблема с границей в 1 пиксель на мобильном терминале</title> <style> * { Margin: 0; Padding: 0 } ul, li{ list-style: нет } .lines { ширина: 200 пикселей; поле: 0 авто; } .lines li { граница: 1 пиксель #cccccc; высота строки: 50 пикселей; выравнивание текста: центр; -top: 10px; } .hairlines { ширина: 200 пикселей; поле: 0 auto; 3px; } .hairlines li { высота: 50 пикселей; граница: нет; положение текста: относительное; поле-верх: 10 пикселей } .hairlines li: after {content: ''; : абсолютный; слева: 0; верхняя граница: 1 пиксель #cccccc; ширина границы: 26 пикселей; 200%; высота: 200%; -webkit-transform: Scale(0.5); Transform: Scale(0.5); -webkit-transform-origin: слева вверху; 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? Все ли модели нужно уменьшать вдвое, иными словами, универсальны ли они? Как ответить на этот вопрос?
Это возвращает нас к сути проблемы. Почему он по-прежнему выглядит намного толще, чем обычно, хотя я написал в css 1px?
После проверки информации выясняется, что заданные в css пиксели не соответствуют пикселям устройства один в один. Это значит, что если я укажу в css 1px, то то, что я увижу на мобильном телефоне, может не соответствовать. быть одним пикселем. Ширина, занимаемая точкой.
Пиксель CSS — это абстрактное и относительное понятие. На разных устройствах и в разных средах представленные физические пиксели различаются. На старых устройствах плотность пикселей экрана относительно низкая. Таким образом, пиксель размером в 1 пиксель действительно является физическим. пикселей, но технология быстро развивается. Все экраны современных мобильных телефонов имеют высокое разрешение. Если размер не изменится, экран будет заполнен большим количеством пикселей. В настоящее время пиксель CSS (обычно называемый логическим пикселем) будет соответствовать пикселю. несколько физических пикселей.
Так скольким физическим пикселям соответствует ширина пикселя CSS?
Для этого необходимо указать devicePixelRatio (соотношение пикселей устройства).
devicePixelRatio = физический пиксель/независимый пиксель на устройстве, который можно получить с помощью window.devicePixelRatio. Это соотношение пикселей может точно описать, сколько физических пикселей соответствует ширине пикселя CSS, что фактически соответствует пикселям devicePixelRatio.
Когда атрибут начального масштаба области просмотра равен 1, размер страницы является нормальным, но когда начальный масштаб равен 0,5, страница уменьшается в 1 раз. Устройство с параметром devicePixelRatio, равным 2, изначально имеет ширину 1 CSS-пикселя, что соответствует 2. ширина физических пикселей. После уменьшения ширина 1 пикселя CSS занимает только 1 физический пиксель, то есть достигается настоящий 1 физический пиксель.
Решение 2: rem + область просмотраНа данный момент решение очень ясно: мы можем получить devicePixelRatio устройства во время выполнения и динамически изменить начальный масштаб области просмотра на 1/devicePixelRatio, чтобы гарантировать, что ширина 1 пикселя равна реальному 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>Проблема с границей в 1 пиксель на мобильном терминале</title> <script> (function () { var clientWidth = window.screen.width; var dpr = window.devicePixelRatio; var vp = document.createElement('meta'); document.documentElement.style.fontSize = clientWidth > '20px': 20 * dpr * clientWidth / 360 + ' px'; vp.name = 'окно просмотра'; vp.content = `начальный масштаб = $ {1,0 * 1 / dpr}, максимальный масштаб = $ {1,0 * 1 / dpr}, минимальный масштаб = $ {1,0 * 1 / dpr}, масштабируемый пользователем = нет, ширина = устройство- ширина`; var m = document.getElementsByTagName('meta')[0]; m.parentNode.insertBefore(vp, m); })(); </script> <style> * { поля: 0; заполнение: 0; ul, li {стиль списка: нет; .lines { ширина: 10rem; поля: 0 } .lines li; { граница: 1 пиксель #cccccc высота: 2.5rem; выравнивание текста: центр; 0,6рем; маржа-топ: 0,5рем; } </style></head><body><ul class=lines> <li>1</li> <li>2</li></ul></ тело></html>Полученный эффект можно увидеть на картинке ниже (он более заметен при просмотре на мобильном телефоне):
С вышеизложенной точки зрения, возвращаясь к предыдущим вопросам: 1. Почему ScaleY(0,5)? Откуда у тебя такая цифра 0,5? Все ли модели нужно уменьшать вдвое, иными словами, универсальны ли они? На самом деле, это не обязательно 0,5. На устройстве с dpr, равным 3, на самом деле оно должно быть 0,3333... Это не универсально, поскольку dpr каждого мобильного телефона может быть разным, однако значение 0,5 в методе 1 обычно составляет. по крайней мере тоньше 1 пикселя, поэтому он также может почти соответствовать требованиям дизайнера.
Выше приведено все содержание этой статьи. Я надеюсь, что она будет полезна для изучения всеми. Я также надеюсь, что все поддержат сеть VeVb Wulin.