Align-content property is working on a single line - html

I am learning Flex Box and I have troubles with the property align-content. The property shouldn't have result when there is a single line, but in my case it does and I can't understand why.
The result is that my single line of divs is at the end of my container.
I will be glad for some help.
.conteiner {
border: solid red;
display: flex;
flex-direction: row;
flex-wrap: wrap;
min-height: 500px;
justify-content: flex-start;
align-items: flex-start;
align-content:flex-end
}
.child {
min-height: 100px;
min-width: 100px;
background-color: lightblue;
margin: 10px;
}
<body>
<section class="conteiner">
<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>
</section>
</body>

try this:
.container{
justify-content: flex-end;
}

Likely, the reason your code is not working as intended... The result is that my single line of divs is at the end of my container. I will be glad for some help.
Is because of this line of code:
align-content:flex-end
Also, in your code, you did not close the css function with a semicolon either.
this means the content in your div that is defined as flex, will have its content placed at the end of the parent element. Likely simply changing this to one of the other definitions for align-content will be the outcome you are looking for.
The following article should assist you in understanding flex-box alignment better:
Aligning Items in a Flex Container

From my comment :
if you read the specification, you'find out that it doesn't work when flex-wrap is set to no wrap. you did set flex-wrap:wrap, so if you have a single line, it does work and send the content all the way down. You probably need javascript to reset the wrap property when your flex children stands on a single row.
https://developer.mozilla.org/en-US/docs/Web/CSS/align-content
The CSS align-content property sets the distribution of space between and around content items along a flexbox's cross-axis or a grid's block axis.
This property has no effect on single line flex containers (i.e. ones with flex-wrap: nowrap).
here is a possible javascript workaround, not on flex-wrap but align-content value to get the expected result for both case (a single line or many) : resize the window to wrap an unwrap your flex children
window.onload = check;
window.onresize = check;
let flexbox = document.querySelector(".conteiner");
function check() {
flexbox.style.alignContent = "flex-start";
var child = document.querySelector(".conteiner > :last-child");
var childPos = child.offsetTop;
child.style.color="red";
var parentPos = flexbox.offsetTop;
var childOffset = childPos - parentPos;
console.log( parentPos + ' - ' + childPos)
if (childOffset > 20) {
flexbox.style.alignContent = "flex-end";
}
}
.conteiner {
border: solid red;
display: flex;
flex-direction: row;
flex-wrap: wrap;
min-height: 500px;
justify-content: flex-start;
align-items: flex-start;
align-content:flex-end
}
.child {
min-height: 100px;
min-width: 100px;
background-color: lightblue;
margin: 10px;
}
<section class="conteiner">
<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>
</section>

Related

Using Flexbox, how do you separate two items even after the row wraps? [duplicate]

