Задать вопрос

Проблема масштабирования адаптивной верстки на мобильных браузерах

Взялся за верстку своего первого адаптивного сайта. Все шло хорошо: размеры блоков в процентах, использование медиа-запросов и т.д. При экспериментировании с размером браузера все растягивается, сжимается, перестраивается как надо. Загрузил сайт на сервер, зашел со своего смартфона (android) и столкнулся с проблемой. Но тема даже не об этой проблеме, а о другой, которую породило решение первой. Об этом ниже…


Наверное, все кто занимался адаптивной версткой (да и не только адаптивной), знают, что при отображении сайта на мобильной версии браузера (скажем, на размере экрана в ширину 480 точек), сайт не отображается в масштабе 1:1, а «ужимается» под размер окна браузера. Т.е. браузер уменьшает сайт до такого размера, чтобы он целиком уместился в окно браузера. Элементы сайта становятся мелкими, шрифты не читабельными. И пользователю приходится увеличивать (масштабировать) его вручную. Но меня то не устраивает такая ситуация. Я то делал адаптивную верстку с надеждой, что она отобразится в браузере в своем реальном размере и сожмется не за счет масштабирования страницы под размер окна, а именно за счет резиновости блоков. Внешний блок () сайта имеет максимальную ширину 900 пикс, с возможностью сжиматься до 320. Блоки внутри так же сжимаются, перестраиваются и т.д. – это не важно, т.к. речь не об этом. Так вот при сжатии окна браузера на ПК, при размере окна меньше 900 пикс, сайт начинает успешно сжиматься за счет прописанных в css размерах в процентах, медиа-запросов и т.д… А при открытии его на мобильном устройстве он остается в своих реальных размерах и пропорциях, но просто масштабируется до такой степени, чтобы уместиться в окно браузера.

Еще раз повторюсь, что проблема не нова, и возможно многим верстальщикам знакома и может я зря так разжевываю, но все же на всякий случай постарался описать подробно.

И на хабре уже упоминалось решение этой проблемы, и нагуглить не составляет труда. Используем мета тег viewport

<meta name="viewport" content="width=device-width; initial-scale=1">

который говорит браузеру, что сайт должен отображаться как есть, не масштабироваться автоматически при первоначальной загрузке (потом пальцами, конечно, можно масштабировать, если не запретить это в том же мета-теге). И если, например, это не адаптивный сайт и ширина его больше ширины окна браузера, то он, конечно же, не уместится целиком, пользователю нужно будет либо уменьшать (масштабировать вручную) либо прокручивать. А если это адаптивный сайт, то он, как и было задумано верстальщиком, сожмется за счет резиновости блоков до ширины окна. Что в итоге и произошло с моим сайтом.

Но радость моя была не долгой. До тех пор пока я не открыл эту страничку на планшете. Ширина экрана моего самсунга в горизонтальной ориентации (а проблема возникла именно в просмотре в горизонтальной ориентации) 1280 пикс.

Что же в итоге получилось. Сайт, максимальная ширина которого, напомню 900 пикс, отобразился в своем нормальной размере в 100% масштабе. Но размер экрана устройства 1280 пикс! И что в итоге получлось? А получилось, что сайт не занял всю ширину экрана, а занял свои законные 900 пикс. В итоге по краям остались поля примерно по 154 пикс ((1280-900)/2). Кто-то скажет, что это ж нормально. Ведь когда мы открываем сайт на ПК, с шириной экрана, скажем, те же 1280 точек, то естественно сайт не будет занимать всю ширину, а будет занимать положенные ему 900 пикс, которые заданы в CSS как максимальная ширина сайта (или фиксированная ширина, если это фиксированный макет).

Но на планшете то эта ситуация не кажется нормальной. Т.к. экран сам по себе все-таки маленький, по сравнению с десктопами, хоть разрешение у него и 1280 точек. Хотелось бы, чтобы сайт занимал максимум пространства этого экрана. На компе нам этого не нужно, т.к. 900 пикс на мониторе будут выглядеть нормально, благо размер пиксела у него побольше чем у планшета. А вот на планшете когда страница не занимает весь экран – это кажется дикостью (по крайней мере мне). И все дело в том самом мета-теге viewport, которым мы задали отображение сайта в реальном масштабе. Это помогало нам, когда размер сайта был меньше 900 точек, т.е. помогало нам не масштабировать его под размер экрана, а отображать в реальном размере. Но это мешает нам при размере экрана больше 900 точек, ведь тут как раз хочется, чтобы масштабирование сработало, чтобы сайт увеличился до размеров окна, т.е. по максимум использовал всю ширину экрана, ведь это ж все-таки мобильное устройство.

Я для сравнения загрузил старую версию этого сайта (дизайн полностью такой же, за тем исключением, что не адаптивный, а фиксированной ширины 900 пикс) и он при первоначальной загрузке занял всю ширину экрана. Ведь в нем я не использовал viewport.

В заключение хочу сказать, что тестировал пока только на самсунге. Боюсь предположить, что же будет на iPad, разрешение которого по широкой стороне в два раза больше самсунга, 2048 пикс. Неужели страница будет занимать меньше половины экрана (она ж 900 точек)?

Короче говоря, хотелось бы поинтересоваться у сообщества, сталкивался ли кто-нибудь с подобными проблемами. И можно ли это считать проблемой? Или это нормальное поведение, которое не нужно никак исправлять? Т.е. отобразился сайт в реальном масштабе. Если не занял весь экран, то клиент без проблем увеличит его уже пальцами, смасштабирует как надо?

