I have a ul tag with display: flex.
I need it ordered by column with flex-direction: column;, but it does not work.
CSS for the container:
#nav li.four_columns ul.sub-menu {
width: 600px;
display: flex;
-webkit-flex-direction: column;
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
flex-flow: wrap;
}
CSS for the child:
#nav li.four_columns ul.sub-menu li {
flex-basis: 25%;
/* white-space: nowrap; */
/* overflow: hidden; */
/* text-overflow: ellipsis; */
/* border-bottom: none; */
}
Here is the source of your problem: flex-flow: wrap
This is a shorthand property for flex-direction and/or flex-wrap.
The initial values of this property are row nowrap.
You have only declared the flex-wrap component: wrap.
This means that the flex-direction component remains the default value: row.
Hence, your flex items are aligning horizontally in a row that wraps.
As a solution, either specify both components:
flex-flow: column wrap
OR, since you already have flex-direction: column in the rule, remove flex-flow and use:
flex-wrap: wrap
Also important: If you want flex items to wrap in column-direction, you need to define a height on the container. Without a fixed height, the flex items don't know where to wrap and they'll stay in a single column, expanding the container as necessary.
Reference:
5.3. Flex Direction and Wrap: the flex-flow shorthand
If flex direction column is not working, make sure you didn't forget to specify the height:
Example:
#container {
display: flex;
width: 100%;
height: 100%;
flex-direction: column;
}
.child {
width: 200px;
/* height: 200px;*/
flex: 1;
}
#child1 {
background-color: red;
flex: 2;
}
#child2 {
background-color: green;
}
#child3 {
background-color: blue;
}
<section id="container">
<div id="child1" class="child"></div>
<div id="child2" class="child"></div>
<div id="child3" class="child"></div>
</section>
Related
I'm currently doing some stuff with Flex Box and I'd like my flex box to stretch but I can't do it. Here is my codepen : https://codepen.io/chevalierv/pen/bGdBKyg
.FlexContainer {
height: 65vh;
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: stretch;
align-content: stretch;
justify-content: center;
padding: 1em;
background-color: red;
}
.SecondChildContainer {
align-self: flex-end;
order: 2;
flex: 1;
flex-basis: 100%;
background-color: green;
}
.FirstChildContainer {
order: 1;
flex-grow: 5;
align-self: stretch;
background-color: blue;
}
<div class="FlexContainer">
<div class="FirstChildContainer">
a
</div>
<div class="SecondChildContainer">
a
</div>
</div>
I have cleaned your css a little bit and made it work. See the jsfiddle below:
https://jsfiddle.net/gqptemhu/
Basically, what your flex container needs is
.FlexContainer {
height: 65vh;
display: flex;
flex-direction: column;
}
so it knows to stack the items vertically.
And you use
flex: 0 1;
flex: 1 0;
On the items inside of the flex container, to tell which item will grow, and which one will shrink. The first number corresponds to flex-grow, and the second to flex-shrink. They are both relative numbers which tell which percentage of space the items will grow/shrink to.
You can read more about flexbox and how to use it on the link below:
https://css-tricks.com/snippets/css/a-guide-to-flexbox/
align-content and justify-content seem to do nothing when I run it on Chrome and Firefox.
I'm not sure what's wrong.
#container {
display: flex;
flex-wrap: wrap;
justify-content: center;
align-content: center;
height: 90vh;
}
#header {
flex: 1 0 200px;
background-color: lightgreen;
height: 200px;
border-radius: 1rem;
}
#main {
flex: 1 0 200px;
background-color: coral;
height: 200px;
border-radius: 1rem;
}
#footer {
flex: 1 0 200px;
background-color: silver;
height: 200px;
border-radius: 1rem;
}
#media screen and (max-width: 915px) {
#container {
flex-flow: column wrap-reverse;
}
}
<div id="container">
<div id="header">Header</div>
<div id="main">Main</div>
<div id="footer">Footer</div>
</div>
They're doing exactly what you're asking them to do. What's wrong here is your flex definition.
If you want them to be 200px each, you shouldn't give it a flex-grow value of 1 which you're doing in your shorthand flex-grow: *1* 0 200px.
Instead, rewrite the flex properties as such:
#header {
flex: 0 0 200px;
...
}
Working JSFiddle
As for why align-content isn't working, you only have 1 line of items, so it has nothing to do.
align-content
This aligns a flex container's lines within when there is extra space in the cross-axis, similar to how justify-content aligns individual items within the main-axis.
Note: this property has no effect when there is only one line of flex items.
From: CSS-Tricks
I'm guessing what you want is to center vertically and horizontally, in which case you don't want align-content, you want align-items.
Try replacing align-content: center with align-items: center to get the vertical centering.
JSFiddle example of align-items
I am trying to center a red box in the middle of the page.
I have set the flex container to 100% in height, and have also set the html,body to 100%, and it still does not align center.
Can anyone please help me understand why its not working? Thanks!
html, body {
height: 100%;
}
.flex-container {
display: flex;
flex-flow: column;
justify-content: center;
height: 100%;
}
.box {
flex: 0 0 100px;
background: red;
width: 100px;
}
<div class='flex-container'>
<div class='box'></div>
</div>
You use justify-content to align flex items on the main axis.
You use align-items to align flex items on the cross axis.
Since your flex container is flex-direction: column:
the main axis is vertical, and
the cross axis is horizontal.
justify-content: center is working fine.
You just need to add align-items: center.
html, body {
height: 100%;
}
.flex-container {
display: flex;
flex-flow: column;
justify-content: center; /* centers flex items vertically, in this case */
align-items: center; /* NEW */ /* centers flex items horizontally, in this case */
height: 100%
}
.box {
flex: 0 0 100px;
background: red;
width: 100px;
}
<div class='flex-container'>
<div class='box'></div>
</div>
Here's a more detailed explanation:
In CSS Flexbox, why are there no "justify-items" and "justify-self" properties?
You need to add align-items to .flex-container
align-items: center;
See here for an example https://jsfiddle.net/x9gyheo6/1/
I have a container named #center in which I want to display canvas and a button inside it. I want the canvas object to take all the available space (respecting the button inside the container).
This is my code:
html, body {
width: 100%;
height: 100%;
}
#container {
display: flex;
height: 100%;
background-color: blue;
}
.block {
flex: 1;
}
#left {
background-color: green;
}
#center {
display: flex;
flex: 1;
flex-wrap: wrap;
align-content: flex-start;
}
#right {
background-color: orange;
}
#canvasObject {
display: block;
margin: 0 auto;
border: 1px solid;
background-color: yellow;
}
<div id="container">
<div id="left" class="block">Left</div>
<div id="center" class="block">
<canvas id="canvasObject">Your browser does not support Canvas.</canvas>
<button type="button">Click!</button>
</div>
<div id="right" class="block">Right</div>
</div>
If I do not have any button in my code, canvas occupy the full div but when I display the button, canvas does not seem to resize the desired height.
Example 1: Without button.
Example 2. With button.
How can I make that the canvas object will resize until the available height (also width but it is already doing it)?
Thanks in advance!
The problem is that you have align-content: flex-start on a row-direction flex container:
#center {
display: flex;
flex: 1;
flex-wrap: wrap;
align-content: flex-start; /* <-- source of the problem */
}
The align-content property controls the spacing between flex items in the cross-axis when there are multiple lines in the container.
When the button element is excluded, there is only one line in the flex container. In such a case, align-content has no effect (align-items would work).
But when you add the button, there are now two lines on wrap, and align-content takes over (align-items does not work).
Since align-content is set to flex-start in your code, both lines are packed to the top of the container. (For other options, try flex-end, center, space-between, space-around and stretch).
An efficient solution would be to use flex-direction: column and apply flex: 1 to the canvas.
#center {
display: flex;
flex-direction: column; /* new; stack flex items vertically */
flex: 1;
flex-wrap: wrap;
/* align-content: flex-start; <-- remove; not necessary */
}
#canvasObject {
flex: 1; /* new; consume all available free space */
/* display: block; <-- remove; not necessary */
/* margin: 0 auto; <-- remove; not necessary */
border: 1px solid;
background-color: yellow;
}
Revised Fiddle
W3C References:
8.4. Packing Flex Lines: the align-content property
8.3. Cross-axis Alignment: the align-items and align-self properties
I'm using flex box to align two items to left and right of the container, while vertically centre-aligning them. Here's a very simple example of what I'm trying to achieve.
HTML:
<div class="container">
<div class="first"></div>
<div class="second"></div>
</div>
CSS:
.container {
width:100%;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
}
.first {
background-color: yellow;
width: 200px;
height: 100px;
}
.second {
background-color: blue;
width: 200px;
height: 100px;
}
Here's the jsfiddle of the example.
This works perfectly well if the screen is wide enough to fit both internal divs on one row. However when the screen size is small (e.g. a mobile phone) and the divs wrap onto the second line, the second one also becomes aligned to the left side (i.e. flex-start). How can I force the second div to always be aligned against the right border, regardless of whether it's on the first row or wrapped onto the second one?
EDIT: In the example, I assigned fixed width to the two child elements - this is for simplicity only. In the real life application, all widths are dynamically changing based on the content read from the database at run-time. Hence, any solution that's based on fixed sizes will not work.
You can try adding some left margin to push your .second element to the right:
.second {
margin-left: auto;
}
.container {
width:100%;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
}
.first {
background-color: yellow;
width: 200px;
height: 100px;
}
.second {
background-color: blue;
width: 200px;
height: 100px;
margin-left: auto;
}
<div class="container">
<div class="first"></div>
<div class="second"></div>
</div>
Or, similarly, justify all elements to the right but push .first element to the left:
.container {
justify-content: flex-end;
}
.first {
margin-right: auto;
}
.container {
width:100%;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-end;
align-items: center;
}
.first {
background-color: yellow;
width: 200px;
height: 100px;
margin-right: auto;
}
.second {
background-color: blue;
width: 200px;
height: 100px;
}
<div class="container">
<div class="first"></div>
<div class="second"></div>
</div>
I found a solution but it is rather "hacky" in nature (see demo here, explanation later), in the sense that it requires you to explicitly know the width of the parent container which will trigger a layout change based on #media.
The reason why your code is not working is because of the confusion over how align-self works. In the flexbox model, "align" refers to alignment along the cross-axis (i.e. in a conventional sense of a "row" layout direction, that will refer to vertical alignment), while "justify" refers to alignment along the main axis (i.e. the row). To better explain my point, I hereby attach an image made by Chris Coyier from his flexbox guide:
Therefore, align-self: flex-start means telling the .first to align to the top of the container, and align-self: flex-end means telling .second to align to the bottom of the container. In this case, since you have not declared an explicit height for the parent, the parent will take on the height of its tallest child. Since both .first and .second are 100px tall, the parent will also have a computed height of 100px, therefore making no difference in the alignment (because both with be flush with the start and end of the cross axis).
A hack would be switching the flex-direction to row, with the following restrictions: You know how wide your container will be, or the explicit widths of its children. In this case the breakpoint will be at 400px, where .first and .second will intersect each other.
.container {
width:100%;
display: flex;
flex-direction: column;
flex-wrap: wrap;
justify-content: space-between;
height: 100px;
}
.first {
background-color: yellow;
width: 200px;
height: 100px;
align-self: flex-start;
}
.second {
background-color: blue;
width: 200px;
height: 100px;
align-self: flex-end;
}
#media screen and (max-width: 400px) {
.container {
height: 200px;
}
}
Then again, here is a proof-of-concept fiddle, modified from your original one: http://jsfiddle.net/teddyrised/cncozfem/2/