Прошу прощения за картинки-сслыки (не хватает репутации) и за "много букав". О проблеме хочется хотя бы просто поговорить :)
Перелопатив с десяток статей я начал осознавать, что 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/
Последние версии десктопных браузеров проработали медиазапросы. Браузеры iphone3 и 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 предложить решения и как можно обобщить вышеуказанные способы в один пусть полурабочий вариант?
Ответ
Спустя какое-то время я пришел к тому, что надо работать по второму предложенному мною способу. Суть рабты примерно следующая. Сайт верстается "как обычно", все размеры задаются в пикселях. Только теперь 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%; // или вариации
}
}
Комментариев нет:
Отправить комментарий