Пытался найти способ как сделать так, чтобы при размере экрана меньше 900 пикс, viewport срабатывал бы, а при размере больше 900 пикс не срабатывал. Не нашел.

P.S. прошу прощения что не разместил этот текст в q&a, упустил этот момент, а теперь уже не могу поменять.
  • Вопрос задан
  • 151665 просмотров
Подписаться 33 Средний 2 комментария
Пригласить эксперта
Ответы на вопрос 7
officialmuse
@officialmuse
фронтэндщик и немного бэкэндю :)
Просто вот так:
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
Ответ написан
@LemaroWeb
Не один из вариантов выше не помог.
Проблема была в том, что на мобильных устройствах отображался не на всю ширину и высоту.

Решил таким образом, но основе комментариев и почитав другие вопросы и ответы:

if (window.devicePixelRatio !== 1) { // Костыль для определения иных устройств, с коэффициентом отличным от 1		
  var dpt = window.devicePixelRatio;
  var widthM = window.screen.width * dpt;
  var widthH = window.screen.height * dpt;
  document.write('<meta name="viewport" content="width=' + widthM+ ', height=' + widthH + '">');
}
Ответ написан
Комментировать
@hardhardy
В моем случае с подобной проблемой помогло простое решение
html, body {width:100%; overflow-x:hidden}
Ответ написан
@Makito
А почему вам именно важно чтобы сайт был не более 900 пикселей по ширине?
А на счет iPad с Retina дисплеем не переживайте, если выключать масштабирование у сайта то фактически вы получите те же 1024 в ландскейпе а не 2048.
Ответ написан
Комментировать
@m-haritonov
Если я всё правильно понял, то у Вас имеется контент, минимальной шириной в 320px и максимальной — в 900px. И Вам надо:
1. Если размер экрана устройства меньше 900px, то задать ширину viewport'а страницы как у экрана устройства (чтобы произошло перестроение CSS разметки под эту ширину).
2. Если размер экрана устройства больше или равен 900px, то задать ширину viewport'а страницы в 900px (чтобы на экранах размером в 900px и больше контент увеличивался за счёт масштаба).

Для этой задачи могу предложить следующее решение (скопируйте из данного примера на свой сайт JavaScript код, разместив его выше всех других подключений и вставок CSS и JavaScript кода). Проверял только на iPad 2.

<!DOCTYPE html>
<html>
	<head>
		<script type="text/javascript">
			(function(){
				// Выполняем код только на мобильных браузерах (на всякий случай)
				if (typeof(window.orientation) !== 'undefined')
				{
					// Функция взята отсюда: https://makandracards.com/makandra/13743-detect-effective-horizontal-pixel-width-on-a-mobile-device-with-javascript
					function getDeviceWidth()
					{
						var deviceWidth = window.orientation == 0 ? window.screen.width : window.screen.height;
						// iOS returns available pixels, Android returns pixels / pixel ratio
						// http://www.quirksmode.org/blog/archives/2012/07/more_about_devi.html
						if (navigator.userAgent.indexOf('Android') >= 0 && window.devicePixelRatio)
							deviceWidth = deviceWidth / window.devicePixelRatio;

						return deviceWidth;
					}

					var deviceWidth = getDeviceWidth();
					var maxWidth = 900;
					
					if (deviceWidth < maxWidth)
					{
						// Мои эксперименты на iPad 2 показали, что device-width всегда содержит значение ширины 
						// экрана в книжной (portrait) ориентации (т.е. даже, если устройство находится в 
						// альбомной (landscape) ориентации). Это же утверждалось в некоторых найденных мною статьях.
						if (window.orientation == 0 || window.orientation == 180)
							document.write('<meta name="viewport" content="width=device-width">');
						else
							document.write('<meta name="viewport" content="width=device-height">');
					}
					else
						document.write('<meta name="viewport" content="width=' + maxWidth + '">');
				}
			})();
		</script>
		
		<style type="text/css">
			* { margin: 0; padding: 0; }
			.content { min-width: 320px; max-width: 900px; background: #ffff99; }
			.content div { border: 1px solid #f00; }
		</style>
	</head>
	<body>
		<div class="content">
			<div>
				abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc
				abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc
				abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc
			</div>
		</div>
	</body>
</html>
Ответ написан
@zetabit
если вы про неправильный начальный масштаб в iPad то вот мне помогло это:
<script>
  $(function() {
    if (navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i)) {
      var viewportmeta = document.querySelector('meta[name="viewport"]');
      if (viewportmeta) {
        viewportmeta.content = 'width=device-width, minimum-scale=1.0, maximum-scale=1.0, initial-scale=1.0';
        document.body.addEventListener('gesturestart', function () {
          viewportmeta.content = 'width=device-width, minimum-scale=0.25, maximum-scale=1.6';
        }, false);
      }
    }
  })
</script>

у меня по умолчанию в не зависимости от viewport и initial-scale=1 всеравно не хотел, ох уж эти айпады :-)
Ответ написан
Комментировать
@fursanton1986
всё просто, делайте медиа запросы с указанием ширины окна в сантиметрах, а не пикселях.
Например: media (max-width: 20cm) позволит вам отделить маленькие устройства от мониторов, и неважно какие у них будут разрешения в пикселях.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы