Сайт отображается некорректно из за системного масштабирования, и как с этим быть
Проблема
Неоднократно я сталкивался с тем, что верстая по макету в Figma и указывая точные размеры блоков в пикселях, результат выглядит иначе, значительно крупнее, хотя размер холста совпадает с разрешением моего экрана. Чуть позже я понял - всё дело в том, что у меня в системе установлено масштабирование интерфейса:
![](https://webcf.waybackmachine.org/web/20211113011409/https://habrastorage.org/getpro/habr/upload_files/679/74c/d74/67974cd7494ee7eda8f766d685c9bd29.png)
Из за этого размер видимой области (viewport) при полном экране браузера составляет не 1920px, а всего 1519px.
![](https://webcf.waybackmachine.org/web/20211113011409/https://habrastorage.org/getpro/habr/upload_files/424/7e9/d61/4247e9d6156c08893e574826699d577d.png)
В поисках решения я видел массу различных вариантов, но все они были каким то компромиссом, а хотелось простого и универсального решения, которое можно использовать везде. В конечном итоге я нашёл его, и считаю для себя эту информацию очень ценной, поэтому делюсь с вами - может кого-то эта статья даже выручит. Я был бы рад 😊
Решение
Нам потребуется самая малость JavaScript. Нужно обернуть всё содержимое страницы в один div-контейнер, и указать ему id, пусть это будет container:
<div id="container">
...ваш HTML код...
</div>
В самом конце документа, перед закрывающимся тэгом body мы напишем наш скрипт:
<script>
function forcedOriginalScale( containerId ) {
var App = document.getElementById( containerId ); //получаем div по его id
App.style.zoom = 1 / devicePixelRatio; //устанавливаем масштаб в зависимости от pixel-ratio
}
document.addEventListener( //когда DOM загрузился
"DOMContentLoaded",
function() {
forcedOriginalScale('container'); //выполняем функцию, передаём в неё id нашего контейнера
}
);
</script>
Наша функция универсальна тем, что в неё можно передать id любого блока. Т.е. мы не ограничиваем себя только корректным масштабированием body (гипотетически может возникнуть ситуация, когда это не нужно). Что же происходит внутри функции?
Мы получаем в JS наш контейнер по его id. Затем устанавливаем его свойство масштабирования в зависимости от pixel-ratio устройства.
devicePixelRatio - свойство глобального объекта window (окно браузера) Оно содержит отношение разрешения дисплея текущего устройства в физических пикселях к разрешению в логических (CSS) пикселях. Также это значение можно интерпретировать как отношение размера одного физического пикселя к размеру одного логического (CSS) пикселя.
Затем мы вызываем функцию, но не просто вызываем - а только когда загрузится весь HTML код, а точнее DOM (подробнее про DOM можно почитать здесь: https://ru.wikipedia.org/wiki/Document_Object_Model)
И ву-а-ля! Неважно какое установлено масштабирование - 25%, 35%, 50%, сколько угодно, наш сайт будет отображаться в своём исходном размере, и радовать нас!
Многократное использование
Очевидно, что применять этот способ придётся достаточно часто, если не сказать всегда. Я решил написать NPM-пакет чтобы не заниматься копи-пастой этого фрагмента кода из проекта в проект. Вот как выглядит использование модуля:
originalScale('container');
Функцию можно использовать как в фреймворках (например используя React нужно писать это внутри useEffect главного компонента, или внутри componentDidMount, если вы предпочитаете классы), так и в чистом HTML+JS, вызывая её после загрузки DOM, как было описано выше.
Прочитать полную инструкцию по использованию модуля а также установить его вы можете по ссылке.
Спасибо за внимание!
Я очень рад, если вам помогла статья, или пригодился модуль. Если есть предложения как это можно сделать лучше/проще - пишите в комментариях. Напишите если вам понравился формат статьи, и возможно я буду писать ещё о решении достаточно популярных проблем, с которыми столкнулся сам, и решение которых порой найти не так-то просто. Это моя первая статья, привет, Хабровчане!