не бойся добавить обертку к разметке, от этого никто еще не умер.
есть всего 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. просто они решили сделать так а не как то иначе.