Как прижать футер к низу страницы с помощью CSS
Набросаем простенькую страничку, на которой будем экспериментировать:
Document HEADER - HEADER
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Praesentium molestias nulla neque omnis eaque ad perspiciatis cum mollitia excepturi sit. Amet, totam velit fugiat sunt voluptatum incidunt reprehenderit earum animi.
Sit excepturi natus velit laborum adipisci deserunt quasi veniam, pariatur non aspernatur fuga beatae dolorum cupiditate commodi maxime, id eligendi laboriosam molestiae iusto dignissimos ea et error assumenda architecto! Eos.
Perferendis animi totam, vel at reprehenderit veniam assumenda consequuntur perspiciatis similique. Eum repellat minus sed dolorem molestias, aperiam debitis hic! Quis obcaecati delectus iusto amet atque veritatis incidunt aspernatur temporibus.
Pariatur id ut obcaecati expedita, impedit ipsa error repudiandae fuga harum, saepe ratione perspiciatis recusandae! Hic numquam, beatae fuga laborum id illum voluptates voluptatibus ex deleniti mollitia nesciunt temporibus consequatur.
И зададим для нее такие же простенькие стили:
/* Декоративные стили */ * < margin: 0; padding: 0; box-sizing: border-box; >.page < width: 900px; margin: 0 auto; border: 2px dotted black; >header < padding: 10px; background: black; color: white; text-align: center; >.content-row < display: flex; >main < background: #eee; padding: 10px; >aside < background: #ddd; padding: 10px; >footer
Пока что это простое украшательство, мы добавили обертке штриховую рамку и раскрасили основные блоки — header, main , aside и footer, чтобы проще их различать. Текущий результат не очень впечатляет, правда?)
Футер висит где-то высоко над землей, а мы очень хотим его к этой земле приклеить.
Постановка задачи
Если в главном блоке мало контента, футер «прилипать» к низу странички. Если контента много, футер должен следовать за ним в нормальном потоке, скрываясь за нижней границей браузера. Другими словами, футер не должен маячить в нижней части страницы как приклеенный, если контент пытается выдавить его вниз.
Рассмотрим несколько вариантов решения проблемы.
Position: absolute
Предупреждение: данный способ годится только для футеров фиксированной высоты (для блока footer определено свойство height )!
footer
Выдернем футер из общего потока контента и спозиционируем его абсолютно, причем позиционировать будем относительно нашей обертки (page), а точнее ее левого нижнего угла. Если мы абсолютно спозиционируем футер относительно самого окна браузера, он, конечно, прилипнет к низу, а вот отлепить его обратно будет уже проблематично. Даже когда контент начнет занимать всю страницу.
.page < position: relative; >footer
Что произошло? Да в общем ничего, за исключением того, что ширина футера уменьшилась до ширины его содержимого, а сам он наполз на контент главного блока. Чтобы исправить это пропишем футеру 100% ширину, а блоку .content нижний паддинг (отступ).
footer < width: 100%; >.content
При этом 100% будут браться от ширины блока .page , так как наш футер спозиционирован относительно него.
Однако, проблема по-прежнему не решена: футер парит высоко над землей. Логика подсказывает, что необходимо каким-то образом вытянуть наш шаблон на всю высоту экрана, но при этом не добавляя контент. Справиться с этой задачей поможет свойство минимальной высоты:
.page
Ничего же не изменилось! — возмутитесь вы, и будете правы. Да, мы строго-настрого приказали блоку page растянуться минимум на 100% от высоты доступной ему области. Однако, мы забыли, что этот блок находится внутри тела нашего документа — тега body , а тот, в свою очередь, внутри html , которым никто не потрудился сообщить о том, что следует занять всю доступную высоту. Понаблюдать за этой связью мы можем, назначив body любую высоту, например:
body
Прогресс налицо — футер уполз вниз. Теперь просто задаем body и html 100%-ную высоту и радуемся прилипшему футеру.
html, body
Того же эффекта можно было добиться, просто установив блоку .page минимальную высоту в 100vh .
.page
Табличная верстка
Не пугайтесь, никто не заставляет вас верстать таблицами, эта технология постепенно отходит в прошлое. Однако, сложно отрицать тот факт, что таблицы в некоторых аспектах — вещь крайне удобная. Например, в позиционировании футера. Мы можем заставить наши блоки вести себя как строки таблицы с помощью CSS-свойства display:table-row . Это весьма удобный метод, который, к тому же, не требует категорично определять высоту футера.
Блок .page станет таблицей, а блоки header , .content и footer ее рядами.
.page < display:table; >header, .content, footer
На первый взгляд ничего не изменилось. Однако теперь давайте зададим таблице и ее родительским блокам 100%-ную высоту.
html, body, .page
Что такое произошло? Наша таблица растянулась на всю высоту экрана, но все высота блоков изменилась. Это волшебное свойство таблиц — автоматически балансировать высоту своих рядов в зависимости от содержимого. С этим очень легко разобраться. Зададим футеру и хедеру высоту в 1 пиксель. Не бойтесь, они не превратятся в узкие полоски, их реальная высота будет высчитываться в зависимости от контента. Этот способ лишь позволить блоку .content растянуться во всю высоту страницы.
header, footer
В принципе, никто не мешает и здесь задать конкретную высоту для футера или хедера.
See the Pen by furrycat (@furrycat) on CodePen.
Флексбоксы
На самом деле, таблицы — не самый лучший инструмент для верстки сайтов. Просто потому, что предназначены они для другого. Но принимая во внимание отсутствие специального инструмента, приходилось как-то крутиться. Теперь же этот инструмент есть и поддерживается он уже почти всеми браузерами.
Это флексбоксы.
С их помощью решение проблемы «липкого футера» осуществляется очень просто и очень изящно:
html, body < height:100%; >.page < display: flex; min-height: 100%; flex-direction: column; >.content
Вот и вся хитрость «липкого» футера.
Верстайте с удовольствием!
Прибитый к низу футер своими руками
Все, кто привык к полноценно оформленным страницам сайтов, предпочитает вид «прибитого» (прилипающего, sticky) к низу футера страницы. Но есть в интернете две беды: нерастущие вниз поля ввода и неприбитые (к низу окна) футеры. Например, когда открываем короткие по высоте страницы типа habrahabr.ru/settings/social — сразу бросается в глаза, что информация, призванная быть в нижней части окна просмотра, прилипает к содержанию и находится где-то посередине, а то и в верхней части окна, когда внизу — пусто.
Так, вместо того, чтобы .
Данное пособие для начинающих верстальщиков покажет, как за 45 минут сделать «прибитый» футер, исправив недоработки даже такого уважаемого издания, как Хабр, потягаться с ним в качестве исполнения своего перспективного проекта.
Посмотрим на реализацию одного вида прибитого футера, взятого из сети, и попробуем разобраться в происходящем. css-tricks.com/snippets/css/sticky-footer
CSS:
* < margin:0; padding:0; >html, body, #wrap < height: 100%; >body > #wrap #main < padding-bottom: 150px; >/* must be same height as the footer */ #footer < position: relative; margin-top: -150px; /* negative value of footer height */ height: 150px; clear:both;>/* CLEAR FIX*/ .clearfix:after .clearfix /* Hides from IE-mac \*/ * html .clearfix < height: 1%;>.clearfix /* End hide from IE-mac */
Вряд ли каждый, даже знающий CSS, глядя на этот код, разберётся в принципах и будет уверенно править сложный проект. Любой шаг в сторону приведёт к побочным эффектам. Рассуждения и изготовление футера ниже призваны дать больше понимания правилам CSS.
Начнём с теории
Обычная реализация прибитого футера основывается на том уникальном для CSS2 свойстве, что элементы — непосредственные потомки BODY — поддерживают процентную высоту (height:100% или другую) относительно окна, если все их родители имеют тоже процентную высоту, начиная с тега HTML. Раньше, без доктайпов, а сейчас в Quirks Mode процентные высоты элементов поддерживаются на любом уровне, а в современных доктайпах — только внутри процентно заданных элементов. Поэтому, если мы сделаем блок контента (назовём его #layout), имеющий 100% высоты, он будет иметь скролл, как будто это — окно. В него помещают всё (потоковое) содержание, кроме футера и, может быть, хедера.
Футер помещают вслед за этим блоком и делают ему 0 пикселей высоты. Вообще, можно вслед за #layout поставить сколько угодно блоков, но все они должны быть или с 0 пикселей высоты, или вне потока документа (не position: static). И есть ещё один важный фокус, которым обычно пользуются. Не обязательно делать высоту, равную 0. Можно сделать высоту фиксированной, но из основного блока вычесть её за счёт свойства margin-bottom: -(высота);.
Говоря человеческим языком, стилями делается пустой «карман» снизу, в который вкладывается футер, и он всегда оказывается или прилепленным к нижней границе окна, или к нижней границе документа, если документ по высоте больше высоты окна. По интернету и на Хабре существует множество реализаций футера, с разной успешностью работы во всех браузерах. Продолжим строить его самостоятельно, используя вёрстку Хабра как «рабочую лошадку».
Поскольку низ блока #layout — это карман, он для футера должен быть пустым, не отображающим объекты страницы. И тут встречаемся с ещё одним ограничением — мы не можем делать пустой карман за счёт padding в #layout, потому что тогда он станет больше 100%. Не спасёт и margin — пустоту нужно делать за счёт свойств вложенных элементов. Плюс ко всему, надо обеспечить невылезание под границу блока плавающих элементов, что делается, например, блоком
где .clear . Важно, чтобы или эта «высота» была фиксированной, или в тех же относительных единицах, или мы её вычисляли бы в процессе изменений страницы. Обычно удобно совместить этот выравнивающий блок с установкой для него требуемой высоты.
Посмотрим на строение страниц нашего подопытного. Для этого проще всего раскрыть окно Firebug или подобное окно («Инструменты разработчика» (Ctrl-F12)) в Chrome.
. Верхний блок рекламы.. ===Содержимое страницы===.. Правый сайдбар.. Блок..
.
.
.
.
.Перейдём к рабочему примеру
Какие видим недостатки вёрстки в плане реализации эффекта прибитого футера? Видим, что
1) футер на сайте находится внутри блока с который не имеет процентной высоты. По теории, ему, родителям и блоку содержания .content-left требуется поставить высоту 100%. С последним возникают проблемы — он для такого не приспособлен. Следовательно, не хватает одного прослоечного блока или футер находится не на том уровне. Кроме того,
2) высота футера переменная (зависит от числа элементов в списке и от размера шрифта, это видно не из HTML, а из CSS). И
3) над #layout имеется рекламный блок фиксированной высоты 90px;
4) выравнивающих блоков нет ни в футере, ни (вообще говоря) в блоке #layout (есть, но над блоком .rotated_posts; впрочем, возможно, его надо отнести к футеру).Пункт 4 — придётся прорисовывать скриптом.
C третьим пунктом разобраться, казалось бы, просто, добавив#layoutНо вспомним, что этого блока может не быть — он подавляется баннерорезкой, или рекламщики его вдруг решат не показывать. Есть ряд страниц сайта, где его нет. Поэтому зависимость margin-top от рекламного блока — плохая идея. Гораздо лучше — разместить его внутри #layout — тогда он ничем не будет мешать.
Первый пункт — чтобы прибитый футер вообще заработал, надо блок футера поместить под #layout. Впрочем, с помощью javascript можно реализовать и другие схемы прибитого футера, но в любом случае нужен JS или изначально правильная вёрстка, чтобы обойтись без него.
Поскольку мы не можем быть сильнее самого последнего верстальщика сайта, «влепившего» футер внутрь содержания, отложим идею правильного размещения футера на свой будущий сайт (который, стало быть, будет «круче» Хабра!), а Хабр препарируем джаваскриптом (юзерскриптом) до правильного состояния. (Сразу скажем, виноват не верстальщик, не стрелочник, а вид сайта, конечно, определяет стратегическое решение руководства проекта.) Так мы не достигнем идеала, потому что в первую секунду-две в процессе загрузки страница будет с неправильной вёрсткой. Но для нас важен концепт и возможность превзойти по качеству самый популярный сайт
мираайтишников.Поэтому в нужном месте скрипта (пораньше, в конце загрузки страницы) напишем переносы DOM-блоков рекламы и футера на нужные места. (Приготовимся к тому, что за счёт юзерскриптов решение будет сложнее чистого.)
var dQ = function(q) //для сокращения var topL = dQ('#topline'), lay = dQ('#layout'), foot = dQ('#footer'); if(topL && lay) //баннер - внутрь блока контента lay.insertBefore(topL, lay.firstChild); if(lay && foot && lay.nextSibling) //перенос футера lay.parentNode.insertBefore(footer, lay.nextSibling);
Расставили блоки по местам — теперь осталось приписать элементам нужные свойства. Высоту футера придётся задавать точно, просто потому что мы её уже знаем к моменту действия юзерскрипта (конец загрузки страницы). Из-за точки срабатывания юзерскрипта, как уже говорилось выше, прыжок отображения футера на странице неизбежен. Можно пытаться делать «хорошее лицо», но при «плохой игре»? Зачем? «Плохая игра» сайта позволяет сделать без сверхусилий концепт, которого будет достаточно для оценки качества и не понадобится при «правильной игре» на своём проекте.
if(foot)< //блок-выравниватель в футере h.apnd_el(); var footH = foot.offsetHeight; //. и измеряем высоту футера > if(topL && lay && footer && lay.nextSibling)< //выравнивающий блок нужной высоты в контенте ("лейауте") h.apnd_el(, appendTo: lay>); lay.style.minHeight ='100%'; h.addRules('#layouthtml, body '); >
Здесь позволили себе применить самописную функцию h.apnd_el, делающую примерно то же, что и в jQuery —
$(' ').css().appendTo($(footer))
И далее — ещё одна типичная функция внедрения правил CSS — h.addRules. Здесь без неё не обойтись, потому что нужно объявить правило с «!important» — как раз из-за особенностей приоритетов стилей из юзерскрипта.
С этими кусочками кода мы сможем увидеть в юзерскрипте прибитый футер (после прыжка его вниз) и полностью осознать, как надо строить вёрстку страниц. Использовать прыгающий дизайн повседневно — неприятно, поэтому рекомендуется его сделать исключительно для демонстрации и тестирования. В юзерскрипте HabrAjax я установил аналогичный скрипт, закрыв его настройкой «underFooter» (установить «галочку» в списке настроек перед «прибитый к низу футер»), начиная с версии 0.883_2012-09-12.
Затрагивает ли прибитый футер необходимость обновления стилей ZenComment, если они установлены? Да, затрагивает. Из-за сложной цепочки приоритетов стилей, в которых стили, вставляемые юзерскриптом, имеют низший приоритет, пришлось немного подкорректировать юзерстили для возможности работы с прибитым футером. Если вы не обновите юзерстили (до 2.66_2012-09-12 +) — футер будет работать неточно.
Блок rotated_post (три популярных поста из прошлого) логичнее смотрится при футере, поэтому в реальном скрипте он тоже перенесён в футер.
Второй пункт (из списка недостатков вёрстки) — рассуждения чисто для Хабра (к юзерскрипту не относятся и частично повторяют прежние).
У страниц имеется проблема, мешающая сделать прибитый футер на чистом CSS — неопределённая высота футера, зависящая от размеров шрифта по умолчанию в браузере. Для реализации футера на CSS требуется подобрать относительные высоты шрифтов, но и они могут не сработать, если на компьютере пользователя не будет предусмотренных шрифтов. Поэтому решение должно включать джаваскрипт, который может подгонять переходами (transitions) приблизительное положение футера до точного. Или, посмотрев на приемлемость сделанного решения на юзерскрипте на разных платформах, сделать вычисляемую установку прибитого футера — первые наблюдения показывают, что решение практично.
Вывод: полноценно оформить раскладку на Хабре можно, но для этого нужен верстальщик, чётко понимающий поведение раскладки, располагающий блоки в правильном порядке. (Сейчас футер и верхний баннер стоят «не там» и не так, чтобы просто стилями получить прибитый футер.) Можно обойтись без JS, если задать высоту футера в относительных единицах, взяв некоторый запас места на неопределённость шрифта.
Реализация
Если включить HabrAjax 0.883+, то увидим работу «прибитого футера». Он адаптируется по высоте с помощью скриптов. Он позволяет оценить, насколько лучше выглядят страницы с прибитым футером по сравнению с обычными. Юзерстили ZenComment совместимы со скриптами, но для правильной работы прибитого футера с ними нужно установить версию ZenComment 2.66_2012-09-12 +.
Факты о поведении реализации
Шаманство с футером, стилями и скриптами — это шаманство (лишь подкрепляемое теорией). В разных браузерах немного разное поведение, но кое-где — неожиданное. Без юзерскриптов и переставления блоков результаты будут другие. Вот что дали эксперименты с реализацией на юзерскрипте.
1) Firefox — неожиданное отсутствие прыжков футера. Странно, что их нет — отрисовка происходит после размещения футера внизу.
2) Chrome — он удивил «блуждающим скроллом» — к странице с периодом раз в секунду добавляются пустые пространства внизу — что-то неправильное происходит с расчётом высот. Лечится прописыванием html,body в юзерстили, но без гарантий, что всегда будет работать. Надёжнее — проверять, не превышает ли документ окно по высоте, и если не превышает, то двигать футер, иначе — ничего. С прыганием — всё в порядке, оно есть.
3) Опера — без прыжков (v. 12.02) при первой загрузке страницы, но поспешная перезагрузка может показать прыжок футера. В остальном ведёт не менее корректно, чем Fx.
Что же, придётся специально приучить Хром вести себя правильно (скриптом) и в таком виде выкатить версию на обозрение. Поэтому участок в юзерскрипте немного сложнее, чем приведённый в статье.
Надо напомнить, что это не полноценная реализация — не учитывает, например, случаи ресайза окна пользователем. Можно найти и редкие (на практике) сочетания изменяющихся высот футера до перемещения и после него, где логика начнёт давать сбои, не приводящие к неудобствам. Недостатки оставлены сознательно, потому что соблюдается баланс сложности доработки и временности решения.
В итоге, получилась вполне работоспособная схема работы, по крайней мере, для быстрых стационарных компьютеров. Если обнаружится неправильное поведение футера, настройку «underFooter» нужно отключить.
Для каких страниц это полезно?
На стандартном сайте, без юзерстилей даже короткие страницы вопросов-ответов оказываются длиннее 1500px, что в большинстве случаев незаметно при горизонтально расположенных мониторах. Но даже при обычных мониторах часто попадаются персональные страницы пользователей высотой порядка 1300 пикселей, где неприбитый футер предстаёт во всей красе. Не очень длинен и ряд страниц в настройках пользователя.
Если применять юзерстили ZenComment, они сильно сокращают необходимую высоту страницы, а юзерскрипт HabrAjax может не показывать некоторые или все боковые блоки в сайдбаре. Поэтому со скриптами и стилями заметно чаще наблюдается эффект неприбитого футера. Поэтому логично, что в HabrAjax исправление футера появилось впервые. Но и обычный сайт имеет ряд страниц, где прибитый футер был бы полезен.
Будет ли поддержка?
Поведение сайта за последний год показывает, что разработчики (а значит, руководство) начали внедрять возможности, ранее существовавшие только в юзерскриптах и юзерстилях. Например, в начале года я написал статью-обзор по юзабилити Хабра, где собрал множество небольших пожеланий. Через полгода я вернулся к ней и с удовлетворением пометил (прямо в тексте; можно ознакомиться с «UPD» и датами), что целый ряд возможностей, описанных как пожелания, уже были внедрены в сайт.
Далее, посмотрим на «стрелочки» вместо квадратиков для оценивания комментариев. Они появились в юзерсилях almalexa («Prettifier») года 3 назад и переняты в ZenComment года 2 назад. Месяца 2-3 назад они появились на сайте. Начинает вериться в то, что через некоторое время стрелки разнесут на некоторое расстояние, как это сделано в ZenComment (одна стрелка слева от числа, вторая справа), чтобы меньше промахиваться.
Поэтому, возможно, и «прибитый футер» на Хабре — это не такая фантастика, какой могла показаться года 3 назад.
Другие возможности в скрипте HabrAjax, появившиеся за последние 3 месяца (отключаемы в настройках):
* авторост полей ввода (в Опере может тормозить на больших текстах);
* дни недели при датах, кроме «сегодня» и «вчера»;
* события в Ленте, сворачиваемые до 1 строки и 2 символов;
* сокращение слов «хабр*» до «χ·» и «χα»;
* подсказки дат по номерам статей — сообщается, какого месяца и года статья до её загрузки, по номеру в URL;
* свёрнуты «Похожие посты» до 2 слов. Скриншот всплывающих «похожих постов» (показывает 12 ссылок, а не 4).Как отключить шапку (header) или подвал (footer) на отдельной странице?
Чтобы отключить Header или Footer на какой-либо странице, откройте Настройки страницы → Дополнительно и поставьте галочку у пункта Не использовать Header / Footer на этой странице. Переопубликуйте страницу.
- Как добавить фавикон (favicon, иконку в браузере)?
- Как сделать «шапку» (header, хедер) сайта?
- Как добавить HTML-код в Head сайта?
- Как создать сайт на нескольких языках?
- Как добавить еще одну страницу на сайт?
Этот ответ был вам полезен?
Шапка и подвал сайта (Header и Footer)
Посмотрите видеоурок о том, как добавить шапку и подвал на сайт или прочитайте подробную инструкцию ниже.
Чтобы разместить блок сразу на всех страницах сайта (например, меню), нужно создать отдельную страницу, поместить на нее элементы, которые должны быть на всех страницах, перейти в Настройки сайта → Шапка и подвал и назначить созданную страницу как шапку или подвал.
Header (хедер, хидер, шапка) – это блок в верхней части страницы сайта , который виден на всех страницах сайта. Как правило, содержит логотип, меню, контакты, переключатель языков или корзину, если в интернет-магазине несколько страниц и нужна общая корзина.
Чтобы сделать хедер, создайте новую страницу и добавьте нужные элементы: меню или логотип. Перейдите Настройки сайта > Шапка и подвал и назначьте эту страницу как шапку (header).
Footer (футер, подвал) — блок в нижней части страницы. Содержит полезную, но не первостепенную информацию. Виден на всех страницах сайта. В футер можно вынести: копирайт, название студии, которая разрабатывала сайт, контакты. Иногда в футере дублируются пункты меню. Футер создается аналогично хедеру: создайте новую страницу, на ней оформите футер, перейдите Настройки сайта > Шапка и подвал и назначьте эту страницу как подвал (footer).
Чтобы хедер и футер стали видны, опубликуйте все страницы (а не только страницы, назначенные как хедер и футер).