flex box make items 100% width of itself - html

I have the following html structure which I'm trying to arrange with a flex-box approach, with a row flex-direction. This is more or less the idea
<!-- 100% viewport width -->
<body>
<!-- This toolbar should have whatever width may remain from parent -->
<div class="toolbar-1 width-remain">
<!-- This toolbar should have whatever width may remain from parent -->
<div class="tb1-item1 width-remain">Some content</div>
<!-- This toolbar should have 100% of its content -->
<div class="tb1-item2 width-content">
<!-- This toolbar should have 100% of its content -->
<div class="tb1-item2-inner1 width-content">Some content</div>
<!-- This toolbar should have 100% of its content -->
<div class="tb1-item2-inner2 width-content">Some content</div>
<!-- This toolbar should have 100% of its content -->
<div class="tb1-item2-inner3 width-content">Some content</div>
</div>
<!-- This toolbar should have 100% of its content -->
<div class="tb1-item3 width-content">Some content</div>
</div>
<!-- This toolbar should have 100% of its content -->
<div class="toolbar-2 width-content">
<div class="tb2-item1 width-content">Some content</div>
</div>
</body>
I was hoping to have two toolbars where one may grow in width (the second one, and the first one may occupy whatever space is left). Also, inside the first toolbar I have some extra items which I'd like to be able to grow in width, and one item which may occupy whatever space is left).
In general the width set in the inner items as
flex: 1 1 100%; takes the 100% of its parent, and not of its width. Setting flex: 1 1 auto; makes the items to have an even width. Also tried putting 0 to the flex-growth and flex-shrink properties. I've tried setting justify-content: stretch; to the toolbar parent, and justify-self: stretch to the inner items that may grow based on its content but with no success.
does anyone know how I can achieve this? Thanks in advance!

It sounds like there's a misunderstanding on how to use the flex property with child elements within an element with display:flex;.
Essentially you need to tell .toolbar-1 it's okay to grow, and .toolbar-2 it's okay to shrink. To accomplish that you can certainly use the flex property like so:
.toolbar-1 {
flex: 1 0 auto; /* grow shrink basis */
}
.toolbar-2 {
flex: 0 1 auto;
}
Alternatively you can just use the grow and shrink properties:
.toolbar-1 {
flex-grow: 1;
}
.toolbar-2 {
flex-shrink: 1;
}
I threw together this example based on what I understand from the question: Flexible Toolbars

Related

How to stop parent containers from resizing to fit dynamic content

I have a setup like this
<app-component> <!-- need this to not fit the content but be reactively sized-->
<div> <!--display:flex-->
<form> <!-- display: flex-->
<div> <!-- display: block-->
<section> <!-- display: flex-->
<div> <!-- display:flex-->
<app-component> width:100%-->
<div> <!-- display: flex row-->
<div> <!-- overflow-x: scroll, whitespace: nowrap-->
***inserted here are photos the user is uploading***
***this extends from left to right ***
</div>
</div>
</app-component>
</div>
</section>
</div>
</form>
</div>
<app-component>
The problem is that the first app-component is resizing to fit the images as they continue to be added. immediate div containing the images, and its containing divs all act appropriately but the containing app-component fits the invisible photos which throws off the whole page.
I can easily solve this by setting static parameters for width but this is a reactive app and will have to scale to all different screen sizes so i was wondering if someone has a good solution that keeps the css fluid and not needing to add specific px sizes.
Have you tried setting the container to viewport units?
width: 100vw;
height: 100vh;
overflow: auto;

Form with variable content and control button in fixed area

The main issue that is not treated in similar questions listed below is a FORM object that has a variable part and a non variable footer (submit buttons)
The aim is to display:
A header (a table (width:100%) with a logo and a text in second cell): size should be the smallest possible with all content displayed
A FORM (containing 2 parts):
Fields are in a div that will expand to all space remaining and will scroll if it lack space. (minimum size: 1 text line)
Submit / Rest buttons are in a table and should ALWAYS be visible and not resized in anyway. At worst the stick to bottom of browser window.(except if browser window becomes ridiculously small of course)
Nothing should go below bottom of browser window (except if user resize to a ridiculous size).
Hardcoded height is NOT an option (except the 100% for technical reasons - body or column parent for example). Header and footer height MUST be autocomputed by browser to use minimum space while displaying all content. If user reduce the width of the browser window increasing the header or footer text to wrap on more lines, the height must grow accordingly. Thus percentage or viewport heigh is not an option as it is arbitrary and can't take car of the user zoom, the browser width resize and such.
I've tried the following layout:
<div id="column">
<div id="header>
<table><tbody>
<tr><td>LOGO</td><td>Some intro text on a few lines</td></tr>
</tbody></table>
<!-- optionnel error line (arbitrary length) if previous form submission failed -->
</div>
<form>
<div id="variable_scrollable_content">
<!-- multiple field sets hosting some input (text, select, ...) -->
</div>
<div id="footer">
<table><tbody>
<tr><td>Save button</td><td>Reset button</td></tr>
</tbody></table>
<!-- A few lines of text -->
</div>
</form>
</div>
After I gave a careful view to similar questions (see below), I was unable to find something that could handle the FORM object that has a variable size scrollable part and a fixed footer.
I also gave a careful look at https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Basic_Concepts_of_Flexbox with no more success.
I tried the flex approach for classes header, variable_scrollable_content and footer with no success. I also tried to put the form object in flex class but that doesn't work.
As I can't separate the FORM submit/reset buttons from the fields they manage, I don't know how to solve this.
header should stick to top of browser windows
footer (containing form control buttons) should stick to bottom of browser window at worst or stick at the end of the last fields if browser windows is big enough.
fields should be in a variable size container that uses all the remaining space between header and footer and has overflow-y:scroll; so it can scroll if it can't display its whole content.
In case the above simplified code is not sufficient, the "real" code can be found here:
https://github.com/finley/SystemImager/blob/initrd-from-imageserver-and-dont-package-initrd/webgui/edit_config.php
The full css is here:
https://github.com/finley/SystemImager/blob/initrd-from-imageserver-and-dont-package-initrd/webgui/css/screen.css
Similar questions
I have checked the following similar questions, and I believe my question is different as the main problem is the FORM object interfering with the layout:
scrolling content between fixed header & footer with variable height
Content height expand between fixed header and fixed footer
Make a div fill the height of the remaining screen space
Original question was here: variable height div between header and footer
I've just found the solution.
In this situation, the problem was the FORM object that would interfere with flex column children not at the same Dom level tree.
The simple solution was to move the FORM object so it includes the flex column it its whole content.
The above code becomes:
<form>
<div id="column">
<div id="header>
<table><tbody>
<tr><td>LOGO</td><td>Some intro text on a few lines</td></tr>
</tbody></table>
<!-- optionnal error line (arbitrary length) if previous form submission failed -->
</div>
<div id="variable_scrollable_content">
<!-- multiple field sets hosting some input (text, select, ...) -->
</div>
<div id="footer">
<table><tbody>
<tr><td>Save button</td><td>Reset button</td></tr>
</tbody></table>
<!-- A few lines of text -->
</div>
</div>
</form>
But this was not sufficient because setting flex column height to 100% (when body is also set to 100%) won't work. maybe the form object doesn't propagate the height?
The solution was to set height of column with vh (viewport height) unit.
So I set it to 100vh. Unfortunately, there are some glitches due to some border size and padding from parent objects and itself. So as a fallback I put it to 96vh, but this is ugly and I'll investigate and will remove the parasite border size padding that makes the body bigger than 100vh.
<body style="height: 100%">
<form>
<div style="display: flex; flex-flow: column; height: 100vh;">
<div id="header" style="flex: 0 0 auto;">foo bar</div>
<div id="content" style="flex: 1 1 auto; overflow-y: scroll;">Input fields</div>
<div id="footer" style="flex: 0 0 auto;">Control buttons</div>
</div>
</form>
</body>
The above sump is bigger than 100vh in height.
There are 2 solution to fix that:
Remove any border padding or such from parent object.
Set the column to an absolute position (0,0)
Alternative solution to scrollable FORM in flex content with fixed footer containing control buttons is to move FORM control buttons outside the form.
The code then looks like:
<body style="height: 100%">
<div style="display: flex; flex-flow: column; height: 100%;">
<div id="header" style="flex: 0 0 auto;">foo bar</div>
<div id="content" style="flex: 1 1 auto; overflow-y: scroll;">
<form id="foobar">
Input fields
</form>
</div>
<div id="footer" style="flex: 0 0 auto;">
<button form="foobar" type="submit" formmethod="POST">Submit</button>
<button form="foobar" type="reset">Reset</button>
</div>
</div>
</body>
The advantage is that it works with height 100% as it takes account of margin borders and padding of parent (while vh is an absolute viewport size).

Angular component destroys flexbox height information for its child elements

I have a flexbox parent container whose flex-grow gives my containing div element as much height as is available. The children of this div element of course have height:100%. This works fine.
<div style="display:flex; flex-direction:column;">
<div style="flex-grow:1;background:green;" id="parentContainer">
<div style="height:100%;overflow:auto;background:red;" id="contentContainer">
<!-- content of whatever size confined to space allocated -->
</div>
</div>
</div>
But when I have an angular component in-between the parentContainer and contentContainer like so:
<div style="display:flex; flex-direction:column;">
<div style="flex-grow:1;background:green;" id="parentContainer">
<my-ng-component style="height:100%; display:block; background:blue;">
<div style="height:100%;overflow:auto;background:red;" id="contentContainer">
<!-- content of whatever size confined to space allocated -->
</div>
</my-ng-component>
</div>
</div>
The angular component resets the height to 0px, so the contentContainer ends up with 0px height as well.
How do I fix the angular component to not destroy the height information?
Plunk: http://plnkr.co/edit/0eai5HFZh7o2Vguzd5j6?p=preview
Generally, height: 100% doesn't work properly on child of a flex child, and the main reason is that Flexbox stretch to fit its flex parent but still resolve its height to auto, as shown here in this answer:
Why height=100% doesn't work?
In your case though, when using flex column direction, it is possible.
The now used flex-grow: 1 will leave the flex-shrink and flex-basis to their default, 1 and auto, and here it is the auto that cause the issue.
By changing it to, and here using the recommended shorthand flex, flex: 1 100% the child and its descendants will have a height to pick up their 100% from.
Note 1, simply using flex: 1 (same as flex: 1 1 0) works too on Chrome/FF/Edge/IE11, but if I'm not wrong, Safari 10 had some issues when flex-basis becomes 0.
Updated plnkr
With the following updated code fragments
app.component.html
<div style="display:flex;flex-direction:column;height:324px;">
<div style="flex:1 100%; background:black; color: white;">
foo
<app-list style="height:100%;display:block; background:blue;"></app-list>
</div>
</div>

Fluid content div with optional sidebar

I have a question that I haven't found addressed in the various CSS layout models I've looked at, so I thought I'd post it here.
I'm working on a site that uses a basic fluid/fixed two-column layout. The content of the site is in the left div, and the sidebar in the right. The sidebar has a fixed width of 200 pixels or so, and the content expands to fill out the remaining width of the parent.
Here's what the code looks like:
<div style="width: 90%; margin: 10px auto 10px auto;"> <!-- site container -->
<div style="margin-right: 200px;">Content goes here.</div>
<div style="float: right; width: 200px;">Menus goes here.</div>
<div style="clear: both;"></div> <!-- float-clearer div -->
</div>
This is a pretty standard approach and works fine for the most part, but the issue is that the design of the site requires the sidebar to only appear in certain cases. All of the HTML is generated through PHP, and the "get-content()" function doesn't know whether the "get-sidebar()" one will be called or not.
When the sidebar is called, I'd like the content to expand out to fill the parent div while leaving enough room for the sidebar. If there is no sidebar, the content should expand out to fill the entire width of the parent.
Is there any way to do this with CSS -- perhaps using "auto" for the content margins -- without relying on PHP/JavaScript?
You might consider doing it like this:
<div style="width: 90%; margin: 10px auto 10px auto;"> <!-- site container -->
<div style="background-color:#CCC;height:100%;">
<div style="background-color:#444;float: right; width: 200px;height:100%;">Menus goes here.</div>
Content goes here.
</div>
<div style="clear: both;"></div> <!-- float-clearer div -->
</div>
By doing it that way, the menu sits inside the main div and there is no margin-right, so when the menu goes away, the text expands to fill the space.
The "height:100%;" ensures that the menu and content boxes stretch to the same height. You could also set this to a pixel or em amount or a percentage less than 100 if you want.
Instead of floating the sidebar, try this:
#sidebar {
display: inline-block;
display: -moz-inline-box;
-moz-box-orient: vertical;
vertical-align: top;
zoom: 1;
*display: inline;
}
Would it be possible to add a class to the body using PHP? Something like "one-col" or "two-col" depending on the context. Then you can give the content div a margin when there is a sidebar, but not when there isn't.

Simple CSS MasterPage layout

I'm helpless, tried my best understanding CSS but it's just not for me.
I would like to make a really simple MasterPage:
at the top a div of full width and height 40px (1)
at the bottom also a div of full width and height 40px (2)
in the middle:
on the left: a div of width 200 px (3)
on the right side of the left div: a div with contentPlaceHolder (4)
What I would like to get is: if i make some site that uses my master page and place a panel in the contentPlaceHolder that has width 800px, I would like my site to adjust to it - top, middle and bottom divs to have their width of 1000px (200 + 800). I also wouldn't like (and I have a huge problem with that) the (4) to move down if I resize (shrink) the browser window - I would like all the divs to be blocked.
This is my master page html:
<div>
<div class="header">
</div>
<div>
<div class="links">
</div>
<div class="content">
</div>
</div>
<div class="footer">
</div>
</div>
What kind of CSS do I have to write to make this finally work?
Not sure if you have checked into this or not, but we use the YUI-Grids CSS Framework for our layouts. It keeps us from having to spend a lot of time on CSS, which we are not great at being developers.
There is even a grid builder which will let you graphically layout a page, and then copy and paste the required HTML to make it happen :)
To prevent floated divs from being "squeezed" out of the alignment you want, you usually use either width or min-width.
For example, in this code the div containing the links and content will never be smaller than 1000 pixels. If the screen is smaller than 1000 pixels, a scrollbar is displayed.
<div style="min-width: 1000px">
<div class="links"></div>
<div class="content"></div>
</div>
You could also use width instead of min-width:
<div style="width: 1000px">
<div class="links"></div>
<div class="content"></div>
</div>
The difference between the two is simple: if you specify min-width, the div CAN grow to be larger if it needs to. If you specify width, the div will be exactly the size you specified.
Be aware that min-width is not supported by IE6.
Here's a quick stab at specific CSS/Markup for this problem.
Markup:
<!-- Header, etc. -->
<div class="contentView">
<div class="links">
</div>
<div class="content">
</div>
</div>
<!-- Footer, etc. -->
CSS:
.contentView {
/* Causes absolutely positioned children to be positioned relative to this object */
position: relative;
}
.links {
position: absolute;
top: 0;
left: 0;
width: 200px;
}
.content {
padding-left: 200px;
}
You might want your footer to be "sticky." Check here for information on that: http://ryanfait.com/resources/footer-stick-to-bottom-of-page/
How appropriate this is depends on precisely what the design calls for. This makes the links section more of a floating box on the left than a column for example.
This ends up looking like this (.content is green, .links is red):