Приветствую. Представляю вашему вниманию перевод статьи «Keep the Footer at the Bottom: Flexbox vs. Grid», опубликованной 8 апреля 2020 года автором Stephanie Eckles



Это первая статья из серии, посвящённой ознакомлению с современными способами решения CSS-проблем, с которыми я сталкивалась на протяжении более 13 лет в роли фронтенд-разработчика.


В течение многих лет я регулярно возвращалась к этой статье Matthew James Taylor за способом удержания футера страницы в нижней её части, даже если высота основного содержимого меньше высоты окна. Данный метод основывался на явном задании высоты футера, что являлось не масштабируемым, но очень хорошим решением (до появления Flexbox).


Если вы в основном имеете дело с разработкой SPA, можете быть озадачены тем, почему эта проблема всё ещё существует, но до сих пор встречаются ситуации, когда при недостаточной высоте содержимого, футер также отрывается от нижнего края страницы, например на:


  • страницах авторизации
  • статьях блогов или новостей
  • страницах списка товаров
  • подробностях событий календаря

Существует два способа решить эту проблему с помощью современного CSS: Flexbox и Grid.


Ниже представлена демонстрация кода с использованием метода на основе Flexbox. Если перейти на страницу Codepen, можно поменять переменную $method на grid, чтобы увидеть альтернативное решение.


Описание каждого метода приведено ниже после демонстрации кода.



Метод с использованием Flexbox


Эффект достигается путём задания:


body {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

footer {
  margin-top: auto;
}

/* Опционально */
main {
  margin: 0 auto;
  /* или: align-self: center */
  max-width: 80ch;
}

Как это работает


Во-первых, мы гарантируем, что благодаря свойству min-height: 100vh, высота элемента body будет равняться как минимум, высоте окна браузера. Это не приведёт к переполнению, если содержимого слишком мало (исключение – определённые мобильные браузеры), но если понадобится, позволит body увеличиться по высоте.


Установка свойства flex-direction: column задаёт поведение как у нормального потока документа в том плане, что блочные элементы занимают всё доступное место по всей ширине.


Преимуществом Flexbox является поведение при добавлении свойства margin: auto. Этот трюк приводит к тому, что внешние отступы элемента, к которому применено это свойство, забирают всё доступное пространство в указанном направлении (или во всех направлениях). Например, задание margin-top: auto оттолкнёт футер к нижней части экрана от расположенных выше элементов.


Проблема


В демонстрационном Codepen выше я добавила к элементу main свойство outline, чтобы продемонстрировать, что при использовании метода Flexbox, main не заполняет всю доступную высоту. Вот почему мы должны использовать именно трюк с margin-top: auto.


Вряд ли это будет иметь для вас большое значение, но если это так, посмотрите вариант с использованием Grid, который растягивает элемент main, заполняя всё доступное пространство.


Метод с использованием Grid


Эффект достигается путём задания:


body {
  min-height: 100vh;
  display: grid;
  grid-template-rows: auto 1fr auto;
}

/*Опционально*/
main {
  margin: 0 auto;
  max-width: 80ch;
}

Как это работает


В этом случае мы также используем свойство min-height: 100vh, но затем добавляем grid-template-rows для правильного расположения элементов.


Ключевым трюком этого метода является использование специальной Grid единицы измерения fr. Единица измерения fr означает "фракция / доля" и с её помощью браузер вычисляет "долю" пространства, доступную данному элементу в определённой колонке или строке. В нашем случае элемент заполнит всё доступное пространство между хедером и футером, что одновременно является решением "проблемы" из метода Flexbox.


Что лучше?


После ознакомления с методом, использующим Grid, вам могло показаться очевидным, что он лучше. Однако, если добавить больше элементов между хедером и футером, придётся менять стилизацию. Чтобы выйти из этой ситуации, следует убедиться, что данный элемент будет выполнять роль единственной обёртки и не будет влиять на потомков.


С другой стороны, метод с Flexbox может использоваться в различных шаблонах с множеством блочных элементов в средней секции – например, набор элементов <article> вместо одного <main>.


В итоге, как и в случае с другими технологиями, всё зависит от проекта. Но думаю, вы согласитесь с тем, что это удивительно – иметь в распоряжении все эти современные методики.