Как без костылей сделать так, чтобы footer сайта всегда был внизу?

Ну визуально, есть шапка, основной контент и подвал:
<header></header>
<main></main>
<footer></footer>

Как обычно, если main пустой или имеет мало содержимого, то из-за высоты этого контента за ним тоже идет footer.
Как вы решаете такую задачу?
Конечно не стоит делать через:
position: absolute;
bottom: 0

так как если main увеличится, то он не увидит footer и как бы перепрыгнет.
  • Вопрос задан
  • 25343 просмотра
Решения вопроса 3
Palehin
@Palehin
Frontend
Ответ написан
Комментировать
Комментировать
loratokareva
@loratokareva
html верстальщик
Пример страницы

В примере и footer и header прижаты

<div class="wrapper">
    <div class="main">
        <div class="header">
            <div>Код блока HEADER</div>
        </div>
        <div class="article">
            <p>Код блока article </p>
        </div>
    </div>
    <div class="footer">
        <div>Код блока FOOTER</div>
    </div>
</div>
Ответ написан
Пригласить эксперта
Ответы на вопрос 8
@dmz9
не бойся добавить обертку к разметке, от этого никто еще не умер.
есть всего 2 случая:
1. высота футера заранее известна и жестко можно её указать. в этом случае обычно использую вот такое
<html>
<head>
<style type="text/css">
* {
    /* обычно все нормальные адекватные верстальщики юзают css-reset поэтому 
    тут просто масло-масляное. такие правила в нем всегда есть, но они необходимы на самом деле.*/
    padding: 0;
    margin: 0;
    box-sizing: border-box;
}

body,
html {
	background-color: orange;
    height: 100%;
    /* растягиваем корневой элемент и боди на всю высоту окна браузера. 
    да, даже если контента 10 страниц - эти элементы будут именно по размеру окна */
}

.wrapper {
    min-height: 100%;
    /* обертка должна быть не-меньше чем всё окно целиком. это растягивает враппер 
на всю высоту окна браузера (как минимум). если контента больше чем одна страница - 
правило будет просто опускаться, и враппер будет заниматься столько, сколько нужно  */
    padding-bottom: 80px;
    /* вообще, указывать надо чуть больше, либо добавлять main отдельный нижний маржин. 
если этого не делать футер будет очень близко к main поэтому нужен отступ. 
обычно 15-16 пикселей (спейсер) */
}

footer {
	background-color: green;
    height: 80px;
    /* мы знаем высоту футера и указываем ее */
    margin-top: -80px;
    /* основная суть всего способа - отрицательный верхний маржин затягивает футер наверх на всю 
собственную высоту футера. соль в том что враппер, идущей по потоку документа перед футером уже занял 
всю высоту окна. и если мы этого не сделаем то футер всегда будет ниже нижней границы окна 
даже когда контента не будет, плюс, появится полоса прокрутки. отрицательный маржин 
нивелирует этот эффект и футер оказывается "прибит" к полу */
}
</style>
</head>
<body>
    <div class="wrapper">
        <header></header>
        <main>я майн</main>
    </div>
    <footer>пыщщ пыщщ</footer>
</body>
</html>

если используется less/sass то еще проще - заводим переменную (типа $footer_height) и юзаем ее и в паддинге (padding-bottom:$footer_height+15px) и в стилях футера (height:$footer_height; margin-top:-1*$footer_height;). замена высоты футера будет в одном месте (dry!)
2. второй вариант - высота может меняться - в основном у адаптивных сайтов.
расскажу как обойтись без флексбокс но нужно немного JS.
за высотой футера следит скрипт, и при каждом ресайзе страницы обновляет высОты и маржины/паддинги. использовать jquery проще всего, плюс, он почти всегда есть почти везде.
выглядит примерно так.
<html>
<head>
    <style type="text/css">
    * {
        padding: 0;
        margin: 0;
        box-sizing: border-box;
    }
    
    body,
    html {
        background-color: orange;
        height: 100%;
    }
    
    .wrapper {
        min-height: 100%;
        /* теперь паддинг не нужен */
        /* погорячился - все таки нужен )) */
       padding-bottom:80px;
    }
    
    footer {
        background-color: green;
        min-height: 80px;
        /* чтобы футер не схлапывался в нулевую высоту когда в нем пусто */
        height: 80px;
        margin-top: -80px;
        /* можно не убирать, чтобы оставить совместимость с чем то без JS */
    }
    </style>
