Страницы

Поиск по вопросам

воскресенье, 24 ноября 2019 г.

Верстка под ретину — как определять плотность пикселя?


Это вопрос из прошлого и поставлен он был несколько странно. Но ответ ниже боле
чем актуален.



Перелопатив с десяток статей я начал осознавать, что ppi - большая палка в колеса. Как с ним бороться, пока не ясно.

Итак, у нас есть элементарная страница: jsfiddle.net

Мы хотим 14px (к примеру) - как основной размер шрифта. Допустим, что так было 
PSD от дизайнера. От этого будем отталкиваться. 

Обварачиваем весь контент в div.font-size-setting, которому выставляем font-size: 1.4em (так как после нормализации у нас было 10px).

Смотрим на страницу с разных устройств:



Будь там iphone4 шрифт и квадратик были бы еще меньше. Проблема, очевидно, в большо
разнице в ppi (pixels per inch) устройств. Обычные мониторы имеют 96ppi. У iphone3 163ppi. У виты 220ppi.

Очевидное решение - это определить ppi устройства и увеличить шрифт. С последни
проблем никаких. Обарачиваем в div.font-size-normalize и в зависимости от dpi выставляем соответствующий шрифт: jsfiddle.net

Получаем:

div.font-size-setting - чтобы выставить размер шрифта от дизайнера,

div.font-size-normalize - делаем этот шрифт одинакового размера (визуально) на всех устройствах.



Яблофон чуть растянул сам шрифт или увеличил расстояниями между строчкам, но по сут
все сходится. Так или иначе, квадратик с размерами в em везде одинаковый, хоть линейкой меряй.

Вопрос в том, как определять ppi?

1.media queries - resolution
Медиа запросы умеют определять не только ширину и высоту, но и много других характеристик
в том числе и dpi (dots per inch). Вообще dpi - бессмысленный параметр для дисплея, так как это параметр для печати принтером, но в нашем случае совпадает с ppi.

Я решил, что не плохо было бы сделать шаг в 0.1em. Это примерно каждые 10ppi. Взя
наши 96ppi за 1em составил табличку и посчитал диапазон так, чтобы интересующие нас  значения были в середине. Составил запросы: 

    @media screen and (min-resolution: 90dpi) and (max-resolution: 100dpi)  {
        .font-size-normalize { font-size: 1em; /* normal desktops */ }
    }
    @media screen and (min-resolution: 101dpi) and (max-resolution: 111dpi)  {
        .font-size-normalize { font-size: 1.1em; }
    }
    @media screen and (min-resolution: 112dpi) and (max-resolution: 122dpi)  {
        .font-size-normalize { font-size: 1.2em; }
    }
  /*...*/
    @media screen and (min-resolution: 158dpi) and (max-resolution: 168dpi)  {
        .font-size-normalize { font-size: 1.7em; /* iphone3 */ }
    }
  /*...*/
    @media screen and (min-resolution: 216dpi) and (max-resolution: 226dpi)  {
        .font-size-normalize { font-size: 2.3em; /* ps vita */ }
    }
  /*...*/
    @media screen and (min-resolution: 322dpi) and (max-resolution: 332dpi)  {
        .font-size-normalize { font-size: 3.4em; /* iphone4 */ }
    }


http://jsfiddle.net/AHzYJ/3/

Последние версии десктопных браузеров проработали медиазапросы. Браузеры iphone
и ps vita не осилили. Думаю последние яблофоны, яблопэды, дройдофоны все же справятся, но тем не менее решение далеко не пуленепробиваемо :(

2.media queries - devicePixelRatio и канонический пиксель
dip - density(device)-independent pixel - что то вроде канонического пикселя. Раве
одному физическому пикселю на 160ppi. С другой стороны мы имеем параметр devicePixelRatio, который может быть использован как аргумент медиа-запроса относительно канонического пикселя: 

@media screen and (device-pixel-ratio: 1) {}


Можно написать аналогичное примеру выше множество запросов:

@media screen and (min-device-pixel-ratio: 1) and (max-device-pixel-ratio: 1.1) {
    .font-size-normalize { font-size: 2.3em; /* ps vita */ }
}


Но у меня ни для одного девайса/компьютера/браузера этого толком сделать не получилось
Такое ощущение, что этот параметр может быть только целочисленным: единица - для iphone3
двойка - для iphone4. Более того, требуются вендерные префиксы, что уже как минимум говорит об отсутвии кросс-браузерности или кросс-девайсности. Еще одна несостыковка в том, что "device-pixel-ratio: 2" (означающий 320ppi) отрабатывает на iphone4, обладающий 326ppi.

3.JS

alert(window.devicePixelRatio);


Думаю, оно работает точно так же как и второй способ. На iphone3 я увидел "1", та
же как в десктопном браузере и на вите, что само собой чушь. На iphone4 высветилось "2", но после предыдущих фэйлов это уже не имеет значение. Еще проблема: тормозилла не справилась и показала undefined.

4.Самописные JS-функции, определяющие ppi.
Что-то типа взять device-width и поделить на width. Это работает на мобильных устройствах
так как нельзя сплющить окно браузера, но в десктопном браузере мы можем просто уменьшить размер окна и все сломается.

В конечном итоге, я не нашел ни одного полнофункционального решения. Думаю, что прост
должно пройти время, пока "device-pixel-ratio: n" будет пониматься всеми. А пока надо придумать как максимизировать количество удачных определений ppi. Ведь описанные выше способы частично, но все же работают.

Кто что думает по этому поводу, какие можетe предложить решения и как можно обобщить вышеуказанные способы в один пусть полурабочий вариант?
    


Ответы

Ответ 1



Спустя какое-то время я пришел к тому, что надо работать по второму предложенном мною способу. Суть рабты примерно следующая. Сайт верстается "как обычно", все размер задаются в пикселях. Только теперь width: 100px не означает ширину в 100 физически пикселей дисплея. Это 100 некоторых абстрахных пикселей (device independent pixel). А дальше операционная система (или браузер) уже сами решают, как показать один такой абстрактный пиксель на дисплее. Помогает им в этом параметр devicePixelRatio. Если этот параметр равен единице, то абстрактный пиксель показывается один в один с физическим пикселем. Если равен двойке, то используется квадрат из четырех пикселей. Если мы возьмем случайный сайт, вообще не оптимизированный под дисплеи с высоко плотностью пикселя, то он никак не сожмется на ретине. Он будет выгялдеть как на обычном дисплее. Получается, что за размерами следить не нужно. Ширины, высоты, бордюры, тени и проче можно задавать в обычных пикселях. И не беспокоится о том, что же там будет на ретине А вот над графикой придется попотеть. Картинки на девайсах с высокой плостностью пикселя выглядят растянутыми. Их надо заменять на картинки увеличенные в соответствующее количество раз. Например. div { background: url(cake.png) no-repeat center top; } @media screen and (-webkit-min-device-pixel-ratio: 2), screen and ( -moz-min-device-pixel-ratio: 2), screen and ( -o-min-device-pixel-ratio: 2), screen and ( min-device-pixel-ratio: 2) { div { background-image: url(cake@2x.png); background-size: 100%; // или вариации } }

Комментариев нет:

Отправить комментарий