I have a
<div class="parent">
<div class="child" style="float:right"> Ignore parent? </div>
<div> another child </div>
</div>
The parent has
.parent {
display: flex;
}
For my first child, I want to simply float the item to the right.
And my other divs to follow the flex rule set by the parent.
Is this something possible?
If not, how do I do a float: right under flex?
You can't use float inside flex container and the reason is that float property does not apply to flex-level boxes as you can see here Fiddle.
So if you want to position child element to right of parent element you can use margin-left: auto but now child element will also push other div to the right as you can see here Fiddle.
What you can do now is change order of elements and set order: 2 on child element so it doesn't affect second div
.parent {
display: flex;
}
.child {
margin-left: auto;
order: 2;
}
<div class="parent">
<div class="child">Ignore parent?</div>
<div>another child</div>
</div>
You don't need floats. In fact, they're useless because floats are ignored in flexbox.
You also don't need CSS positioning.
There are several flex methods available. auto margins have been mentioned in another answer.
Here are two other options:
Use justify-content: space-between and the order property.
Use justify-content: space-between and reverse the order of the divs.
.parent {
display: flex;
justify-content: space-between;
}
.parent:first-of-type > div:last-child { order: -1; }
p { background-color: #ddd;}
<p>Method 1: Use <code>justify-content: space-between</code> and <code>order-1</code></p>
<div class="parent">
<div class="child" style="float:right"> Ignore parent? </div>
<div>another child </div>
</div>
<hr>
<p>Method 2: Use <code>justify-content: space-between</code> and reverse the order of
divs in the mark-up</p>
<div class="parent">
<div>another child </div>
<div class="child" style="float:right"> Ignore parent? </div>
</div>
Use justify-content: flex-end; in parent:
display: flex;
width: 100%;
flex-wrap: wrap;
justify-content: flex-end;
more info
display: flex;
flex-wrap: wrap;
justify-content: space-between;

CSS flexbox giving unexpected output

I have below markup for testing flexbox:
<html>
<head>
<style>
.parent{
display: flex;
flex-direction: column;
}
.parent>div>button{
display: flex;
}
.parent>div:nth-child(2){
display: flex;
}
</style>
</head>
<body>
<div class="parent">
<div class="div1"><button>butt1</button><button>butt7</button></div>
<div class="div2"><button>butt2</button><button>butt3</button><button>butt4</button>
<button>butt5</button><button>butt6</button></div>
</div>
</body>
</html>
Its output is given below:
What I don't understand is that even if we haven't given any flex-direction: column to the div1 i.e., we haven't written:
.parent>div>button{
display: flex;
flex-direction: column;
}
even then butt1 and butt7 are aligned in column. Why they are not aligned in row?? Is it the case that child div inherits the value of flex-direction of parent? I have read that default value of flex-direction is row. So, with that logic as well, they should have been aligned row-wise, not column-wise.
Please help me to find the reason of above behaviour.
Thank You.
The problem is in this:
.parent>div>button{
display: flex;
}
You overwritten default style of button, which is display: inline-block. display: flex works for children not for element itself, so your buttons behave like normal div (display: block). If you want to use flex in your way even if it's inappropriate change it to display: inline-flex.
More precise information directly from specification:
flex -
This value causes an element to generate a flex container box that is block-level when placed in flow layout.
inline-flex - This value causes an element to generate a flex container box that is inline-level when placed in flow layout.
#IMPROVEMENT
You have a lot of code that is not needed.
You can achieve same result by:
.parent > div {
display: flex;
}
<div class="parent">
<div>
<button>butt1</button>
<button>butt7</button>
</div>
<div>
<button>butt2</button>
<button>butt3</button>
<button>butt4</button>
<button>butt5</button>
<button>butt6</button>
</div>
</div>
If you want to apply a flex to the div1 do it like this:
.parent>.div1{
display: flex;
}
See here, I've added a background color for you to see what's going on:
.parent {
background: red;
display: flex;
flex-direction: column;
}
.parent>.div1 {
background: blue;
margin: 10px;
display: flex;
}
.parent>div:nth-child(2) {
background: green;
margin: 10px;
display: flex;
}
<div class="parent">
<div class="div1">
<button>butt1</button><button>butt7</button>
</div>
<div class="div2">
<button>butt2</button><button>butt3</button><button>butt4</button>
<button>butt5</button><button>butt6</button>
</div>
</div>
this line of CSS is the issue:
.parent>div>button{
display: flex;
}
You are telling css CSS using > that rules will be applied to elements which are direct children of the .parent -> div -> button element.
.parent {
display: flex;
flex-direction: column;
}
.parent>div:nth-child(2) {
display: flex;
}
<div class="parent">
<div class="div1"><button>butt1</button><button>butt7</button></div>
<div class="div2"><button>butt2</button><button>butt3</button><button>butt4</button>
<button>butt5</button><button>butt6</button></div>
</div>

Vertical layout css

I would like to create a vertical layout with flexbox.
Here is the structure :
.container {
display: flex;
flex-direction: column;
}
<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 class="child">7</div>
<div class="child">8</div>
</div>
And it should display 6 items per column
1 7
2 8
3
4
5
6
For the structure to break into a new column, it needs to know the limit to which it can fit its contents.
To make it clear, think of a simple paragraph tag with some text. Once the text exceeds the width of the page (or the container), the excess text wraps to the next line. So, in case of rows, width can be set as the limit, which is by default 100% of the viewport width or 100% of the container's width.
But here as we are dealing with columns and it takes height as the limit, the challenge here arises as the height is limitless in a HTML document. Because the height of a page increases to any extend when the content increases along with the vertical scroll bar. (Note that the same can be made possible in case of width with overflow a horizontal scroll bar, but here we are talking about the default behaviour).
Therefore, in this situation, to break the contents into a new column is only possible (exception with CSS grid) if we specify a height to the container.
It can either be specified in pixels or rem as mentioned in other answers.
Or if you are looking for a behaviour equivalent to the rows' as mentioned above, you can resort to viewport-height similar to viewport-width in case of rows. PEN
body {
margin: 0;
}
.container {
display: flex;
flex-direction: column;
flex-wrap: wrap;
height: 100vh;
}
.child {
height: 16.667vh;
}
Please note that this is not a perfect solution as it could cause misalignment when the content exceeds the height and also have browser compatibility issues. Also you may consider CSS grid or try Javascript solutions to perfectly tackle this scenario.
Hope this helps.
Try this style:
.container {
display: flex;
flex-direction: column;
height: 112px;
flex-wrap: wrap;
}
What I did here is set height to the container div so that the flex items wrap to the next column when it overflows. For this you need to set flex-wrap: wrap; too. In this case, height: 112px caused the overflow. You can change it as per your requirements.
The height is dynamic, base on the number of items you want to control vertically (in this case 6), I have calculated the height base on a 1rem font-size:
Example for 6 items:
.container {
display: flex;
flex-flow: column wrap;
font-size: 1rem;
max-height: calc(6 * 1.2em);
}
<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 class="child">7</div>
<div class="child">8</div>
</div>
Example for 7 items:
.container {
display: flex;
flex-flow: column wrap;
font-size: 1rem;
max-height: calc(7 * 1.2em);
}
<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 class="child">7</div>
<div class="child">8</div>
</div>
As the OP agreed to accept a CSS Grid solution, here is one:
.container {
display: grid;
}
.child:nth-child(6n + 2) {
grid-row-start: 2;
}
.child:nth-child(6n + 3) {
grid-row-start: 3;
}
.child:nth-child(6n + 4) {
grid-row-start: 4;
}
.child:nth-child(6n + 5) {
grid-row-start: 5;
}
.child:nth-child(6n) {
grid-row-start: 6;
}
PEN - Hope this helps.

Making a child of a flex container NOT a flex item

I believe this goes exactly against the way the display: flex property is supposed to work, but I wonder if it's possible, or if there's a hack for it.
Is it possible to have a child of a flex container not behave as a flex item? Example:
http://jsbin.com/jusehedumi/edit?html,css,output
Is there any way in which child three could be made behave as a normal display block? Without it automatically aligning due to the justicity-content: center of the parent flex container?
A purely css solution would be awesome. Thinking about it, adding some extra HTML would probably make this issue easier to fix/solvable.
.flex{
display: flex;
justify-content: center;
width: 400px;
height: 400px;
background: #ccc;
}
.child{
width: 100px;
height: 100px;
background: red;
margin: 20px;
}
.child.three{
background: blue;
display: block;
}
Is there any way to make child three not behave as a flex child?
<div class="flex">
<div class="child one"></div>
<div class="child two"></div>
<div class="child three"></div>
</div>
Edit: I know a child can be taken out of the flex container by using position: absolute or the likes. What I'm looking for is a way of making one of the children behave as a block element (or inline for that matter) while remaining a child of the flex container.
Updated based on a question edit
No, there is no property that can be set, to make a flex container child stop being a flex item.
What can be done though, is to not use any flex properties on one, and by that make it behave as a block or inline-block element.
E.g., combined with flex-wrap: wrap enabling items to wrap, giving the third item flex: none will make it behave as an inline block, giving it width: 100% it will behave as a block (as shown below).
When it comes to flex container properties, some can be overridden on the item, like align-items / align-self, some cannot, like justify-content.
To mimic justify-content in your given code sample, auto margins could be used, and with that, together with a trick using the order property and a pseudo element, one could make the third behave like an inline block:
.flex{
display: flex;
flex-wrap: wrap;
align-content: flex-start;
width: 400px;
height: 400px;
background: #ccc;
}
.child{
width: 100px;
height: 100px;
background: red;
margin: 20px;
}
.child.one{
margin-left: auto;
}
.child.two{
margin-right: auto;
}
.flex::after{
content: '';
width: 100%;
order: 1;
}
.child.three{
background: blue;
order: 2;
}
Is there any way to make child three not behave as a flex child?
<div class="flex">
<div class="child one"></div>
<div class="child two"></div>
<div class="child three"></div>
</div>
As a note, here is a good answer that describes the flex item's display type:
What are allowed values of the `display` property for a flex-item? (layout of flex-item’s children is irrelevant)
Initial answer
Is it possible to have a child of a flex container not behave as a flex item?
There is no good, cross browser solution to make a flex container child not behave as a flex item.
One can use absolute positioning, though as it will take the element out of flow, it won't behave like a block element when it comes to content flow.
Is there any way in which child three could be made behave as a normal
display block?
Based on the fact that a normal block element take a row of its own, filling its parent's width, you can, by adding flex-wrap: wrap to the container and give the third item a width of 100%, make it behave like one.
Note, I also added align-content: flex-start; so the items won't stretch/spread along the parent's height, instead align at its top.
.flex{
display: flex;
flex-wrap: wrap;
justify-content: center;
align-content: flex-start;
width: 400px;
height: 400px;
background: #ccc;
}
.child{
width: 100px;
height: 100px;
background: red;
margin: 20px;
}
.child.three{
background: blue;
width: 100%;
}
Is there any way to make child three not behave as a flex child?
<div class="flex">
<div class="child one"></div>
<div class="child two"></div>
<div class="child three"></div>
</div>
If you want the third item to keep the same width as the first two, a wrapper could help you.
.flex{
display: flex;
flex-wrap: wrap;
justify-content: center;
align-content: flex-start;
width: 400px;
height: 400px;
background: #ccc;
}
.child{
width: 100px;
height: 100px;
background: red;
margin: 20px;
}
.child.three{
background: blue;
}
.wrapper{
width: 100%;
}
Is there any way to make child three not behave as a flex child?
<div class="flex">
<div class="child one"></div>
<div class="child two"></div>
<div class="wrapper">
<div class="child three"></div>
</div>
</div>
If a wrapper can't be used, you could use a right margin, though since percent based margin might render different on different browsers, you need to test it properly, or use another unit, e.g. viewport units, like vw.
.flex{
display: flex;
flex-wrap: wrap;
justify-content: center;
align-content: flex-start;
width: 400px;
height: 400px;
background: #ccc;
}
.child{
width: 100px;
height: 100px;
background: red;
margin: 20px;
}
.child.three{
background: blue;
margin-right: calc(100% - 120px);
}
Is there any way to make child three not behave as a flex child?
<div class="flex">
<div class="child one"></div>
<div class="child two"></div>
<div class="child three"></div>
</div>
If neither of the above solutions is an option, the same layout can be achieved using block and inline block elements.
.flex{
/* removed the Flexbox properties
display: flex;
flex-wrap: wrap;
justify-content: center;
*/
text-align: center; /* added */
width: 400px;
height: 400px;
background: #ccc;
}
.child{
display: inline-block; /* added */
width: 100px;
height: 100px;
background: red;
margin: 20px;
}
.child.three{
background: blue;
display: block;
}
<strike>Is there any way to make child three not behave as a flex child?</strike>
<div class="flex">
<div class="child one"></div>
<div class="child two"></div>
<div class="child three"></div>
</div>
Only elements that are in-flow children of a flex container are flex items.
Therefore, elements that are absolutely-positioned children or descendants beyond the children of a flex container are not flex items and ignore flex properties.
See my answer here for more details:
Absolutely positioned flex item is not removed from the normal flow in IE11

using a flex item as a flex container

I wanted to use flexbox with a column layout, but I wanted the top n - 1 flex items to be pinned to the top and the nth flex item to be pinned to the bottom of the main flex container area.
I solved this by using the nth flex item to also be a new flexbox/flex container using justify-content: flex-end, but I couldn't find any examples that were doing this - so is this a correct/acceptable solution according to the standard and, if not, how would I otherwise go about this with flexbox?
Here's a quick example:
.flex-container {
display: -webkit-flex;
display: flex;
-webkit-flex-direction: column;
flex-direction: column;
width: 300px;
height: 240px;
background-color: Silver;
}
.flex-container-bottom {
display: -webkit-flex;
display: flex;
-webkit-flex-direction: column;
flex-direction: column;
width: 300px;
height: 240px;
background-color: orange;
-webkit-justify-content: flex-end;
-ms-flex-pack: end;
justify-content: flex-end;
}
.flex-item {
background-color: DeepSkyBlue;
width: 100px;
height: 100px;
margin: 5px;
}
.flex-item-bottom {
background-color: red;
width: 100%;
height: 50px;
}
<div class="flex-container">
<div class="flex-item">flex item 1</div>
<div class="flex-item flex-container-bottom">
<div class="flex-item-bottom">flex item 2</div>
</div>
</div>
The spec isn't very clear on this, but it states that "Each in-flow child of a flex container becomes a flex item, and each contiguous run of text that is directly contained inside a flex container is wrapped in an anonymous flex item." This seems to imply that if I put a flex container inside another flex container that the inner flex container would also implicitly become a flex item for its containing flex container even if this is not explicitly defined. Example 1 of the specification shows a flex container within a flex container and assuming it is legal syntax it follows that my use case may also be legal, but the section with example 1 is marked as non-normative... (╯°□°)╯︵ ┻━┻... At this point I'm just going to assume this is correct.
It's hard to say that your use of flex-end is wrong because you're getting the desired effect, but there's an easier way to do it.
Try using:
.flex-container{
display: flex;
justify-content: space-between;
flex-direction: column;
}
justify-content: space-between; forces your flex items to spread out as much as possible in the flex container.
This is the reference guide I use whenever doing anything with flexboxes:
https://css-tricks.com/snippets/css/a-guide-to-flexbox/
You can also try this this will make your last item to stick to bottom of your parent container
.flex-container{
position:relative;
}
.flex-item-bottom{
position:absolute;
bottom:0;
}