In a dom structure like this:
<div id="1">
<div id="2">
<div id="3">
</div>
</div>
<div id="4">
<div id="5">
</div>
</div>
</div>
with css specified as:
#1{
display: flex;
flex-direction: row;
}
#2, #4{
flex: 1;
}
The divs with id 2 and 4 will be evenly distributed as long as the sum of the width of the contents in id 3 and 5 does not exceed the width of the dom with id 1.
When the sum exceeds the width, they are not evenly distributed, and one with wider content will take up more width. How can I force 2 and 4 to take up even width using flexbox even in such cases?
I do not want to use width specification by percent. I want to stick to flexbox.
If you want elements to grow or shrink independently to it's content, specify zero flex basis:
flex-basis: 0;
However, my demo incorrectly works in Chrome: large image stretches it's parent container no matter that zero basis has been set. As a workaround, maximum width can be set:
img {
max-width: 100%;
height: auto;
}
To force the equal distribution, you have to add width: 0 to all flex items. This came to my mind after reading Manuel Matuzovic's article, which has a very good in-depth conclusion how flex-grow works.
https://css-tricks.com/flex-grow-is-weird/
Related
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
I'm experiencing various glitches, weird rendering artifacts and so forth on my React application and was wondering about the way defining dimensions works from a browser's point of view.
Let's say I have a grid display, and there's a div which has grid-template-columns: 1fr auto 1fr and a child div which has spans grid-column: 2 / 3 - in other words spanning in the auto area of the parent grid.
As I understand, the value auto in grid template columns defines the column to be sized to fit its contents.
Now let's add an img with the max-width set to 100% - in other words, we don't want to exceed the size of the parent container.
However, the parent container's width is determined by the auto rule - so how can the browser let the child know to take up 100%?
Example
.box {
display: grid;
grid-template-columns: 1fr auto 1fr;
background-color: lightblue;
}
.box>div {
border: 1px solid red;
grid-column: 2 / 3;
margin: 10px 10px 0px;
}
<div class="box">
<div style="">
<img src="https://via.placeholder.com/800" style="max-width:100%">
</div>
</div>
To explain this, I will start with a more simplified example that will produce the same output:
<div style="display:inline-block">
<img src="https://via.placeholder.com/1000x100">
</div>
<div style="display:inline-block">
<img src="https://via.placeholder.com/1000x100" style="max-width:100%">
</div>
<div style="display:inline-block">
<!-- even a big explicit width specified won't change the behavior -->
<img src="https://via.placeholder.com/1000x100" style="wdith:2000px;max-width:100%">
</div>
<div style="display:inline-block">
<img src="https://via.placeholder.com/1000x100" style="width:100%">
</div>
We have an inline-block element so its width depend on its content and the use of max-width:100% (or width:100%) will give us the strange result.
To understand this, we need to refer to the specification and more precisely Percentage Sizing section where we can read:
Sometimes the size of a percentage-sized box’s containing block depends on the intrinsic size contribution of the box itself, creating a cyclic dependency. When calculating the intrinsic size contribution of such a box (including any calculations for a content-based automatic minimum size), a cyclic percentage—that is, a percentage value that would resolve against a containing block size which itself depends on that percentage—is resolved specially:
Our box is the image and the containing block is the inline-block div. The image is a replaced element so we need to follow the (b) and (c) to identify the max-content contribution and the min-content contribution
b. Likewise, if the box is replaced, then the entire value of any max size property or preferred size property specified as an expression containing a percentage that is cyclic is treated for the purpose of calculating the box’s max-content contributions only as that property’s initial value.
Considering max-width/width as auto will keep the max-content contribution the same (1000px in our case). What will change is the min-content contribution:
c. If the box is replaced, a cyclic percentage in the value of any max size property or preferred size property (width/max-width/height/max-height), is resolved against zero when calculating the min-content contribution in the corresponding axis.
So the min-content contribution of the image will become 0 and no more 1000px which was the initial min-content contribution based on its intrinsic dimension (related: https://www.w3.org/TR/css-sizing-3/#intrinsic-sizes) and all the trick is here!
Now our inline-block is a shrink-to-fit element and the following algorithm apply:
Then the shrink-to-fit width is: min(max(preferred minimum width, available width), preferred width). ref
the contribution of the image will vary from 0 to 1000px so the browser will pick the value that will avoid any overflow (the available width part) and not bigger than 1000px (the min part)
Without the use of percentage the min-content of the image was 1000px so the browser is obliged to use a value between 1000px and 1000px as preferred minimum width which will give the div the intrinsic size width of the image.
All this is only the calculation of the div width. After this, we consider the calculated width as a reference for our percentage value.
We can also consider different value and the logic will be the same:
div {
border:2px solid red;
margin:5px;
}
<div style="display:inline-block">
<img src="https://via.placeholder.com/1000x100">
</div>
<div style="display:inline-block">
<img src="https://via.placeholder.com/1000x100" style="max-width:80%">
</div>
<div style="display:inline-block">
<img src="https://via.placeholder.com/1000x100" style="width:50%">
</div>
The above logic apply the same way to your code since your column is set to auto which means that its size is based on its content and is also the containing block of the image.
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>
I'd like the CONTENT flex column to wrap around the left-hand rowChild592 column.
I have this:
I'd like it to look something like this:
I saw an answer here about making a div set to a table cell wrap around:
Wrapping table content around a floating div across multiple rows
Would I have to redo all of this with a table, or is it possible to wrap a flex column around another?
.rowParent,
.columnParent {
display: flex;
}
.columnParent {
flex-direction: column;
}
.flexChild {
flex: 1;
}
#flexymenu {
flex-grow: 2;
height: 100%;
}
.frame {
display: block;
margin: 0 auto;
}
.socialwrap {
display: flex;
}
<div id="container" class="flexChild rowParent">
<div id="rowChild592" class="flexChild">
<h1></h1>
<div class="socialwrap"></div>
</div>
<div id="flexymenu" class="flexChild columnParent">
<div id="columnChild85412" class="flexChild rowParent">
<div id="rowChild97758" class="flexChild"></div>
<div id="rowChild52237" class="flexChild"></div>
</div>
<div id="columnChild59385" class="flexChild selected">
<div class="frame">CONTENT</div>
</div>
</div>
</div>
In flex layout, elements can be aligned along columns or rows. A flex item cannot span between both columns and rows, which could allow the content of one item to wrap around another item. So, flexbox is not a good option for achieving your layout. Read more.
In grid layout, elements can span across columns and rows. A grid item can be configured to take up as many rows and columns as desired, which would allow for the content of one item to wrap around other items, except for one limitation currently in place: The grid area must be rectangular.
This behavior is defined in two parts of the spec.
9. Placing Grid
Items
Every grid item has a grid area, a rectangular set of grid cells that
the grid item occupies.
7.3. Named Areas: the grid-template-areas
property
If a named grid area spans multiple grid cells, but those cells do not
form a single filled-in rectangle, the declaration is invalid.
Note: Non-rectangular or disconnected regions may be permitted in a
future version of this module.
So, for the foreseeable future, tetris-shaped grid areas are not possible, which would make your layout simple and easy.
To wrap your text around images, stick to the good ol' float property. After all, this is exactly what it was designed to do.
And if you're thinking about using float inside a flex or grid container, it won't work. Floats are ignored in both a flex formatting context and grid formatting context.
I want to put the same div twice on the same row and cover all of its width and I need to put some space between them both.
The problem is when I use margin it will affect them both since they have same class so the second div will go below the other because the total width will become bigger than the container width.
I tried to use overflow:hidden or overflow-x:hidden with margin or change their size but nothing changed.(also I've tried to use borders with overflow hidden)
I am forced to use many div from the same class and I need them to cover all the width of the row.
Edit: the code is big so I will post a small example to explain my question
<div class="container">
<div class="block">content...</div>
<div class="block">content...</div>
</div>
<style>
.container{width:1000px; margin:0px auto;}
.block{width:480px;height:500px;float:left;}
</style>
I want to put first block + 40px space + second block
If you want the two .block divs on the same row what I would do is not do it in pixels but with %'s.
For example what I would do is this:
Give your div that you want on the right an id of right and the one that you want on the left an id of left:
<div class="container">
<div class="block" id="right">content...</div>
<div class="block" id="left">content...</div>
</div>
Then I would style it with
<style>
.container{width:1000px; margin:0px auto;}
.block{width:48%;height:500px;display:inline;}
#left{float:left;}
#right{float:right;}
</style>
You can play around with the exact width percent to get it to your standards.
You might want to make give them different class names or ids if you want to manipulate the two of them different.
<div class="container">
<div class="block1">content...</div>
<div class="block1">content...</div>
</div>
You can use inline display to make them appear in the same row.
.block1, block2 {
display: inline;
}
From there you can style them how you want by selecting either of those classes.
Could this be something like you're after?
http://jsfiddle.net/justin_thomas/9S46N/
The CSS:
.myRow {
width:48em;
}
.myclass {
padding: 1em;
margin-left:1em;
margin-right:1em;
float: left;
display:inline;
width: 20em;
}
The HTML:
<div class="myRow">
<div class="myClass">Blah... blah...</div>
<div class="myClass">Blah... blah...</div>
</div>
In there, i've used floats to get the desired effect. Unfortunately this means you have a hard time if you can't specify the actual width of the row's container in physical units (or one of its parents) and you also need to know whe number of columns there will be in this row to use as the width amount in the class with the divs.
I don't really like this as as solution as you need to make sure that the sum of each (div width + left-margin + right-margin) is never larger than the width of the row container.