I use to play with both display: flex and margin: auto to have this kind of layouts:
This works well on every browser supporting Flexbox, even IE.
However, it would have been too easy if there hadn't had a little exception: min-height.
You can find a simple working example here. When using min-height on my wrapper, the last element is not pushed to the bottom of this wrapper (IE only).
I can't get this to works, do you girls/guys have any idea? Thanks.
Testing on IE11
.wrapper {
display: flex;
flex-direction: column;
min-height: 300px;
border: 1px solid grey;
padding: 5px;
}
.element {
height: 35px;
border: 1px solid grey;
margin: 5px;
}
.element:last-child {
margin-top: auto;
}
<div class="wrapper">
<div class="element"></div>
<div class="element"></div>
<div class="element"></div>
<div class="element"></div>
</div>
This is a bug in IE's flexbox implementation:
In all other browsers that support flexbox, a flex-direction:column based flex container will honor the containers min-height to calculate flex-grow lengths. In IE10 & 11-preview it only seems to work with an explicit height value.
Bug report - (https://connect.microsoft.com/IE/feedback/details/802625/min-height-and-flexbox-flex-direction-column-dont-work-together-in-ie-10-11-preview#tabs)
It appears that this is on Microsoft's radar and will be fixed some point in the future:
Unfortunately, we are not able to address this feedback in our upcoming release. We will consider your feedback for a future release. We will keep this connect feedback bug active to track this request.
Reply from Microsoft - (https://connect.microsoft.com/IE/feedback/details/802625/min-height-and-flexbox-flex-direction-column-dont-work-together-in-ie-10-11-preview#tabs)
For now the simple solution is to use height:
.wrapper {
border: 1px solid grey;
box-sizing: border-box;
display: flex;
flex-direction: column;
height: 300px;
padding: 5px;
}
.element {
border: 1px solid grey;
height: 35px;
margin: 5px;
}
.element:last-child {
margin-top: auto;
}
<div class="wrapper">
<div class="element"></div>
<div class="element"></div>
<div class="element"></div>
<div class="element"></div>
</div>
But this has the limitation that the box wont grow if more .elements are added so probably isn't what you are after.
There does appear to be a somewhat hacky way of achieving this although it does require an extra containing element:
.container {
display: table;
min-height: 300px;
width: 100%;
}
.wrapper {
border: 1px solid grey;
box-sizing: border-box;
display: flex;
flex-direction: column;
height: 100%;
min-height: 300px;
padding: 5px;
}
.element {
border: 1px solid grey;
height: 35px;
margin: 5px;
}
.element:last-child {
margin-top: auto;
}
<div class="container">
<div class="wrapper">
<div class="element"></div>
<div class="element"></div>
<div class="element"></div>
<div class="element"></div>
</div>
</div>
This adds a container (.container), sets it to display: table; and gives it max-height: 300px;. height: 100%; is then added to .wrapper to get it to fit the full height of .container (effectively 300px) thus making IE behave the same as other browsers.
Compliant browsers ignore this and will continue to follow the min-height: 300px; rule set on .wrapper.
Here's another solution:
Adding an additional container with 2 elements:
an element with an height of "300px"
your ".wrapper"
.container {
display: flex;
}
.min-height-fix {
flex: 0 0 auto;
height: 300px; /* the "min-height" */
width: 1px; /* DEBUG */
background: red; /* DEBUG */
}
.wrapper {
flex: 1 1 auto;
display: flex;
flex-direction: column;
/*min-height: 300px;*/
border: 1px solid grey;
padding: 5px;
flex-wrap: wrap;
}
.element {
height: 35px;
border: 1px solid grey;
margin: 5px;
}
.element:last-child {
margin-top: auto;
}
<div class="container">
<div class="min-height-fix">
</div>
<div class="wrapper">
<div class="element"></div>
<div class="element"></div>
<div class="element"></div>
<div class="element"></div>
</div>
</div>
Related
I am looking for a pure CSS approach to hide div 3 that has partially overflown its container. See the attached image.
Here's a working solution that'll entirely hide an item that wouldn't fit in the fixed height of its parent: Codepen
It uses Multi-Column Layout in a tricky way with :pseudos and overflow: hidden as a final touch. OK on Fx, Chrome, Edge and IE11 (if you don't use Custom Properties as I did for a better understanding. Preprocessor variables will be fine)
.container has a fixed height otherwise the question makes no sense
Same .container is twice as large as expected. It has 2 columns with no gap/gutter
Its :pseudo :after exists (the translucid tomato blob) and thus is considered as a 4th item to be taken into account in this 2-columns layout. Its height is 100% => it makes the 3rd item occupy the 2nd column if it doesn't have enough room on 1st column (2nd example)
Parent .mask has the width we want (half of .container) and overflow: hidden: the 2nd column of .container is clipped. You can remove latter declaration to see what it clips
…
Profit!
:root {
--w: 40rem;
--p-horiz: 1rem;
box-sizing: border-box;
font-size: 62.5%;
}
* {
box-sizing: inherit;
}
.mask {
width: calc(var(--w));
overflow: hidden; /* REMOVE to see the trick */
/*padding: 0 1rem; NOPE */
padding: 1rem 0;
background-color: #aaa;
/*outline: 1px dashed red;*/
}
.container {
position: relative;
display: column;
column-count: 2;
column-gap: 0;
width: calc(var(--w) * 2);
/*max-*/height: 25rem; /* max-height also work, at least on Fx */
font-size: 1.6rem;
}
.container:after {
content: '';
display: block;
height: 100%;
background-color: #FF634780;
}
.container:before {
content: '';
position: absolute;
top: 0;
left: 0;
z-index: -1;
width: 50%;
height: 100%;
background-color: #aaa;
}
/* 1. Sufficient for Fx */
/* 2. Needed for Chrome */
[class^="item-"] {
overflow: hidden; /* 1. */
display: inline-block; /* 2. */
width: calc(100% - 2 * var(--p-horiz)); /* 2. */
margin-left: var(--p-horiz);
text-align: center;
background-color: #ddd;
/*outline: 1px dashed blue;*/
}
.item-1 {
height: 8rem;
}
.item-2 {
height: 4rem;
}
.item-3 {
height: 8rem;
background-color: lightblue;
}
.alt .item-3 {
height: 16rem;
}
.mask:first-child {
margin-bottom: 3rem;
}
[class^="item-"]:not(:first-child) {
margin-top: 1rem;
}
<div class="mask">
<div class="container">
<div class="item-1">Block 1</div>
<div class="item-2">Block 2</div>
<div class="item-3">Block 3</div>
</div>
</div>
<div class="mask">
<div class="container alt">
<div class="item-1">Block 1</div>
<div class="item-2">Block 2</div>
<div class="item-3">Block 3</div>
</div>
</div>
Our team looked for solution on hiding vertically content which overflows
But, simple overflow: hidden wouldn't work because it can hide overflowing content partially.
And we wanted to hide it fully.
So, #FelipeAls suggested to use css columns
And yes, it actually works
VIDEO DEMO: https://streamable.com/3tdc8
JSBIN: http://jsbin.com/fumiquhoxo/2/edit?html,css,output
Launchable example
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<style>
html, body {
height: 100%;
width: 100%;
}
#container {
padding: 5px;
height: 50px;
resize: both;
/*
Change this to "visible" to see how it works
*/
overflow: hidden;
}
#container-2 {
height: 100%;
width: 200%;
column-count: 2;
column-fill: auto;
}
</style>
</head>
<body>
<div id="container" style="width: 150px; outline: 1px red solid;">
<div id="container-2">
<div>ONE LINE</div>
<div>SECOND LINE</div>
<div>THIRD LINE</div>
<div>FOURTH LINE</div>
</div>
</div>
</body>
</html>
Hope this will help you. In case If you want to hide it, use property overflow: hidden
.container {
max-height: 300px;
width: 500px;
padding: 20px;
border: 1px solid #ddd;
overflow: auto;
}
.el {
padding: 10px;
margin: 10px 0;
height: 130px;
border: 1px solid #ddd;
}
<div class="container">
<div class="el">Div 1</div>
<div class="el">Div 2</div>
<div class="el">Div 3</div>
</div>
.container{
width: 500px;
height: 800px;
background-color: gray;
border:1px solid black;
text-align: center;
overflow: hidden;
}
.box{
display: inline-block;
width: 400px;
height: 300px;
background-color: lightgray;
margin: 20px 0px;
}
<div class="container">
<div class="box">div 1</div>
<div class="box">div 2</div>
<div class="box">div 3</div>
</div>
I need to preserve the aspect ratio of several divs using flex, cross browser. The divs contain charts and diagrams as SVGs, not IMGs.
I have a preferred solution working in firefox (https://jsfiddle.net/2d5hcfbo/4/), and another working in IE (https://jsfiddle.net/229oo3br/2/), but neither solution works in both. These were based on this answer. When looking at the Jsfiddles, if you increase the width of the output window (by dragging the middle column boundary to the left) you'll see the yellow divs turn pink and a Filter column is added (#media queries).
In both cases, the problem is that the divs seem to default to text height + padding. They need to stay oblong, broadly 1.5 times as wide as high. Also in IE the divs overlap each other and the font aligns low.
The FF solution uses flex-basis: 30vw; to set the height based on the width (flex-direction = column). (Height: 30vw doesn't work, not sure why.) This works in Chrome too.
The IE solution uses padding-top: 16.67%; to affect the height. This method has never been intuitive to me but I'd use it if it worked in FF.
I'm using IE 11 and FF45.9. I understand IE11 has/had a bug in this area(https://github.com/philipwalton/flexbugs/issues/71) but I can't avoid the browser. Thanks for any help!
Edit: I can make both declarations. But is there a better way?
CSS:
div#container {
/*position: relative;*/
padding-top: 50px;
display: flex;
/*flex-direction: row wrap;*/
/*align-items: stretch;*/
}
div#column1 {
flex: 0 0 auto;
background-color: white;
box-shadow: 3px 0px 10px #bebebe;
z-index: 9999;
overflow-y: scroll;
}
div#column2 {
display: flex;
flex-direction: column;
}
.row { display: flex; }
.row--top { flex: 2;}
.row--bottom { flex: 1; }
.cell {
flex: 1;
padding: 0.5em;
background-color: white;
margin: 1em;
box-shadow: rgba(0, 0, 0, 0.12) 0px 1px 6px, rgba(0, 0, 0, 0.12) 0px 1px 4px;
}
.cell-wrap {
flex-basis: 31%;
display: flex;
flex-direction: column;
}
.cell-wrap div {
margin-left:0;
}
div.row--top div#cell1,
div.row--top div.cell-wrap div {
margin-bottom: 0;
}
div.fullwidth { width: 100%; }
div.fullheight { height: 100%; }
#media screen and (max-width: 1100px) {
#container {
height: auto;
}
.row { flex-direction: column; }
.cell {
flex-grow: 1;
background-color: pink;
/* flex-basis: 30vw; */
padding-top: 16.67%;
}
/*.flex.padding div {
padding-top: 16.67%;
}*/
#cell4 {
margin-bottom: 0;
}
.cell-wrap {
width: 100%;
flex-direction: column;
}
.cell-wrap div {
margin-left:1em;
}
}
#media screen and (max-width: 700px) {
.cell {
/*flex-grow: 0;*/
background-color: yellow;
padding-top: 16.67%;
/* flex-basis: 50vw; */
}
div#column1 {
display: none;
}
}
HTML:
<div id="container" class="fullheight fullwidth">
<div class="fullheight" id="column1">
<div id="filterRow">
<div class="selectHolder" id="filters"><h1>Filter</h1><div class="spanHolder">
</div></div>
</div>
</div>
<div class="fullheight fullwidth" id="column2">
<div class="row row--top">
<div class="cell" id="cell1">cell one</div>
<div class="cell-wrap">
<div class="cell" id="cell2">cell two</div>
<div class="cell" id="cell3">cell three</div>
</div>
</div>
<div class="row row--bottom">
<div class="cell" id="cell4">cell four</div>
<div class="cell-wrap">
<div class="cell" id="cell5">cell five</div>
</div>
</div>
<!-- </div> -->
</div>
</div>
Perhaps IE requires re-declaration of the default flex property within media queries. Adding back default declaration flex: 0 1 auto did the trick.
Thanks to Michael_B for the pointer. Fix here: https://jsfiddle.net/2d5hcfbo/9/
I have a simple table structure made up of divs:
$(document).ready(function() {
$("button").on("click", function() {
$(".cell").outerWidth(500);
})
})
div {
border: 1px solid black;
box-sizing: border-box;
}
.container {
width: 400px;
height: 100%;
padding: 5px;
overflow: auto;
}
.row {
min-width: 100%;
width: auto;
display: inline-flex;
padding: 5px;
margin-bottom: 5px;
border-color: red;
}
.cell {
flex: 0 0 auto;
border-right: 1px solid black;
overflow: hidden;
min-width: 200px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="row">
<div class="cell">x</div>
</div>
<div class="row">
<div class="cell">x</div>
</div>
<div class="row">
<div class="cell">x</div>
</div>
</div>
<button type="button">Change width</button>
The rows need to be vertically stacked, each having the (unknown) height of their content and be at least as wide as the container. The container has to scroll if the content does not fit. The width of the cells will be interactively changed using JS and the rows should expand to fit the whole content. For this reason, the rows have the following style:
.row {
min-width: 100%;
width: auto;
display: inline-flex;
}
The flex part is needed for the cells and is outside of the scope of this question. Being an inline element, the row will grow with the content in all major browsers but not in Internet Explorer 11. Check out the fiddle and click the button to change the width of the cells. The border helps to visualize the behaviour. The image below shows the expected behaviour (top) and how Internet Explorer interprets it (bottom):
What kind of bug is this (couldn't figure it out from the list of flexbugs) and how can I make it work in Internet Explorer?
In IE11 the behavior is as wanted:
The default flex behavior of flex items has changed. In Internet
Explorer 10, flex items that didn't fit their containers overflowed
the margins of the container or clipped to the margins of the
container. Starting with IE11, these items now shrink to fit their
containers (up to the min-width value, if specified). Use the
flex-shrink property to change this behavior.
https://msdn.microsoft.com/en-us/library/dn265027(v=vs.85).aspx
So, the following .cell rules should solve the issue
.cell {
flex: 0 0 auto;
-ms-flex: 0 1 auto; /* overwrites the previous rule only in IE11 */
border-right: 1px solid black;
overflow: hidden;
min-width: 200px;
}
Here's a solution I've come up with... that doesn't use Flex at all.
Updated:
Simplified the CSS to handle the margins and padding better. When you click the button to make the cell grow larger, because of the fixed width of the container, there is no margin between the row and the container.
$(document).ready(function() {
$("button").on("click", function() {
$(".cell").width(500);
})
})
html, body { width: 100%; height: 100%; margin:0; padding:0; }
div {
border: 1px solid black;
/* box-sizing: border-box; */
}
.container {
width: 400px;
padding: 5px;
margin:10px;
background: green;
overflow: auto;
}
.container::after, .row::after {
content: " ";
visibility: hidden;
display: block;
height: 0;
width: 0;
clear:both;
}
.row {
min-width: calc(100% - 22px);
padding: 5px;
margin: 5px;
border-color: red;
background: pink;
float:left;
}
.container > *:last-child {
/* margin: 0; */
}
.cell {
padding: 5px;
margin:5px;
border-right: 1px solid black;
overflow: hidden;
width: calc(200px - 22px);
background: orange;
float: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="row">
<div class="cell">x</div>
</div>
<div class="row">
<div class="cell">x</div>
</div>
<div class="row">
<div class="cell">x</div>
</div>
</div>
<button type="button">Change width</button>
The problem:
div {
box-sizing: border-box;
}
.cell {
flex: 0 0 auto;
}
The solution:
If you don't want to change this part of css, i suggest you to avoid setting width, instead of setting min-width
$(document).ready(function() {
$("button").on("click", function() {
$(".cell").css("min-width","500px");
})
})
this is my first question here, but I've read many Java answers which helped me a lot. I did some research before, but don't hesitate to tell me if I duplicated a question or am doing anything wrong.
I'm trying to create a thumbnails gallery and I made a jsfiddle here.
HTML
<body>
<div id="main">
<div id="wrapper">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>
</body>
CSS
#main {
background-color: rgba(255, 105, 180, 0.5);
height: 100vh;
padding: 10px;
}
#wrapper {
background-color: blue;
display: inline-block;
padding: 5px;
}
.box {
display: inline-block;
background-color: red;
width: 200px;
height: 200px;
margin: 5px;
}
I would like to center the red boxes in the main div, but not like text-align: center;, align the boxes left-to-right between them, and center the whole block. So I thought, why not make a wrapper div and center it ?
This is where my problem is, I would like the blue wrapper to be no larger than its content, but it fills the main div.
An answer here says inline-block should solve the issue but I can't figure out how.
The whole thing surely can be made quite easily, so what am I missing ?
If TLDR, I made some snapshots here : http://imgur.com/a/a2Fjg
Thanks a lot !
You can solve it via CSS, but in this way you should write a lot of mediaqueries with hardcoded values. I recommend you do this magic with javascript:
1) Get available width
2) Calculate, how many blocks in one row can appear
3) Get required width and set it for wrapper-container
So the reason why your content is expanding to fit 100% of the space available is that as the boxes are 'inline-block' they are situated within a line (think line of text) that will take up 100% of the width if it wraps. The browser doesn't know your intention and treats this exactly like text which, normally, we would want to behave like this.
In order to change this we will need to either :
Specify the maximum width of the container.
Specify the number of elements that can be contained on one line before wrapping.
Either way we do have to hardcode some assumptions/limitations (without involving any script or complex media queries etc).
Specifying the maximum width of the wrapper is probably the most straightforward way - like this:
body{
width:100%;
}
#main {
background-color: rgba(255, 105, 180, 0.5);
height: 100%;
padding: 10px;
width:100%;
}
#wrapper {
background-color: blue;
display: block;
padding: 5px;
max-width:640px;
margin: 0 auto;
}
.box {
display: inline-block;
background-color: red;
width: 200px;
/* If you want it to shrink rather than wrap you could say
width: calc((100% / 3) - 15px);*/
height: 200px;
margin: 5px;
}
JS Fiddle: https://jsfiddle.net/Chipmo/z30fLv0v/
Specifying the number of elements before wrap is a bit more tricky. The solution I have found is to add <br> tags after each box and then selectively activate them using the nth-child selector. I'm sure there'll be a way of doing this which doesn't involve extraneous tags - perhaps with display: table shenanigans or flexbox, but this works and shows the basic concept.
JS Fiddle: https://jsfiddle.net/Chipmo/xsf6c7e5/
SO snippets below:
Max-width
body{
width:100%;
}
#main {
background-color: rgba(255, 105, 180, 0.5);
height: 100%;
padding: 10px;
width:100%;
}
#wrapper {
background-color: blue;
display: block;
padding: 5px;
max-width:640px;
margin: 0 auto;
}
.box {
display: inline-block;
background-color: red;
width: 200px;
/* If you want it to shrink rather than wrap you could say
width: calc((100% / 3) - 15px);*/
height: 200px;
margin: 5px;
}
<body>
<div id="main">
<div id="wrapper">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>
</body>
Number of elements
#main {
background-color: rgba(255, 105, 180, 0.5);
height: 100%;
padding: 10px;
text-align: center;
}
/*needs 2 ID's to gain higher precedence than the text-align center from above */
#main #wrapper {
background-color: blue;
display: inline-block;
padding: 5px;
text-align: left;
}
.box {
display: inline-block;
background-color: red;
width: 200px;
height: 200px;
margin: 5px;
}
#wrapper br {
display: none;
}
/*change to 8n for every fourth, 4n for every 2nd etc etc
You will probably want to use media queries with this */
#wrapper br:nth-child(4n) {
display: block;
}
<body>
<div id="main">
<div id="wrapper">
<div class="box"></div><br>
<div class="box"></div><br>
<div class="box"></div><br>
<div class="box"></div><br>
<div class="box"></div><br>
<div class="box"></div><br>
<div class="box"></div><br>
</div>
</div>
</body>
Use flexbox. This is the heart of the design:
#wrapper {
background-color: blue;
height: auto;
padding: 10px;
display: flex;
flex-direction: row;
justify-content: space-around;
align-content: space-between;
flex-wrap: wrap;
}
Added 2 invisible boxes at the bottom to push the last red box to the left.
FIDDLE
SNIPPET
html,
body {
width: 100%;
height: 100%;
}
#main {
width: 100vw;
max-width: 640px;
height: auto;
background-color: rgba(255, 105, 180, 0.5);
padding: 10px;
}
#wrapper {
background-color: blue;
height: auto;
padding: 10px;
display: flex;
flex-direction: row;
justify-content: space-around;
align-content: space-between;
flex-wrap: wrap;
}
.box {
display: block;
background-color: red;
margin: 2.5px auto 10px;
width: 200px;
height: 200px;
}
.space {
background: none;
}
<body>
<div id="main">
<div id="wrapper">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="space box"></div>
<div class="space box"></div>
</div>
</div>
</body>
I am hoping to create the following layout in pure CSS. I know that I can achieve this with a JavaScript solution, but a CSS solution would be much cleaner, if it is possible.
I have created a jsFiddle which I know is incorrect, to provide a starting point. The HTML and CSS I use in the jsFiddle are shown below.
Notes:
I would like this to fill the full height of the window, so that there is no scroll bar for the page (but see my last point)
There are two sections that can contain a variable number of elements.
The red elements are images which the user can add on the fly, and which will be given a frame with a fixed aspect ratio (shown here as a square)
The green section will contain a list which will have at least one item, so it will have a fixed minimum height. It may have up to four items, so its height may change. I would prefer not to have this section scroll. If the user makes the window too short for both the green and the blue elements to show full height, then the page as a whole will have to scroll.
My question is: can this be done in pure CSS? If you know that there is a solution, and if you can provide some pointers as to how I can achieve it, then I can continue to work towards that solution. If you know that there is no solution, then I will simply adopt a JavaScript approach.
If there is a solution, and you would be happy to share it, then I will be delighted that you have saved me a lot of time.
<!DOCTYPE html>
<html>
<head>
<title>Flex</title>
<style>
body, html {
height: 100%;
margin: 0;
background: #000;
}
main {
width: 30em;
height: 100%;
margin: 0 auto;
background: #333;
display: flex;
-webkit-flex-direction: column;
flex-direction: column;
}
.head{
width:100%;
-webkit-flex: 3em;
flex: 3em;
background: #fcc;
}
.expand{
width:100%;
overflow:auto;
}
.filler {
width:100%;
height:20em;
background: #003;
border-bottom: 1px solid #fff;
}
.space {
width:100%;
height:10em;
border-bottom: 1px solid #fff;
}
.foot{
width:100%;
-webkit-flex: 0 0 2em;
flex: 0 0 2em;
background: #cfc;
}
</style>
</head>
<body>
<main>
<div class="head">HEAD</div>
<div class="expand">
<div class="space"></div>
<div class="filler"></div>
<div class="space"></div>
</div>
<div class="foot">FOOT</div>
</main>
</body>
</html>
If I understand it well,
main {
height: auto;
min-height: 100%;
}
.head {
min-height: 3em;
}
.foot {
min-height: 2em;
}
.expand {
flex-basis: 0; /* Initial height */
flex-grow: 1; /* Grow as much as possible */
overflow: auto;
}
body,
html {
height: 100%;
margin: 0;
background: #000;
}
main {
width: 20em;
min-height: 100%;
margin: 0 auto;
background: #333;
display: flex;
-webkit-flex-direction: column;
flex-direction: column;
}
.head {
width: 100%;
min-height: 3em;
background: #fcc;
}
.expand {
width: 100%;
flex-basis: 0;
flex-grow: 1;
overflow: auto;
}
.filler {
width: 100%;
height: 20em;
background: #003;
border-bottom: 1px solid #fff;
}
.space {
width: 100%;
height: 2em;
border-bottom: 1px solid #fff;
}
.foot {
width: 100%;
min-height: 2em;
background: #cfc;
}
<main>
<div class="head">HEAD</div>
<div class="expand">
<div class="space"></div>
<div class="filler"></div>
<div class="space"></div>
</div>
<div class="foot">FOOT</div>
</main>