Как стать автором
Обновить

Сайт отображается некорректно из за системного масштабирования, и как с этим быть

CSS *HTML *JavaScript *
Ожидает приглашения

Проблема

Неоднократно я сталкивался с тем, что верстая по макету в Figma и указывая точные размеры блоков в пикселях, результат выглядит иначе, значительно крупнее, хотя размер холста совпадает с разрешением моего экрана. Чуть позже я понял - всё дело в том, что у меня в системе установлено масштабирование интерфейса:

Из за этого размер видимой области (viewport) при полном экране браузера составляет не 1920px, а всего 1519px.

В поисках решения я видел массу различных вариантов, но все они были каким то компромиссом, а хотелось простого и универсального решения, которое можно использовать везде. В конечном итоге я нашёл его, и считаю для себя эту информацию очень ценной, поэтому делюсь с вами - может кого-то эта статья даже выручит. Я был бы рад 😊

Решение

Нам потребуется самая малость 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, как было описано выше.

Прочитать полную инструкцию по использованию модуля а также установить его вы можете по ссылке.

Спасибо за внимание!

Я очень рад, если вам помогла статья, или пригодился модуль. Если есть предложения как это можно сделать лучше/проще - пишите в комментариях. Напишите если вам понравился формат статьи, и возможно я буду писать ещё о решении достаточно популярных проблем, с которыми столкнулся сам, и решение которых порой найти не так-то просто. Это моя первая статья, привет, Хабровчане!

Теги:
Хабы:
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.