Css fills the remaining height only when children require

I have content and a footer panel. The footer has a fixed size, but the content can either be fixed or fill in the remaining height, depending on the (large) children. If any child fills the remaining height, the content pane should also fill the remaining height. The depth of such filling the child can be any (immediate daughter or 10 nested levels).

Example:

var button = document.getElementById('child-switcher'); var child = document.getElementById('content-filler'); button.onclick = function() { if (child.style.display === 'none') { child.style.display = null; } else { child.style.display = 'none'; } } 
 #main { height: 300px; display: flex; flex-direction: column; } #footer { background-color: green; } #content { flex: 1; display: flex; flex-direction: column; } #some-nested-content { display: flex; flex: 1; flex-direction: column; } #content-filler { flex: 1; background-color: red; } #content-header, #content-footer { background-color: yellow; } 
 <div id="main"> <button id="child-switcher"> Hide/show the child </button> <div id="content"> <div id="some-nested-content"> <div id="content-header"> CONTENT_HEADER </div> <div id="content-filler"> FILLING REMAINING HEIGHT </div> <div id="content-footer"> CONTENT_FOOTER </div> </div> </div> <div id="footer">FOOTER</div> </div> 

In this example, if you press the button, FOOTER will remain at the bottom, but should go up.

PS using flexbox is not a requirement, it can be any layout that will achieve the desired result.

+5
source share
3 answers

In this example, if you press the button, FOOTER will remain at the bottom, but it should grow.

When you delete (set display: none; ) the content-filler flexibility element, content still fills the remaining space with flex: 1 and holds the footer at the bottom.

If any child fills in the remaining height, then the content panel should also fill in the remaining height.

One way to solve this is to simply switch the class to content to switch its flex-grow value.

The depth of such filling children can be any (immediate children or 10 nested levels)

Here I also used the same class to control the content-filler element, since it is better to do this with the class than change the style of the element directly, and you can easily direct any number or levels of elements.

Fragment of a stack

 var button = document.getElementById('child-switcher'); var parent = document.getElementById('content'); button.onclick = function() { parent.classList.toggle('collapse'); } 
 #main { height: 300px; display: flex; flex-direction: column; } #footer { background-color: green; } #content { flex: 1; display: flex; flex-direction: column; } #content.collapse { flex: 0 1 auto; /* added */ } #content.collapse #content-filler { display: none; /* added */ } #some-nested-content { display: flex; flex: 1; flex-direction: column; } #content-filler { flex: 1; background-color: red; } #content-header, #content-footer { background-color: yellow; } 
 <div id="main"> <button id="child-switcher"> Hide/show the child </button> <div id="content"> <div id="some-nested-content"> <div id="content-header"> CONTENT_HEADER </div> <div id="content-filler"> FILLING REMAINING HEIGHT </div> <div id="content-footer"> CONTENT_FOOTER </div> </div> </div> <div id="footer">FOOTER</div> </div> 

Option 2 is to change the markup and move the footer inside the some-nested-content element

Fragment of a stack

 var button = document.getElementById('child-switcher'); var child = document.getElementById('content-filler'); button.onclick = function() { if (child.style.display === 'none') { child.style.display = null; } else { child.style.display = 'none'; } } 
 #main { height: 300px; display: flex; flex-direction: column; } #footer { background-color: green; } #content { flex: 1; display: flex; flex-direction: column; } #some-nested-content { display: flex; flex: 1; flex-direction: column; } #content-filler { flex: 1; background-color: red; } #content-header, #content-footer { background-color: yellow; } 
 <div id="main"> <button id="child-switcher"> Hide/show the child </button> <div id="content"> <div id="some-nested-content"> <div id="content-header"> CONTENT_HEADER </div> <div id="content-filler"> FILLING REMAINING HEIGHT </div> <div id="content-footer"> CONTENT_FOOTER </div> <div id="footer">FOOTER</div> </div> </div> </div> 
+1
source

Why is the footer sticking out below?

The problem is the fixed height that you set for the main container with a flexible display. If you just delete this height or set it to auto. Since #main is not a flexible element , it retains its entire height, but since its contents are flexible, they collapse to the beginning.

But then the content filler does not occupy the full space?

He does not occupy any space, because now there is no height. You can simply set a minimum height in the content filler or just let it grow dynamically. Once you hide all the footers matching the top, since the main container no longer has a fixed height.

 var button = document.getElementById('child-switcher'); var child = document.getElementById('content-filler'); button.onclick = function() { if (child.style.display === 'none') { child.style.display = null; } else { child.style.display = 'none'; } } 
 #main { height: auto; display: flex; flex-direction: column; } #footer { background-color: green; } #content { flex: 1; display: flex; flex-direction: column; } #some-nested-content { display: flex; flex: 1; flex-direction: column; } #content-filler { flex: 1; min-height:200px; background-color: red; } #content-header, #content-footer { background-color: yellow; } 
 <div id="main"> <button id="child-switcher"> Hide/show the child </button> <div id="content"> <div id="some-nested-content"> <div id="content-header"> CONTENT_HEADER </div> <div id="content-filler"> FILLING REMAINING HEIGHT </div> <div id="content-footer"> CONTENT_FOOTER </div> </div> </div> <div id="footer">FOOTER</div> </div> 
+1
source

I think the problem you are talking about can be solved with CSS Grid .

CSS Grid Layout is highlighted when dividing a page into main regions or defining a relationship in terms of size, position and level between parts of a control created from HTML primitives.

If you want to look good, what can you do using CSS Grid. I would recommend visiting this link.

Hope this helps.

0
source

Source: https://habr.com/ru/post/1274314/


All Articles