Вёрстка каркаса сайта под Bottom Nav

📂 Категория: CSS
🏷️ Теги:

Нижняя навигация — обязательный элемент многих мобильных веб-приложений. Она должна всегда оставаться на виду, не перекрывать контент и корректно работать на экранах разных размеров. На практике есть несколько способов её реализации, и каждый из них имеет свои особенности.

Пример Bottom Navigation:

Bottom Navigation

В этой статье мы разберём три популярных подхода:

  • Grid-вёрстка с фиксированным header и footer.
  • Fixed-позиционирование с отступом для контента.
  • Sticky-позиционирование с использованием order.

Рассмотрим их сильные и слабые стороны, а также случаи, когда тот или иной метод может подвести. Статья акцентируется на каркасе самой страницы, поэтому вёрстку самого Bottom Navigation не включаю – вряд ли с этим будут какие-то проблемы.

Вариант 1: Grid-вёрстка

<body class="body-layout">
  <header></header>

  <div class="overflow-y-auto">
    <main class="container"></main>
  </div>

  <nav class="xl:hidden"></nav>
</body>
.body-layout {
  height: 100dvh;
  display: grid;
  grid-template-rows: auto 1fr auto;
  align-content: start;

  @media (width >= 80rem) {
    height: auto;
    min-height: 100dvh;
    grid-template-rows: none;
  }
}

Экран разбивается на три ряда: шапка, контент, подвал. Прокручивается только средняя часть, а <header> и <nav> остаются на месте.

Плюсы:

  • Нет проблем с z-index.
  • Чёткая структура.

Минусы:

  • Нужно создавать внешний контейнер с overflow-y-auto, иначе могут появиться горизонтальные скроллы, если есть вложенные элементы с отрицательным margin.
  • При добавлении новых элементов в <body> нужно следить за разметкой – это хрупкое решение.
  • Если у корневого <div> есть отступы, то scrollbar будет находиться не у края экрана, а у края этого контейнера.
  • Ломает работу библиотек, завязанных на window.scrollY (например, анимации при скролле вроде GSAP ScrollTrigger или Scroll-driven animations в CSS), так как скроллится внутренний контейнер, а не окно браузера.

Вариант 2: Fixed-позиционирование

<body class="body-layout">
  <header class="sticky top-0 z-20"></header>

  <main class="container"></main>

  <nav class="bottom-nav"></nav>

  <footer class="hidden xl:block"></footer>
</body>
:root {
  --bottom-nav-height: 5rem;
}

.body-layout {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}

header {
  flex-shrink: 0;
}

main {
  padding-bottom: var(--bottom-nav-height);
  flex-grow: 1;

  @media (width >= 80rem /* 1280px */) {
    padding-bottom: 0;
  }
}

.bottom-nav {
  position: fixed;
  bottom: 0;
  z-index: 20;
  height: var(--bottom-nav-height);

  @media (width >= 80rem /* 1280px */) {
    display: none;
  }
}

Плюсы:

  • Более предсказуемое поведение, элемент всегда прибит к низу экрана.
  • Скроллится вся страница, а не отдельный <div>.

Минусы:

  • Требуется явный отступ снизу у <main> или последнего элемента, иначе нельзя будет промотать экран до самого последнего элемента.

Вариант 3: Sticky

<body class="body-layout">
  <header class="sticky top-0 z-20 shrink-0"></header>

  <main class="container"></main>

  <nav class="bottom-nav"></nav>

  <footer class="hidden xl:block"></footer>
</body>
.body-layout {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}

header {
  flex-shrink: 0;
}

main {
  flex-grow: 1;
}

.bottom-nav {
  position: sticky;
  bottom: 0;
  z-index: 20;
  order: 9999;

  @media (width >= 80rem /* 1280px */) {
    display: none;
  }
}

<body> нужно задать минимальную высоту 100vh. А центральному элементу flex-grow: 1; для того, чтобы он занял свободную высоту экрана, если страница имеет недостаточно контента для полной высоты.

Плюсы:

  • Скроллится вся страница, а не отдельный <div>.

Минусы:

  • Элемент должен быть последним на странице. Нужно следить за разметкой, иначе <footer> может оказаться ниже <nav>.
  • На всех страницах нужно центральному элементу ставить flex-grow: 1;

Заключение

Каждый из трёх подходов решает задачу фиксации нижней навигации, но с разными компромиссами.

  • Grid — хорош для строгих макетов, но сложен в поддержке и может давать побочные эффекты с прокруткой.
  • Fixed — самый надёжный способ «приклеить» элемент, но требует ручного управления отступами.
  • Sticky — элегантное решение, если вы контролируете разметку и готовы гарантировать порядок элементов.

Мне больше нравится вариант с Sticky, так как для центрального элемента всё равно обычно приходится задавать flex: 1; или flex-grow: 1; (для того, чтобы footer был прибит к низу страницы).

Похожие статьи