Это решит проблему:
<meta name="viewport" content="width=device-width">
TL;DR
"Портативные устройства часто рендерят страницы в виртуальном окне, называемым вьюпортом, ширина которого обычно больше ширины экрана" -
mdn. Для обхода этого поведения используется свойство
width мета-аттрибута viewport, равное значению
device-width:
content="width=device-width"
. В таком случае ширина вьюпорта будет равна ширине экрана устройства.
width - не единственное свойство, позволяющие изменять заложенное поведение вьюпорта, полный список доступен на mdn или в
спеке. Стоит отметить, что это драфт, но современные браузеры его стараются имплементировать.
Другое свойство, используемое тобой в примере, -
initial-scale, устанавливающие зум вьюпорта в определенное значение при первичном запуске сайта. Значение может варьироваться от 0.1 до 10. При 1 зум равен ширине вьюпорта (можно сказать, что в данном случае зум отсутствует). По дефолту же зум равен значению auto, который высчитывается путем деления исходного значения вьюпорта на значение реально отрендеренного холста, что позволяет отобразить весь холст на экране (
формула чуть сложнее). В твоем случае зум равен ширине экрана (т.к. ширина вьюпорта равна ширине экрана через
width=device-width
), т.е. 320px. Когда ты устанавливаешь ограничение на минимальную ширину тела документа, равную, например, 480px, то по дефолту у тебя будет горизонтальный скролл при зуме равном 1. Это логичное поведение, заложенное в спеке. Это как пытаться посмотреть сайт с ограничение в 1600px в ширину с ноутбука, там тоже будет горизонтальный скролл.
Чтобы обойти это поведение достаточно установить initial-scale в значение auto, или убрать это свойство вообще, т.к. это значение по дефолту.