Getting a 100% div inside a flexbox element

I am trying to create the following layout using flexbox.

enter image description here

The upper black bar, the middle section and the lower black bar are all flexible elements that are children of the div wrapper only inside the body tag, which looks like this.

<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href='https://fonts.googleapis.com/css?family=Open+Sans:400,300,300italic,400italic,600,600italic,700,700italic' rel='stylesheet' type='text/css'> <link href="~/Styles/bootstrap.min.css" rel="stylesheet" /> <link href="~/Styles/font-awesome.min.css" rel="stylesheet" /> <link href="~/Styles/ppt_site.css" rel="stylesheet" /> </head> <body> <div class="wrapper"> <div id="topRow"> </div> <div id="centralRow"> <div id="sidebarColumn"> </div> <div id="contentColumn"> </div> </div> <div id="bottomRow"> </div> </div> @Section['customScripts'] <script src="~/Scripts/siteGlobals.js"></script> <script src="~/requireconfig"></script> <script data-main="~/scripts/NewTemplatesAppLoader.js" src="~/requirejs"></script> </body> </html> 

The style sheet that governs all this is as follows

 .wrapper, html, body { height: 100%; margin: 0; } .wrapper { display: flex; -ms-flex-direction: column; -webkit-flex-direction: column; flex-direction: column; } #topRow { background-color: black; color: white; } #centralRow { -ms-flex: 1; -webkit-flex: 1; flex: 1; display: flex; -ms-flex-direction: row; -webkit-flex-direction: row; flex-direction: row; } #bottomRow { background-color: #333333; color: white; } #sidebarColumn { background-color: #B83B1D; color: white; } #contentColumn { -ms-flex: 1; -webkit-flex: 1; flex: 1; background-color: #F7F7F7; color: black; padding: 10px; overflow-y: auto; } 

As for the main layout, all this works great, you will notice that if you look at the image, the red sidebar is like the area at the top with a yellow border.

In this area, there is destined to be a div that stretches the entire height of the red area (sidebar column) in the CSS above, but I try as best I can, I can not get it to do what I need.

Ideally, I want it to be a div, which was a flex container, which I can then put 4 flex items on and each of them takes up a quarter of the space available to everyone, but since the div with the yellow border cannot seem like the height of the parent container (red the sidebar, which is the most flexible), then it only ever takes up the height of the space around it.

I tried wrapping it in more divs and putting those divs, I wrapped extra flexible boxes in further divs, I tried blocks, inline rows, cell tables and almost everything I can think of.

No matter what I try, I just can't make the container with the yellow border have the same height as the parent.

Any ideas anybody?

Update (the next morning)

The 2 proposed solutions really work on their own, and they work the way I expected them.

In my particular case, however, they do not work.

I use NancyFX with this super simple viewer and I use KnockoutJS to compose the “web components”, so I can keep my parts reusable.

If I edit my “Master Template” and paste the div directly into the markup below #sidebarColumn, I get 4 divs of equal size as desired.

However, what really needs to happen is this: my template looks like this:

 <div class="wrapper"> <div id="topRow"> @Section['topbarContent'] </div> <div id="centralRow"> <div id="sidebarColumn"> @Section['sidebarContent'] </div> <div id="contentColumn"> @Section['bodyContent'] </div> </div> <div id="bottomRow"> @Section['bottombarContent'] </div> </div> 

If I remove the "@Section ['sidebarContent']" and put the divs directly in them.

If I put the div directly on my page that uses the template as follows:

 @Master['shared/ppt_layout.html'] @Section['topbarContent'] <toptoolbar></toptoolbar> @EndSection @Section['sidebarContent'] <div>aaa</div> <div>aaa</div> <div>aaa</div> <div>aaa</div> @EndSection @Section['bodyContent'] <h1>Body Content</h1> <p class="lead">I am the test page that uses a wide sidebar component</p> <p>If you notice however, I also have a top toolbar with title added to me, and a footer bar.</p> <p>We all use the same template however....</p> @EndSection @Section['bottombarContent'] <footerbar></footerbar> @EndSection @Section['customScripts'] @EndSection 

This also works, but if I put the markup in the knockout component, even direct divs work on the page, then I get the effect that I initially noticed.

So for some reason, adding content using knockout components is what causes the problem.

Even if I try to build a new flexible layout inside the component, nothing works vertically, horizontally, but everything works fine.

The footer, for example, is divided into left and right sections without any problems, but the vertical alignment is simply canceled.

+5
source share
3 answers

So, after what seems like days of torture, I finally figured out what the problem is.

I use knockout.js in my project, especially the knockout components, and this is the barrier between them that causes the problem.

For those who have not used KO components before, this is a fairly simple process. You create a JS presentation model and a small piece of HTML to display the surface of components.

then you use:

 ko.components.register("myComponent", { viewModel: "Components/myComponent.js", template: "Components/myComponent.html" }); ko.applyBindings(); 

Register your component.

Once a component is registered, you can simply use it by setting

 <myComponent></myComponent> 

If you want to add it to your web page.

Now all this is fine and dandy, BUT ... when KO instantiates the component, it leaves its own tag in place.

So, if you imagine that your component looks like this

 <div> <div>Item...</div> <div>Item...</div> <div>Item...</div> <div>Item...</div> </div> 

and your page looks like

 <body> <div> <myComponent></myComponent> </div> </body> 

Then the final output will look like

 <body> <div> <myComponent> <div> <div>Item...</div> <div>Item...</div> <div>Item...</div> <div>Item...</div> </div> </myComponent> </div> </body> 

Given the rules in the CSS above, both my and both respondents were targeting the div wrapper, the rule never matched the target div to enable flex.

The key (as I found during the trial version and the error) is to use the name of the user tag, EG:

 #sidebarColumn > narrowsidebar { width: 70px; flex: 1; display: flex; flex-direction: column; } 

and then, omit further bending operations from this parent.

It still doesn't explain why, when you execute the full flexbox layout from scratch inside the component (this is without any bending operations on the main web page and / or template), it still has problems with vertical alignment, as far as I can see KO does nothing for dom, which should cause this behavior.

However, for my initial problem, custom tag targeting gave me what I needed.

Shawty

+2
source

You can use nested flexbox:

 <div id="sidebarColumn"> <div>...</div> <div>...</div> <div>...</div> <div>...</div> </div> 

 #sidebarColumn { display: flex; flex-direction: column; } #sidebarColumn > div { flex: 1; } 

jsFiddle

+1
source

Use flex: 1 for a flexible child so that it spans the largest possible space

 .wrapper, html, body { height: 100%; margin: 0; padding:0; } /* header */ #topRow { background-color: black; color: white; height:20%; } /* footer */ #bottomRow { background-color: #333333; color: white; height:10%; } /* main */ #centralRow { height:70%; display: flex; } /* sidebar */ #sidebarColumn { background-color: #B83B1D; color: white; width:20%; display: flex; flex-direction: column; } #sidebarColumn nav { padding:1em; border:1px solid yellow; flex:1; } /* content */ #contentColumn { overflow: auto; flex:1; } .big { border:1px solid red; margin:1em; height:400px; } 
 <div class="wrapper"> <div id="topRow"> header </div> <div id="centralRow"> <div id="sidebarColumn"> sidebar <nav> nav links </nav> </div> <div id="contentColumn"> body content <div class="big">some big content</div> </div> </div> <div id="bottomRow"> footer </div> </div> 

https://jsfiddle.net/azizn/y4hag5o3/

+1
source

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


All Articles