</head>
<body>
    <div class="wrapper">
        <header></header>
        <main>я майн</main>
    </div>
    <footer>а я футер! ололо</footer>
    <script src="http://code.jquery.com/jquery-2.2.4.min.js" type="text/javascript"></script>
    <script type="text/javascript">
    $(document).ready(function() {
        // сначала подождем загрузки
        // объявим переменные, чтобы заново не выбирать каждый раз те же ноды
        var footerHeight, $footer = $('footer'),
            $main = $('main');
        $(window).resize(function() {
            // вешаем обработчик на изменение размеров страницы - т.е. если меняется ширина страницы, 
            // или высота, даже если в футер кто то потом аяксом что то подгрузит - 
            // сработает ресайз и все сам поменяет
            footerHeight = $footer.height('auto').height();
            // важный момент - чтобы "снять" правильную высоту элемента - надо чтобы поток документа сам 
            // назначил верную высоту футеру. а для этого сделаем её "auto". даже если забыли/не захотели убрать 
            // из стилей жестко прописаную высоту - инлайн стиль перебивает весом, и поэтому высота 
            // будет такая "как надо". потом снимаем мерку, и юзаем её
            $main.css({
                'paddingBottom': (footerHeight + 15)
            });
            // не забываем кемел-кейс для значений-через-дефис
            $footer.css({
                'height': footerHeight,
                'marginTop': (footerHeight * -1)
            })
        }).trigger('resize'); // после навешивания обработчиков насильно запускаем первый ресайз
    })
    </script>
</body>
</html>

------------------------------
варианты с позиционированием крайне не люблю - дело не в том что я не умею с ним обращаться. я то как раз таки умею, а вот многие другие делают из этого лютые костыли, которые потом заколебешься переделывать. так что лучше не используйте позиционирование там, где оно не нужно (в прибитии футера к полу например).
то что бутстрап использует позиционирование в своём прибитом футере не значит что это супер-правильно или это best-practices. просто они решили сделать так а не как то иначе.
Ответ написан
@Gudzera
Рекомендую использовать bootstrap.
html {
  position: relative;
  min-height: 100%;
}
body {
  /* Margin bottom by footer height */
  margin-bottom: 60px;
  background:#edeef0;
}
.footer {
  position: absolute;
  bottom: 0;
  width: 100%;
  /* Set the fixed height of the footer here */
  height: 60px;
  background-color: #f5f5f5;
}


<footer class="footer">
      <div class="container">
        <p class="text-muted">© Osnova Websites</p>
      </div>
</footer>
Ответ написан
lollyroll
@lollyroll
13 лет опыта накопилось
пример с флексбоксами https://jsfiddle.net/lollyroll/2nhs3mcp/2/
Ответ написан
Комментировать
lightalex
@lightalex
header и footer обычно имеют четкий height
В таком случае для main задать min-height: calc(100vh - 200px); // где 200px это высота header + высота footer
Я предпочитаю для кроссбраузерности добавлять перед этим min-height: 100%; min-height: calc(100% - 200px);
И не забудьте прописать html, body {min-height: 100%;}
Ответ написан
Комментировать
dmitry_pavlov
@dmitry_pavlov
World-class .NET freelance contractor (remotely)
Также советую изучить и использовать Flexbox-лейаут. Это действительно хорошая штука, которая упростит вам жизнь. В качестве материала для изучения совую статью "Что такое Flexbox? Описание всех css свойств, осно...", в которой описаны и наглядно продемонстрированы все концепции.
Ответ написан
Комментировать
moroz69off
@moroz69off
баннерМейкер№02
Флексы хороши, только с Вашим примером человеку будет трудно разобраться.
Есть хорошая статья про флексы на русском: frontender.info/a-guide-to-flexbox
Ответ написан
Комментировать
Evanre
@Evanre
Front-end developer
Тут много хаков на flexbox включая Sticky footer.
Ответ написан
Комментировать
Igor-Maf
@Igor-Maf
Senior Front End developer
Flexbox +.
Если flexbox - не вариант, то раньше всегда использовал такой подход, так как можно без фиксированных высот использовать.

<body class="page">
  <header class="page__row"><header>
  <article class="page__content role="main"></article>
  <footer class="page__row"></footer>
</body>


.page {
  display: table;
  width: 100%;
}
  .page__row {
    display: table-row;
    height: 1px;
  }
  .page__content {
    height: 100%;
  }
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы