Flexbox Conatiner inline taking up remaining width - html

I have a main <div> container, consisting of 3 child <div>'s:
<div id="parent">
<div id="child-left">.. some markup ..</div>
<div id="child-flex>
<div id="flex-child-1">
<div id="flex-child-2">
<div id="flex-child-3">
<div id="flex-child-4">
</div>
<div id="child-right">.. some markup ..</div>
</div>
child-left is display:inline and float:left, with a fixed
set width
child-right is display:inline and float:right,
with a fixed set width
child-flex is display:inline-flex
I would like to achieve the following:
Get the child-flex container to display inline in between child-left and child-right, and take up any remaining space.
Get all the flex-child- children to have equal width within the child-flex container. At the moment I have set flex: 1 0 auto;, but it does not seem to work. Could be because of the parent?

Just use flexbox throughout...in this case, use display:flex on the parent and then make the #child-flex flex-container a nested flexbox.
No need to use floats at all.
Codepen Demo
#parent {
display: flex;
height: 100px;
}
#child-right,
#child-left {
flex: 0 0 100px;
background: pink;
}
#child-flex {
flex: 1;
background: lightblue;
display: flex;
}
.flex-child {
flex: 1;
border: 1px solid grey;
}
<div id="parent">
<div id="child-left">some markup</div>
<div id="child-flex">
<div class="flex-child"></div>
<div class="flex-child"></div>
<div class="flex-child"></div>
<div class="flex-child"></div>
</div>
<div id="child-right">some markup</div>
</div>

Related

Have flex children only use space if they need it to not scroll, but otherwise share space equally and scroll

I have two flex children that may either each be small or large, and I'm defining small as < 50% of the container's height and large as > 50% the container's height. The sum of the heights of the children may be larger than 100% of the container's height, in which case I'd want one or both to scroll.
If one child is small and the other is large, I'd like the small element to use exactly the space it needs: it should not shrink to accommodate the large element, nor grow to 50%, and it should not scroll its contents. I'd like the large element to use the rest of the space, and scroll its contents if necessary.
If both are large, I'd like them to each use 50% of the container's height and scroll their contents.
I have this Codepen started as an example to help illustrate what I'm trying to achieve, but unfortunately it currently does no amount of scrolling or resizing: https://codepen.io/joeysilva/pen/wvmPqLK. It has both a small-large and a large-large case.
.flex-container {
height: 100px;
width: 100px;
display: flex;
flex-direction: column;
display: inline-block;
overflow: hidden;
}
.child {
flex: 50%;
overflow: auto;
}
.small {
background: red;
height: 30px;
}
.large {
background: blue;
height: 110px;
}
<div class="flex-container">
<div class="child">
<div class="small">Small</div>
</div>
<div class="child">
<div class="large">Large</div>
</div>
</div>
<div class="flex-container">
<div class="child">
<div class="large">Large 1</div>
<div class="large">Large 2</div>
</div>
</div>
Note 1: Not use disply:inline-block and display:flex the same time. Simply add another wrapper to show elements inside a row or column.
Note 2: flex: 50%; is equivalent to flex: 1 1 50%; and this is the shorthand form of flex-grow: 1; flex-shrink: 1; flex-basis: 50%;. Here in your code no need to use them because you have strictly defined the height of elements and also the basis of 50% height is wrong since you'd like the small element to use exactly the space it needs; no grow & no shrink, so it should be omitted.
.wrapper {
display: flex;
flex-direction: row;
}
.flex-container {
height: 100px;
width: 100px;
display: flex;
flex-direction: column;
overflow: hidden;
}
.child {
overflow: auto;
}
.small {
background: red;
height: 30px;
}
.large {
background: blue;
height: 110px;
}
<div class="wrapper">
<div class="flex-container">
<div class="child">
<div class="small">Small</div>
</div>
<div class="child">
<div class="large">Large</div>
</div>
</div>
<div class="flex-container">
<div class="child">
<div class="large">Large 1</div>
</div>
<div class="child">
<div class="large">Large 2</div>
</div>
</div>
</div>

How can I wrap columns vertically when their width doesn't fit their containers? [duplicate]

This question already has answers here:
When flexbox items wrap in column mode, container does not grow its width
(9 answers)
Closed 4 years ago.
I have problem with flexbox wrapping into column. The container doesn't fit the content width as seen in the snippet below.
This works if you replace both flex-flow of .wrapper and .container with flex-flow: row wrap, the height fit the content height its children, but the problem then is that the columns then flow horizontally and appear under each other, rather than flowing vertically and beside each other.
I expect the following result:
.wrapper {
display: flex;
flex-flow: column wrap;
max-height: 500px;
max-width: 500px;
overflow: scroll;
}
.container {
display: flex;
flex-flow: column wrap;
align-content: flex-start;
background-color: red;
margin: 5px;
}
.product {
margin: 3px;
min-width: 100px;
min-height: 100px;
background-color: #ccc;
text-align: center;
font-weight: bold;
line-height: 100px;
}
<div class='wrapper'>
<div class='container'>
<div class="product">0.1</div>
<div class="product">0.2</div>
<div class="product">0.3</div>
<div class="product">0.4</div>
<div class="product">0.5</div>
<div class="product">0.6</div>
<div class="product">0.7</div>
<div class="product">0.8</div>
</div>
<div class='container'>
<div class="product">1.1</div>
<div class="product">1.2</div>
<div class="product">1.3</div>
<div class="product">1.4</div>
<div class="product">1.5</div>
<div class="product">1.6</div>
<div class="product">1.7</div>
<div class="product">1.8</div>
</div>
<div class='container'>
<div class="product">2.1</div>
<div class="product">2.2</div>
<div class="product">2.3</div>
<div class="product">2.4</div>
<div class="product">2.5</div>
<div class="product">2.6</div>
<div class="product">2.7</div>
<div class="product">2.8</div>
</div>
<div class='container'>
<div class="product">3.1</div>
<div class="product">3.2</div>
<div class="product">3.3</div>
<div class="product">3.4</div>
<div class="product">3.5</div>
<div class="product">3.6</div>
<div class="product">3.7</div>
<div class="product">3.8</div>
</div>
</div>
The problem is that the .container doesn't have a width defined, so how .wrapper does have a maximum of with and it's a Flexbox, all the children (.container) will fit automatically to their parent, that's the problem.
You can solve it by setting a with to the container class.
Something like this: width: 212px;

Making container div exact size of wrapping contents [duplicate]

This question already has answers here:
CSS when inline-block elements line-break, parent wrapper does not fit new width
(2 answers)
How to remove the space between inline/inline-block elements?
(41 answers)
Closed 4 years ago.
I have a container div that has child divs with fixed widths and wraps. What I realised is that the container's width doesn't fit tightly to the content after it wraps, usually leaving a 'ghost' space on the right. Is there a way to force it to readjust the width according to its content?
.container {
max-width: 12em;
background-color: black;
}
.child {
display: inline-block;
width: 5em;
background-color: red;
}
<div class="container">
<div class="child">1</div>
<div class="child">2</div>
<div class="child">3</div>
<div class="child">4</div>
<div class="child">5</div>
<div class="child">6</div>
</div>
So in this case when the child wraps after 2 of them add up to 10em, the container instead of being 10em, it is still 12em. And if the window size forces it down to a single div wrapping, the container rather than being 5em, could be 6em, 7em, 8em, etc depending on window width.
Is there a way to get rid of the 'ghost' space and make the container fit exactly to how the child is wrapping and it's total width?
Note: I am not talking about the extra space in between each child element. I'm referring to the giant gap left in the container, which causes the container to not accurately reflect the size of its child content. I understand that I can simply count how many child can fit in 12em and change the container width to be 10em to fit 2 childs perfectly. But I want that to be flexible. Is that possible?
The extra space after each child element is a result of the display: inline-block property and is due to the literal whitespace between each div in your HTML. You may verify this by removing the linebreaks between child divs so that their open and close tags are back-to-back:
<div class="container">
<div class="child">1</div><div class="child">2</div><div class="child">3</div>/*...*/
</div>
Although this will eliminate the pesky whitespace, it comes at the expense of code clarity/readability and is surely an irritating way to write HTML.
In my experience, often the best solution to this issue is to set the parent container to display: flex:
.container {
display: flex;
flex-wrap: wrap;
max-width: 10em;
background-color: black;
}
.child {
display: inline-block;
width: 5em;
background-color: red;
}
<div class="container">
<div class="child">1</div>
<div class="child">2</div>
<div class="child">3</div>
<div class="child">4</div><div class="child">5</div>
<div class="child">6</div>
</div>
In this case you will also need to provide the flex-wrap: wrap property to inform the flex container to wrap its contents. Presumably you can now update the container's max-width property to 10em to fit exactly the width of two child elements so I've taken the liberty of this change in the code snippet.
Looks like you want to render a table. So you may want to use:
<table>
<tr>
<td>Col1</td>
<td>Col2</td>
</tr>
...
</table>
In case im wrong:
You can do this with flex or grid
Helpful link Flexbox, Grid
.container {
max-width: 12em;
background-color: black;
display: flex;
}
.child {
display: block;
min-width: 5em;
background-color: red;
border: 1px dashed blue;
}
/* FLEX */
.container-flex {
/* new row if next element doesnt fit */
flex-wrap: wrap;
}
.container-flex .child {
/* makes children grow evenly after wrapping */
flex-grow: 1;
}
/* GRID */
.container-grid {
display: grid;
/* 2 auto-horizontally sized colums */
grid-template-columns: auto auto;
}
.container-grid .child {
/* noting to do here */
}
<div style='float: left; margin-right: 10px;'>
Flex<br>
<small>extend elements to 6em</small><br>
<hr>
<div class="container container-flex">
<div class="child">1</div>
<div class="child">2</div>
<div class="child">3</div>
<div class="child">4</div>
<div class="child">5</div>
<div class="child">6</div>
</div>
</div>
<div style='float: left; margin-right: 10px;'>
Grid<br/>
<small>collapse container to 10em</small><br>
<hr>
<div class="container container-grid">
<div class="child">1</div>
<div class="child">2</div>
<div class="child">3</div>
<div class="child">4</div>
<div class="child">5</div>
<div class="child">6</div>
</div>
</div>
You can do it like this
.container { max-width: 4.5em;background-color: black; }
.child { display: inline-block; width:cover; background-color: red; }
<!DOCTYPE html>
<html>
<head>
<title>Answer</title>
</head>
<body>
<div class="container">
<div class="child">1</div>
<div class="child">2</div>
<div class="child">3</div>
<div class="child">4</div>
<div class="child">5</div>
<div class="child">6</div>
</div>
With the width set to 'cover' it covers the complete area leaving no space.In order to fix the black background (of container which is more or less acting like border), you can manually adjust it's size.

Control width of flex items arranged vertically in a flex container

I'm trying to achieve the effect where the boxes labeled "HALF", take up only 50% of the width (aka they share the first row evenly).
The base requirement is that they remain in a single container. Is this possible to achieve using flexbox?
I've tried playing around with flex-grow, flex-shrink, and flex-basis but I'm afraid I'm not understanding how to make it work, or if it's even possible, given the single container requirement.
Consider this fiddle: http://jsfiddle.net/GyXxT/270/
div {
border: 1px solid;
}
.container {
width: 400px;
display: flex;
flex-direction: column;
}
.child {
height: 200px;
}
.child.half {
flex: 1 1 10em;
color: green;
}
.child:not(.half) {
flex-shrink: 2;
flex-basis: 50%;
color: purple;
}
<div class="container">
<div class="child half">
HALF
</div>
<div class="child half">
HALF
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
</div>
Instead of flex-direction: column, you can try a wrapping flexbox using flex-wrap: wrap; and you can set:
flex-basis: 50% for the half width divs
flex-basis: 100% for the full width divs
See that I have thrown in box-sizing: border-box to adjust for the widths when using flex-basis.
See demo below:
div {
border: 1px solid;
box-sizing: border-box;
}
.container {
width: 400px;
display: flex;
flex-wrap: wrap;
}
.child {
height: 200px;
}
.child.half {
flex-basis: 50%;
color: green;
}
.child:not(.half) {
flex-basis: 100%;
color: purple;
}
<div class="container">
<div class="child half">
HALF
</div>
<div class="child half">
HALF
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
</div>
The flex sizing properties -- flex-grow, flex-shrink, flex-basis and flex -- work only along the main axis of the flex container.
Since your container is flex-direction: column, the main axis is vertical, and these properties are controlling height, not width.
For sizing flex items horizontally in a column-direction container you'll need the width property.
(Here's a more detailed explanation: What are the differences between flex-basis and width?)
To achieve your layout with a single container, see another answer to this question.
If you want to stay in column-direction, you'll need to wrap the .half elements in their own container.
.container {
display: flex;
flex-direction: column;
width: 400px;
}
.container > div:first-child {
display: flex;
}
.child.half {
flex: 1 1 10em;
color: green;
width: 50%;
}
.child {
height: 200px;
width: 100%;
border: 1px solid;
}
* {
box-sizing: border-box;
}
<div class="container">
<div><!-- nested flex container for half elements -->
<div class="child half">HALF</div>
<div class="child half">HALF</div>
</div>
<div class="child">FULL</div>
<div class="child">FULL</div>
<div class="child">FULL</div>
<div class="child">FULL</div>
</div>
The base requirement is that they remain in a single container.
That can also be done without flexbox, by simply float the 2 half elements
div {
border: 1px solid;
box-sizing: border-box;
}
.container {
width: 400px;
}
.child {
height: 200px;
}
.child.half {
float: left;
width: 50%;
color: green;
}
.child:not(.half) {
width: 100%;
color: purple;
}
<div class="container">
<div class="child half">
HALF
</div>
<div class="child half">
HALF
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
</div>
If the purpose is to hardcode the size in CSS units, or in percentages (which was mentioned the question), #kukkuz's solution is good as it is.
If you want to size element widths according to their own individual contents, then align-tems: flex-start or similar could do the job. It's possible to deal with the dimension perpendicular to that of the flex layout itself. See a tester on the bottom of the doc page
(Old question, but previous answers were incomplete, some are misleading)

CSS outline around a flex element not including child element margin?

I am using an outline and a margin in an attempt to avoid a double border around some flex-elements.
If I apply a margin to the flex element itself it works as expected. However, if I apply the margin to a child element the double border shows up again.
Why does the outline correctly render only when the margin is applied to the parent flex element? Is this a bug?
.comment {
padding:20px;
}
#flex-container {
display: flex;
}
.flex-element {
flex-grow: 1;
}
.flex-content {
width: 100%;
height: 100%;
margin-left: 5px;
outline: 5px solid #ccc;
}
.flex-element-working {
flex-grow: 1;
margin-left: 5px;
}
.flex-content-working {
width: 100%;
height: 100%;
outline: 5px solid #ccc;
}
<div class='comment'>
Why doesn't this work?:
</div>
<div id='flex-container'>
<div class='flex-element'>
<div class='flex-content'>
<div class='comment'> Flex Content</div>
</div>
</div>
<div class='flex-element'>
<div class='flex-content'>
<div class='comment'> Flex Content</div>
</div>
</div>
</div>
<div class='comment'>
Working Example:
</div>
<div id='flex-container'>
<div class='flex-element-working'>
<div class='flex-content-working'>
<div class='comment'> Flex Content</div>
</div>
</div>
<div class='flex-element-working'>
<div class='flex-content-working'>
<div class='comment'> Flex Content</div>
</div>
</div>
</div>
The point is in the top flex container (bad working) in double outline the left on is for the right div and the right one is for left div! Please add this style to your code:
.flex-content{background-color:red;}
You will see the out line is how you want.
.flex-content divs have width 303px But .flex-content-working divs have width 298px so in second one we have not such problem.
To see the width of your elements use developer tools of your browser and layout or box menu.
A bit another approach using padding and box-shadow:
#flex-container {
box-shadow: inset 0 0 0 2px red;
display: flex;
padding: 2px;
}
.flex-element {
flex-grow: 1;
box-shadow: inherit;
}
.comment {
padding: 20px;
}
<div id='flex-container'>
<div class='flex-element'>
<div class='flex-content'>
<div class='comment'> Flex Content</div>
</div>
</div>
<div class='flex-element'>
<div class='flex-content'>
<div class='comment'> Flex Content</div>
</div>
</div>
</div>