В этой публикации мне хотелось бы поделиться с вами переводом статьи с очень интересной техникой отзывчивой верстки, которую я использовал своем последнем проекте. Она помогла мне сэкономить много времени и упростила мою работу. Если вам стало интересно, в чем же секрет данного приема, прошу под кат.
Перевод
Целью данной статьи является получение значения размера шрифта, которое плавно переходит от 14px при ширине окна браузера 769px до 24px для ширины окна браузера 2048px.
Прежде всего, давайте разберемся с определением адаптивного элемента DOM. Адаптивные элементы должны отвечать изменениям размера области просмотра (viewport size). То есть, когда я уменьшаю или увеличиваю размер окна, адаптивный DOM-элемент должен отвечать на эти изменения четко определенным образом.
С помощью медиа-запросов CSS3 мы можем отвечать изменениям экрана в самом CSS. Большую часть времени это брейкпойнты (breakpoints) 480px, 768px и 769px. Они подходят для большинства веб-приложений. Но что, если мы сможем пойти дальше 3, 4, 5 брейкпойнтов? Что если мы сможем отвечать на каждое изменение в 1px окна браузера начиная от 2048px и заканчивая 1px. Это значит, что мы можем создать объявления в CSS, которые отвечают на мои изменения окна браузера с 2048px до 2047px, тем самым отвечая на каждое изменение в 1px до значения в 0px.
Благодаря функции calc в CSS3 и единиц измерения области просмотра (vh, vw) мы можем добиться такой функциональности.
Функция calc позволяет вам производить вычисления значений CSS свойств.
Единицы измерения области просмотра представлены, как проценты от видимой части веб-страницы. Это все окно браузера минус адресная строка, полоса прокрутки, вкладки и так далее.
К счастью, calc и единицы измерения области просмотра поддерживаются вплоть до IE9.
html {
font-size: 1vh;
}
В примере выше, если ширина браузера минус полоса прокрутки будет 1800px, размер шрифта будет равен 18px, то есть 1% от 1800. С этим все окей, но на экране в 800px размер шрифта будет равен 8px. Это не то, чего мы хотим.
Благодаря некоторым умным расчетам, которые возможны с помощью функции calc, мы можем преодолеть эту проблему.
Если вы писали на Javascript или другом похожем языке программирования,
есть хороший шанс, что вы сталкивались с похожим математическим выражением ниже. Если нет, я постараюсь объяснить его дальше.
Прим. переводчика: в оригинальной статье в этом месте содержится некоторая неточность, которая исправлена при переводе
(Math.random() * (2048 - 769) + 769)
Это отрывок Javascript кода и все, что он делает — это возвращает число в диапазоне от 769 до 2048. Math.random() генерирует случайное число между 0 и 0.9999999999999999. Мы берем это число и умножаем на разницу между 2048 и 769, которая равна 1279. Это гарантирует, что случайное число * 1279+769, всегда вернет значение между 769 и 2048. Вы можете попробовать это самостоятельно, 0*(1279)+769 равно 769 и 0.999999999999*(1279)+769 возвращает 2047.999999998721.
Теперь у нас есть базис для наших дальнейших вычислений.
В нашем случае мы хотим, чтобы размер шрифта был в диапазоне от 14px до 24px, то есть размер диапазона равен 10px и наша база равна 14px. Мы хотим генерировать случайное число между 0 и 0.999999999999, умножить его на 10 и прибавить к нему 14. Так что, 0*10+14 равно 14 и 0.9999*10+14 равно 23,9999, но у нас нет доступа к Javascript Math.random внутри нашего CSS. Как же в таком случае сгенерировать случайное число, которое нам нужно?
Давайте посмотрим на то, что у нас есть. С помощью единицы измерения VW, мы можем динамически получать ширину окна с помощью 100vw. Выходит, что 100vw на экране 1366px равно 1366px, на экране 1560px равно 1560px, без необходимости жестко записывать в коде значение в пикселях.
С нашим целевым минимальным значение ширины (769px), максимальным значением ширины (2048px) и динамически вычисляемым значением ширины (100vw), мы вооружены тем, что нам нужно для генерации случайного числа между 0 и 0.999999999999. Просто вычисляя (100vw?—?769px)/2048px мы можем генерировать любое значение от 0 и выше, в зависимости от значения 100vw. Так, если ширина области просмотра пользователя будет 1800px, (100vw?—?769px)/2048px вычисляется как (1800px?—?769px)/2048px в браузере и равно 0.50341796875. У нас есть наше случайное число. Теперь мы можем умножить 0.50341796875 на 10 (помните наш диапазон?), что в результате будет 5.0341796875. Финальным шагом будет прибавить к 5.0341796875 14px, что в результате будет 19.0341796875px, как размер шрифта для пользователя с шириной области просмотра в 1800px.
Финальная формула может быть записана, как:
html {
font-size: minimumPixel + range * ((viewportWidth - minScreenWidth) / maxScreenWidth)
}
/* Example */
html {
font-size: calc(14px + 10 * ((100vw - 769px) / 2048));
}
Так что вместо того, что бы обслуживать все размеры экранов между 769px и 2048px одним и тем же размером шрифта (обычно 18px), мы можем динамически обслуживать пользователей с помощью более подходящего диапазона с 14px до 24px.
Это может быть скомбинировано с медиа-запросами, что бы достичь максимально возможной адаптивности.
/* Example */
/* Mobile and Tablet */
@media (max-width: 768px) {
html {
font-size: calc(16px + 2 * ((100vw - 360px) / 768));
}
}
/* Laptop and Desktops screens */
@media (min-width: 769px) {
html {
font-size: calc(14px + 10 * ((100vw - 769px) / 2048));
}
}
/* Excessively large screens */
html {
font-size: 36px;
}
Это может быть применено не только к размеру шрифта, но и к паддингам, марджинам и размерам ширины, которые будут растягиваться и сжиматься вместе с изменением ширины области просмотра в большую или меньшую сторону.
Я надеюсь, что вам понравилась статья и в том числе надеюсь, что вы будете использовать эту технику в ваших проектах.
Прим. переводчика:
В своей следующей статье я постараюсь поделиться с вами своим опытом использования этой техники в реальном проекте, на что стоит обратить внимание и какие изменения я внес в этот прием для своего проекта.
Следующая статья: TV first, отзывчивая типографика или как не забыть о всех размерах девайсов
nin-jin
Пожалуйста, не надо на маленьких экранах уменьшать шрифты. Пользователь ставит в настройках системы тот размер шрифта, который ему комфортно читать. Используйте это значение. И наоборот, не надо вываливать на больших экранах гигантские буквы — их так же не комфортно читать. Вообще, размер шрифта должен зависеть от размера экрана примерно никак.
CodeShaman Автор
Все таки я не соглашусь с тем, что размер шрифта зависит от размера экрана примерно никак. Отображать один и тот же размер шрифта на экране iphone 5 и на экране широкоформатного телевизора вряд ли уместно. Если я, конечно, правильно понял о чем Вы.
У каждого приема есть свои нюансы и особенности, в том числе и свои ограничения. Нельзя сказать, что это универсальная техника для всех на все случаи жизни. В моем приложении это сработало и об этом я хочу рассказать в следующей своей публикации. В том числе и про нюансы и ограничения этого приема, с которыми можно столкнуться.
nin-jin
Вы не теоретизируйте, а проверьте как показывается один и тот же "размер" шрифта на разных девайсах. Везде разные "css пиксели".
CodeShaman Автор
Не очень понимаю, что значит "не теоретизируйте" в данном контексте. И как утверждение: "везде разные "css пиксели"" связано с тем, что пользователю с экраном iphone 5 и широкоформатного телевизора нужно показывать один шрифт. Если Вы клоните к тому, что на телевизоре 4K размер шрифта 14px будет выглядеть так же, как и на iphone 5 (из-за разного размера этих пикселей) и давать одинаковый UX, то из исходя чисто из практики это далеко не так.
nin-jin
Именно к этому и клоню. Если на каком-то телевизоре размер css-пикселей не является удобочитаемым, то это проблема конкретной модели и у неё эти проблемы на всех сайтах.
CodeShaman Автор
То есть Вы всегда используете один размер шрифта на все размеры экрана?
nin-jin
Агась.
CodeShaman Автор
Скажу только, что в моей ситуации такой подход я применить не смогу точно. Подробности постараюсь описать в следующей публикации.
Alexufo
На мониторах c плотными пикселями браузеры сами множат на 2 все размеры с пикселями если я правильно помню. Иначе навернулись бы все продукты что были до этих мониторов.
BeInLife
для удобства пользователя есть чудесная настройка font-size. Используя rem'ы (или em'ы), мы привязываемся к этой настройке. Используя вашу технику, мы игнорируем пользователя, который хотел сделать свой шрифт больше/меньше.
CodeShaman Автор
Правильно ли я понял, что имеется ввиду настройка (например) в настольной версии гугл хром: Внешний вид -> размер шрифта? Если да, то к сожалению ее игнорирует хабр, на котором мы сейчас находимся. Или допустим возьмем такой сайт, как google. Попробуйте поставить очень крупный шрифт в настройках и перейти на google.com. На основной странице вы увидите увеличенные буквы, но как только вы наберете что-то в поиске и нажмете enter, страница с выдачей окажется игнорирующей эту настройку. Если пойти еще дальше и перейти в Настроить шрифты -> Размер шрифта и там выставить максимальные 72, то страница с выдачей поведет себя еще интересней. Сами шрифты проигнорируют эту настройку, а вот все расстояния на странице будут сильно увеличены.
Там есть еще одна настройка — Минимальный размер шрифта. На нее будет реагировать и хабр и сайт с этой техникой. Если указанный в ней минимальный размер шрифта будет больше, чем тот, что на посещаемом сайте. Но если размер шрифта на сайте больше, то хабр это тоже проигнорирует. Как и гугл. Но это логично исходя из названия настройки.
BeInLife
Правильно
Almatyn
Как я понимаю в размер по умолчанию для html устанавливаю браузеры. Практически 16px. Оставляем этот размер для всех устройств? Если у юзера на телефоне выбран очень большой шрифт — то браузер телефона будет показывать те-же 16px или увеличит его? Из браузера мы же не имеем доступа к настройкам размера шрифта телефона — а как тогда «использовать это значение»?
Для базового размера шрифта это понятно. А вот для заголовков я бы хотел на больших экранах заголовки побольше. Например для больших экранов h1- 4rem, будет вполне нормально выглядеть, но на телефоне такой заголовок будет слишком.
nin-jin
Не будет.
CodeShaman Автор
Но какое это имеет отношение к системным настройкам шрифта в системе пользователя? Возьмём к примеру IOS и системные настройки TextSize. Изменение системного TextSize в любую сторону никак не влияет на размеры шрифтов на веб-страницах в браузерах IOS.
nin-jin
Поищите соответствующий пункт в настройках браузера.
CodeShaman Автор
Настройки браузера != настройки системы пользователя. Вы говорили о том, что нужно брать именно настройки системы. Комментарий Almatyn, как я понимаю, был именно об этом.
ivan386
В настройках Firefox под Android есть пункт "Использовать системный размер шрифта".
CodeShaman Автор
IOS в данный момент не предоставляет такой возможности пользователю. Настройки отображения браузера и настройки шрифтов в системе регулируются отдельно.
Alexufo
Не соглашусь.
Конечно же размер шрифта зависит от экрана. Обе эти сущности основаны на занимаемой площади и контрасте. На большом экране количества информации больше, поэтому заголовки приходится выделять сильнее, чтобы выделять структуру документа. На мобиле это практически не требуется.
Поэтому решения по адаптивности размера и отступов очень и очень хороши. www.npmjs.com/package/rfs
Тут на хабре h1 32px. В мобильной 22px. Ужасно было бы сделать везде h1 заголовки 22px. Это технически абсолютно приемлиемо, но убежден, что статиситически в любом слепом тесте больший размер шрифта на десктопах будет восприниматься как более одобряемый. Так сделано, наверное, в 90% всех популярных сайтов.
nin-jin
В мобильной 24px, а в ленте на десктопе 28px. И эту разницу вы на глаз не заметите. А вот что вы заметите, так это то, что заголовок из 3 слов не влезает по ширине и начинает переноситься.
Alexufo
у меня 20px на мобиле в ленте (пресет iphone 6/7/8)и 28px на десктопе. Но не суть. Разницу в 4px очень не сложно заменить,
а при 8 еще сильнее.
Если говорить о словах, то о каких именно, если о «сказ о css» то и при 40px не перенесется. А если о «сложности синтеза тетрагидропиранилциклопентилтетрагидропиридопиридина» то никуда не влезет.
Влезет или нет это отдельная история. Не думаю, что есть некий универсальный размер куда прям явно можно попасть, чтобы не было висячих строк и смотрелось норм. обычно чуть крупнее основного на мобиле, а то и вообще можно обойтись одним strong иногда, а на десктопе эта минимальная разница не так важна и может быть увеличина 2-4 раза. Накупят себе 32 мониторов. У них там все заголовки как чешуйницы в туалете. Все от идеи.
qant
Согласен. Дико раздражает что некоторые сайты на большом мониторе используют гигантские заголовки отступы и шрифты… Это как читать книгу где шрифт меняется от размера страницы…