The "height: calc(100%)" function is commonly used in CSS to set the height of an element to 100% of its parent container. However, sometimes this does not work as expected and the height is not set correctly. In this comprehensive guide, we will dive deep into the various reasons why height: calc(100%) may not work properly and how to fix it.
Overview of Height: calc(100%) Function
The calc() function allows mathematical expressions to be used as property values. This is extremely useful for dynamically setting heights, widths, positions and other property values.
Here is the syntax:
height: calc(100% - 20px);
This will set the height to 100% minus 20px.
Some key points about the calc() function:
- Allows +, -, *, / mathematical operations
- Improves flexibility over static pixel or percentage values
- Values inside calc() can be any valid CSS length or percentage
In most cases, using calc(100%) should make the element take up 100% height of its parent container. However, there are some specifics around how this works that often catch developers off guard.
Reason 1: No Position Set
One of the most common reasons height: calc(100%) fails is that the element does not have a position value set.
By default, elements are statically positioned, meaning they exist in normal document flow. For percentage heights to work properly, the element must be absolutely positioned, removing it from normal flow.
Here is an example:
/* Will NOT work */
.my-element {
height: calc(100% - 20px);
}
/* Works as expected */
.my-element {
position: absolute;
height: calc(100% - 20px);
}
Absolutely positioning the element makes the percentage height relate to the nearest positioned parent container.
This trips up many developers but the fix is quite simple – just remember to add position: absolute or position: relative.
Reason 2: No Height Set on Parent
Another reason height: calc(100%) may fail is that the parent container does not have an explicit height set.
For an element to be 100% height of its parent, that parent must have a static height value defined.
Here is an example:
/* Parent has height so child can be percentage height */
.parent {
height: 300px;
}
.child {
height: calc(100% - 20px);
}
/* Parent has no height so child height will fail */
.parent {
}
.child {
height: calc(100% - 20px);
}
The solution is to simply set a pixel height, max-height, height percentage etc on the parent. This gives the child a reference point for its percentage height.
Reason 3: Margins or Padding on Parent
A less obvious reason height: calc(100%) could fail relates to margins or padding on the parent element.
Consider this CSS:
.parent {
height: 300px;
padding: 20px;
}
.child {
height: calc(100% - 20px);
}
We might expect .child to take up 100% of the parent‘s height minus 20px. However, it actually fails because the parent‘s content height is not 300px – it is 300px PLUS 40px of padding.
This trips up developers but can be solved with box-sizing:
.parent {
height: 300px;
padding: 20px;
box-sizing: border-box;
}
.child {
height: calc(100% - 20px);
}
The border-box value makes the padding be included in the height rather than added on.
Reason 4: Margins or Padding on Child
Similar to issue #3, if the child element itself has any padding or margins, this will throw off a percentage height:
.parent {
height: 300px;
}
.child {
height: calc(100% - 20px);
padding: 20px;
}
The child‘s padding pushes the height beyond what we calculate with calc().
Again, box-sizing saves the day:
.parent {
height: 300px;
}
.child {
box-sizing: border-box;
height: calc(100% - 20px);
padding: 20px;
}
With box-sizing, the padding is included in the height rather than added on.
Reason 5: Floats
When working with floats, especially floated columns, using calc(100%) heights can get tripped up.
Consider a float-based two column layout:
.left {
float: left;
width: 70%;
height: calc(100% - 20px);
}
.right {
float: left;
width: 30%;
height: calc(100% - 20px);
}
This will often fail to work. Floated elements are like absolutely positioned elements in that they are removed from normal flow.
For calc() height to work properly with floats, set an explicit reference height on the parent.
.parent {
height: 300px;
}
.left {
float: left;
width: 70%;
height: calc(100% - 20px);
}
.right {
float: left;
width: 30%;
height: calc(100% - 20px);
}
This gives a percentage height context to the floated children.
Flexbox Alternative
When working with Flexbox, you can avoid height entirely and use height: 100%
to make child elements fill the parent.
For example:
.parent {
display: flex;
flex-direction: column;
}
.child {
height: 100%;
}
Flex items derive their height from content size so no need for calc() tricks.
This is often easier than using calc(100%) in floats layouts or absolutely positioned elements.
JavaScript Solutions
As an alternative to using CSS for percentage heights, custom JavaScript could be written to achieve a dynamic height effect:
// Query elements
const parent = document.querySelector(‘.parent‘);
const child = document.querySelector(‘.child‘);
// Set heights
child.style.height = `${parent.clientHeight - 20}px`
This measures the parent height then subtracts 20px and applies that dynamically as the inline height of the child.
JavaScript has the benefit that it runs after the page is painted so percentages and paddings are correctly calculated.
The downside is it requires custom programming for each unique case. CSS keeps everything in stylesheets.
So in summary:
- Position parent and child
- Explicitly set height on parent
- Use box-sizing: border-box
- Avoid floats when possible
- JavaScript can offer alternatives
Following these guidelines will help height: calc(100%) work as you expect!