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;
}
Related
This question already has answers here:
When flexbox items wrap in column mode, container does not grow its width
(9 answers)
Closed last year.
I don't know what silliness I've got myself into but I'm stuck in a common flexbox issue..
Here's a pen.. https://codepen.io/webdev51/pen/zYPWwbd
What I'm trying to achieve is the parent flex div to be adapting the width when flex item go into 2nd row using flex-wrap.
Desired/expected result:
Results I get:
And here's the most important part that is driving me nuts.
If I replicate the same in flex-direction: row; , it'll be working as expected and whenever the items drop in the next row, the container will adapt the height accordingly.
after changing display: inline-flex to display: flex, add align-content: flex-start;
.spaceship-group{
display: flex;
flex-direction: column;
flex-wrap: wrap;
height: 90vh;
align-content: flex-start;
justify-content: center;
position: relative;
border:2px solid orange;
}
.spaceship {
height: 240px;
width: 290px;
position: relative;
border:1px solid blue;
}
<div class="spaceship-group">
<div class="spaceship"></div>
<div class="spaceship"></div>
<div class="spaceship"></div>
<div class="spaceship"></div>
<div class="spaceship"></div>
</div>
This question already has answers here:
Keep the middle item centered when side items have different widths
(12 answers)
Closed 5 years ago.
I know flexbox offers a great solution for centering items. But I run into an issue when I have 3 items and I'd like the center (2nd) item to be centered with respect to the window, regardless of the size of the other 2 items.
In my pen you can see the second item "Client Index" is off-center because the content on the right is larger than the content on the left. How can I force it to center itself?
.flex {
display: flex;
align-items: center;
justify-content: space-between;
}
<div class="flex">
<span style="font-size:12px;">small</span>
<span style="font-size:20px;">Client Index</span>
<span style="font-size:18px;">Lots of content that moves the center</span>
</div>
My Codepen
One way would be to set flex-grow: 1; flex-basis: 0 so the 3 columns are distributed evenly, then you can center the text or the content in the middle one.
I'm using text-align to center the middle column. You could also use display: flex; justify-content: center; to do the same thing.
.flex {
display: flex;
align-items: center;
justify-content: space-between;
}
.flex > span {
flex: 1 0 0;
}
.flex > span:nth-child(2) {
text-align: center;
}
<div class="flex">
<span style="font-size:12px;">small</span>
<span style="font-size:20px;">Client Index</span>
<span style="font-size:18px;">Lots of content that moves the center</span>
</div>
Use nested flex containers and auto margins.
.flex-container {
display: flex;
}
.flex-item {
flex: 1;
display: flex;
justify-content: center;
}
.flex-item:first-child>span {
margin-right: auto;
}
.flex-item:last-child>span {
margin-left: auto;
}
/* non-essential */
.flex-item {
align-items: center;
border: 1px solid #ccc;
background-color: lightgreen;
height: 40px;
}
<div class="flex-container">
<div class="flex-item"><span>short</span></div>
<div class="flex-item"><span>medium</span></div>
<div class="flex-item"><span>lonnnnnnnnnnnnnnnnnnnng</span></div>
</div>
Here's how it works:
The top-level div is a flex container.
Each child div is now a flex item.
Each item is given flex: 1 in order to distribute container space equally.
Now the items are consuming all space in the row and are equal width.
Make each item a (nested) flex container and add justify-content: center.
Now each span element is a centered flex item.
Use flex auto margins to shift the outer spans left and right.
You could also forgo justify-content and use auto margins exclusively.
But justify-content can work here because auto margins always have priority. From the spec:
8.1. Aligning with auto
margins
Prior to alignment via justify-content and align-self, any
positive free space is distributed to auto margins in that dimension.
I have a simple block of text sharing a display: flex container with an <a> tag.
Unfortunately, the wrapping is a bit weird, almost as if the <a> tag's "true" width isn't being treated as such, or like it has a width of 0 (judging by how it is positioned).
Is there some styling I can apply to <a> tags to make it act more "text-like"?
JSFiddle
body {
font-size: 32px;
}
body > .container {
display: flex;
flex-flow: column nowrap;
justify-content: flex-start;
align-items: center;
}
body > .container > .foot {
flex: 1 0 100%;
background-color: grey;
display: flex;
flex-flow: column nowrap;
justify-content: center;
align-items: center;
}
body > .container > .foot > .content {
flex: 1 0 70%;
width: 50%;
height: 350px;
display: flex;
flex-flow: row wrap;
justify-content: flex-start;
align-items: center;
align-content: center;
text-align: center;
}
<div class='container'>
<div class='foot'>
<div class='content'>
We'll be back up shortly. We are undergoing a scheduled maintenance. Apologies for the inconvenience. Check <a href='http://status.mywebsite.com'>http://status.mywebsite.com </a> for updates.
</div>
</div>
</div>
Answer
You have text-align: center which is applying to the text, but not the anchor element.
You have justify-content: flex-start which is applying to the anchor element, but not the text.
All you need is a switch to justify-content: center.
revised fiddle
body {
font-size: 32px;
}
body > .container {
display: flex;
flex-flow: column nowrap;
justify-content: flex-start;
align-items: center;
}
body > .container > .foot {
flex: 1 0 100%;
background-color: grey;
display: flex;
flex-flow: column nowrap;
justify-content: center;
align-items: center;
}
body > .container > .foot > .content {
flex: 1 0 70%;
width: 50%;
height: 350px;
display: flex;
flex-flow: row wrap;
justify-content: center; /* ADJUSTED */
align-items: center;
align-content: center;
text-align: center;
}
<div class='container'>
<div class='foot'>
<div class='content'>
We'll be back up shortly. We are undergoing a scheduled maintenance. Apologies for the inconvenience. Check <a href='http://status.mywebsite.com'>http://status.mywebsite.com </a> for updates.
</div>
</div>
</div>
Explanation
You wrote:
I have a simple block of text sharing a display: flex container with an <a> tag.
Well, your block of text isn't as simple as you might think.
You're not dealing with a single string.
What you actually have is a flex container with three flex items:
An anonymous flex item wrapping the text before the anchor element
The anchor element
An anonymous flex item wrapping the text after the anchor element
From the spec:
4. Flex Items
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.
The behavior you're seeing is three flex items wrapping.
The anchor text itself will not wrap because it is equivalent to a single word. But if you add spaces and text in the anchor it will wrap like everything else.
Also see this post:
Why do I need "text-align: center" when the container has "justify-content: center"?
I have an input element which I want to grow and shrink using flex shrink but its flex-basis size is not being applied.
Here is my html:
<div class="flex-container">
<div class="flex-row">
<input type="text" name="query" class="searchbar" />
</div>
<div>
and my css:
.flex-container{
display: flex;
align-items: center;
justify-content: center;
flex-direction: row;
flex-wrap: wrap;
}
.flex-row input { flex: 0 1 450px; }
why is the basis size not being applied? it is getting set to a much smaller width than 450px.
Here is a fiddle with the example.
Actually what is happening here is that your input's immediate parent .flex-row is a simple div with no css properties and also not set to be a flex container hence it's width is auto and wrapping around the input and not applying the flex properties. To apply flex properties to the input use the following css to make the input's parent display be flex.
.flex-container{
display: flex;
}
.flex-row {
display: flex;
flex:1;
align-items: center;
justify-content: center;
}
.flex-container input { flex: 0 1 450px; }
Hope this helps.
I have an input element which I want to grow and shrink using flex shrink but its flex-basis size is not being applied.
Here is my html:
<input type="text"/>
and my css:
input{
background-color: black;
display: flex;
align-items: center;
justify-content: center;
flex-direction: row;
flex-wrap: wrap;
flex: 0 1 450px;
}
why is the basis size not being applied? it is getting set to a much smaller width than 450px.
Here is a fiddle with the example.
You have applied display: flex to the <input> element instead of a div.
The ideal way is to use a container/wrapper and then make the container display: flex & then control the input using flex-basis - Here is your Fiddle updated
HTML
<div class="container">
<input type="text"/>
</div>
CSS
.container{
display: flex;
align-items: center;
justify-content: center;
flex-direction: row;
flex-wrap: wrap;
}
.container input { flex: 0 1 450px; }
You need to establish a flex formatting context.
This is the same as establishing a block formatting context, except
that flex layout is used instead of block layout.
For properties like flex-basis, flex-grow, flex-shrink to work, an element must participate in the flex formatting context.
A flex item establishes a new formatting context for its contents. The
type of this formatting context is determined by its display value, as
usual. However, flex items themselves are flex-level boxes, not
block-level boxes: they participate in their container’s flex
formatting context, not in a block formatting context.
var el = document.querySelector("input");
console.log("input width: " + el.offsetWidth + "px");
.flex-container { /* Flex formatting context, this makes the element a flex container */
display: flex;
}
input { /* Direct children of flex containers are now flex items */
background-color: black;
flex: 0 1 450px;
box-sizing: border-box;
}
<section class="flex-container">
<input type="text" />
</section>
Revised jsFiddle
Source: W3C CSS Flexible Box Layout Module Level 1
/* Latest compiled and minified CSS included as External Resource*/
/* Optional theme */
#import url('//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap-theme.min.css');
body {
margin: 10px;
display:flex;
}
input{
background-color: black;
align-items: center;
justify-content: center;
flex-direction: row;
flex-wrap: wrap;
flex: 0 1 450px;
}
<input type="text"/>
check this
Apply flex properties to a input container rather than to the input.
Have a look at the snippet below:
.input-holder {
display: flex;
align-items: center;
justify-content: center;
flex-direction: row;
flex-wrap: wrap;
}
.input-holder input {
flex: 0 1 450px;
background: #000;
}
<div class="input-holder">
<input type="text"/>
</div>
Hope this helps!