Приветствую. Представляю вашему вниманию перевод статьи «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>
.
В итоге, как и в случае с другими технологиями, всё зависит от проекта. Но думаю, вы согласитесь с тем, что это удивительно – иметь в распоряжении все эти современные методики.
jonSina
не работает, если в боди много контента, то футер уезжает за экран вниз
hisbvdis Автор
Суть данного способа в том, чтобы удерживать футер внизу экрана, если содержимого недостаточно.
При его избытке футер и должен смещаться
TerraV
С чего это вы решили стричь всех под одну гребенку? Мне удобно когда футер зафиксирован внизу и виден всегда. Элементарно когда мне присылают скрин я вижу версию и среду на которой возникла проблема. Банковский сектор если что.
hisbvdis Автор
Пользователь написал:
Когда я в ответ писал «футер и должен смещаться», имел в виду, что такое поведение и предусмотренно в подходе, описанном в этой заметке.
Я не пытался утверждать, что это концепция, которой должны все придерживаться.
Fragster
Вот решение:
jsfiddle.net/zbjsr6wv/2
Для расположения содержимого по центру, если его мало — класс centered
Для проматывания содержимого, если его много, с оставлением футера — scrollable
Если какого-то поведения не нужно — убираешь соответствующий класс и всё.