Неправильная работа скролла у контейнера и body(страницы сайта)

Всем привет! Я новичок в вебе и всё время сам находил решения, но сейчас не получается решить.

Все знают о проблеме вертикальной прокрутки страницы на смартфонах из-за адресной строки браузеров, которая скрывается/появляется во время скролла.

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

  1. главному контейнеру указать строгие размеры ширины и высоты в 100% от видимости вьюпорта;
  2. внутри главного контейнера добавить два блока по 100% ширины и 100dvh высоты;
  3. разрешить прокрутку(overflow-y: auto) у главного контейнера, если контент не помещается в его размеры,

То, по логике, когда эти два блока не помещаются в главный контейнер, у него появляется вертикальная прокрутка, в таком случае должен скроллиться именно главный контейнер, а не сама страница. Соответственно, адресная строка не должна реагировать на прокрутку, и вот тогда мы получаем идеальное и быстрое решение данной проблемы в браузерах. НО! Я столкнулся с непонятным поведением скролла:

Вариант реально рабочий, однако он не работает, если главному контейнеру не указать какой то отступ(не важно, border для контейнера или padding для body). То есть, если сделать всё так, как задумано выше, то оно просто не работает, всё равно почему-то скроллится сама страница браузера и адресная строка меняет своё состояние. А вот если главному контейнеру допустим добавить обводку(border: 1px solid red), то тогда данный способ начинает четко выполнять свою задачу.

Какие действия я предпринимал, чтобы обойти и эту проблему:

  • В html и body указывал по 0px ширины и высоты(и соответственно наоборот по 100vw и 100dvh);
  • Указывал у них position: relative и z-index ниже, чем у главного контейнера,

Но это всё равно не работало.

Так вот, вопросы: почему такое странное поведение у скролла? Почему именно благодаря отступам/обводкам начинает всё работать? Хотя заметьте, что для всего указано box-sizing: border-box, но почему-то они всё равно влияют на поведение браузера. Также главный контейнер занимает все 100% ширины/высоты страницы, то есть перекрывает body. Как это можно решить? P.s. решение с помощью математических вычислений(calc) и использования JavaScript не вариант, потому что решение точно должно быть на чистом CSS и более простым. Тут главное саму суть понять, почему так работает скролл и как избежать применения отступов.

UPD. Причину такого поведения я понял. Если у контейнера указать единицы измерения vw и dvh, то он начинает занимать всю область видимости экрана, и тогда происходит цепная реакция с самой страницей(с body), потому и скроллить начинает не контейнер, а саму страницу(адресная строка начинает реагировать на скролл и менять своё состояние). Но если добавить какой то отступ контейнеру(border например), то цепь разрывается и контейнер становится независимым от страницы(body), и тогда скроллится уже сам контейнер, а не страница(адресная строка перестает реагировать на скролл и изменять своё состояние). Сразу скажу, position: absolute или fixed, а также никакие z-index не помогают разорвать связь с body. А вот если для контейнера указать размеры в пикселях(подогнав под точный размер экрана смартфона), а не vw и dvh, то тогда всё работает и без border и скроллит контейнер, а не страницу. Помогите найти вариант как всё сделать без отступов, разорвав связь с body.

Код прилагается, сами можете проверить, добавляя и убирая border.

P.s. Запрещать прокрутку(overflow: hidden) у body и html не вариант, потому что тогда перестает работать перезагрузка страницы на смартфонах с помощью свайпа вниз.

Лучшего всего используйте Яндекс браузер, чтобы быстрее понимать, реагирует ли адресная строка, или нет, потому что там оно сразу начинает работать, в отличии от Хрома например, где скрывается только если достаточное расстояние прокрутить.

Скриншот как работает данный код БЕЗ обводки border на смартфоне в Яндексе прилагается(там видно, что немного прикручено вниз и адресная строка спряталась). введите сюда описание изображения Но если добавить border - то тогда не реагирует и адресная строка будет всегда видна(что нам и надо).

* {
    box-sizing: border-box;
}

body {
    margin: 0;
    padding: 0;
    background: #F0F4FF;
}

.main-container {
    // border: 1px solid red;
    display: grid;
    grid-template-rows: repeat(2, auto);
    min-width: 100vw;
    max-width: 100vw;
    width: 100vw;
    min-height: 100dvh;
    max-height: 100dvh;
    height: 100dvh;
    overflow-y: auto;
}

.block-1 {
    grid-row: 1/2;
    background: rebeccapurple;
    min-width: 100%;
    max-width: 100%;
    width: 100%;
    min-height: 100dvh;
    max-height: 100dvh;
    height: 100dvh;
}

.block-2 {
    grid-row: 2/3;
    background: green;
    min-width: 100%;
    max-width: 100%;
    width: 100%;
    min-height: 100dvh;
    max-height: 100dvh;
    height: 100dvh;
}
<body>
    <div class="main-container">
        <div class="block-1"></div>
        <div class="block-2"></div>
    </div>
</body>


Ответы (1 шт):

Автор решения: Meth0d

для телефона и проблемы выезжающей адресной строки

.my-element {
  height: 100vh;
  height: calc(var(--vh, 1vh) * 100);
}

let vh = window.innerHeight * 0.01
document.documentElement.style.setProperty('--vh', vh + 'px')

window.addEventListener('resize', () => {
  let vh = window.innerHeight * 0.01
  document.documentElement.style.setProperty('--vh', vh + 'px')
})
→ Ссылка