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.
Related
I'm having a bit of trouble to produce the below with flex box. I'd like a centrally aligned "title" with some buttons to the right (2,3,4).
The code below gets me close, but it's not perfectly aligned and loses it when the window resizes.
Any suggestions?
.header {
display: flex;
height: 50px;
align-items: center;
justify-content: center;
}
.title {
width: 250px;
margin-left: auto;
margin-right: 15%;
}
.btn-group {
margin-right: 15%;
}
<div class="header">
<h1 class="title"></h1>
<div class="btn-group">
<button id="btn_1" class="selected">2</button>
<button id="btn_2">3</button>
<button id="btn_3">4</button>
</div>
</div>
Here's a clean and simple process to get you to your layout:
First, note that CSS pseudo-elements (i.e., ::before and ::after), when applied to flex containers, are treated as flex items.
Create a pseudo-element to serve as the first flex item in the container.
Make the pseudo consume all available space (i.e., set it to flex: 1)
Do the same with your button group (.btn-group) on the opposite end (i.e., set it to flex: 1)
Now, with the outer items pressuring from both sides, the title is pinned to the middle of the container.
Make the button group container a flex container.
Set that container to justify-content: center.
Now, the individual buttons are horizontally centered on the right side of the already centered title.
.header {
display: flex;
height: 50px;
align-items: center;
}
.header::before {
content: "";
flex: 1;
}
.btn-group {
flex: 1;
display: flex;
justify-content: center;
}
<div class="header">
<h1 class="title">1</h1>
<div class="btn-group">
<button id="btn_1" class="selected">2</button>
<button id="btn_2">3</button>
<button id="btn_3">4</button>
</div>
</div>
To better understand the concepts and methodology at work here, see this post:
Center and right align flexbox elements
Here are my suggestions when using flexbox layout. You do not need to set the width on the element because the width will resize dynamically. When you set display as flex in the container, the x-axis would change to row by default then use flex property for 'title' class to expand the width to double the width of 'btn-group'. As the result, the second div will push all the way to the right and you can add the width of margin-right as how much you want it to be. Also, I would create another div after header and give it a class name as 'title' instead of giving it on h1. That way you would have two children that allow you to control it. See below how I fixed it:
h1 {
text-align: center;
}
.header {
border: 1px solid red;
display: flex;
align-items: center;
justify-content: center;
}
.title {
flex: 1;
}
<div class="header">
<div class="title">
<h1>This is a title</h1>
</div>
<div class="btn-group">
<button id="btn_1" class="selected">2</button>
<button id="btn_2">3</button>
<button id="btn_3">4</button>
</div>
</div>
This question already has answers here:
Fill the remaining height or width in a flex container
(2 answers)
How to align flexbox columns left and right?
(5 answers)
Why is a flex item limited to parent size?
(1 answer)
Closed 3 years ago.
I have a header where on the left side there is header name and on the right side, there are a few buttons.
And the problem is, header name splits into two lines at last white space.
I have below code and it's happening because of .right class's width set to inherit.
pls refer the code.
Is there any way for not letting the text to split?
.parent {
width: 100%;
height: auto;
display: flex;
padding: 0.5rem 1rem;
}
.right {
text-align: right;
width: inherit;
}
<div class="parent">
<!---->
<h6>A B C D E</h6>
<div class="right">
buttons
</div>
</div>
JSFiddle
You can simplify the code by assigning flex-grow: 1 to the h6 (the header name). This will have ensure the text grows to fill the most available space in the row. The remaining space will be implicitly given to .right (buttons).
/* default styles */
.parent {
display: flex;
align-items: center;
padding: 0.5rem 1rem;
}
.parent h6 {
flex-grow: 1;
}
<div class="parent">
<h6>A B C D E</h6>
<div class="right">
buttons
</div>
</div>
jsFiddle
You could use justify-content: space-between to evenly distribute your two items within the parent container like so:
.parent {
width: 100%;
height: auto;
display: flex;
justify-content: space-between;
align-items: center;
}
<div class="parent">
<h6>A B C D E</h6>
<div class="right">
buttons
</div>
</div>
remove width: inherit from right class and add margin-left:auto to align it to the right
You can use flex-shrink property to achieve what you wanted. I have remove width:inherit and used flex-grow property. I assume that would be better in this case.
flex-grow defines the ability for a flex item to grow if necessary. It accepts a unitless value that serves as a proportion. It dictates what amount of the available space inside the flex container the item should take up.
If all items have flex-grow set to 1, the remaining space in the container will be distributed equally to all children. If one of the children has a value of 2, the remaining space would take up twice as much space as the others (or it will try to, at least).
.parent {
box-sizing: border-box;
width: 100%;
height: auto;
display: flex;
flex-wrap: wrap;
padding: 0.5rem 1rem;
}
.right {
text-align: right;
flex-shrink: 0;
flex-grow: 1;
}
h6 {
flex-shrink: 0;
}
<div class="parent">
<!---->
<h6>A B C D E</h6>
<div class="right">
buttons
</div>
</div>
This question already has answers here:
In CSS Flexbox, why are there no "justify-items" and "justify-self" properties?
(6 answers)
Closed 3 years ago.
Im trying to put some text and some button into a row, and i want the buttons to be on the Right side and the Text to be on the left side.
Basically im creating a flexbox and then i give some items the right class and some the left.
html, body { width: 100%; }
.flexbox {
flex-direction: row;
width: 100%;
display: flex;
align-items: center;
}
.right {
align-self: flex-end;
}
.left {
align-self: flex-start;
}
<div class="flexbox" *ngFor="let a of api.active_articles">
<a class="left">{{a.nameDe}}/{{a.nameIt}}</a>
<a class="left">{{a.descriptionDe}}/{{a.descriptionIt}}</a>
<button class="right" id="edit">Edit</button>
<button class="right" id="delete">Delete</button>
</div>
Basically i thought with flex-direction: row; the stat would be left and the end would be right, but apparently not, since it puts left on the top of the div and right on the bottom, both horizontally aligned like i didnt even do anything.
align-self works on the cross-axis so in a row it's a vertical alignment.
The align-self CSS property overrides a grid or flex item's align-items value. In Grid, it aligns the item inside the grid area. In Flexbox, it aligns the item on the cross axis.
It's possible you meant justify-self but this does not have any effect in a flex row.
In flexbox layouts, this property is ignored.
If you need the buttons on the right side, you can employ the margin-left:auto option.
html, body { width: 100%; }
.flexbox {
flex-direction: row;
width: 100%;
display: flex;
align-items: center;
}
#edit {
margin-left:auto;
}
<div class="flexbox" *ngFor="let a of api.active_articles">
<a class="left">Name</a>
<a class="left">Description</a>
<button class="right" id="edit">Edit</button>
<button class="right" id="delete">Delete</button>
</div>
I'd like to left align two items, and right align one when there is sufficient space but center on wrap.
On first wrap (too thin for right item to fit)
Right item should go to next line and be centered
Remainder remains left aligned
On Second Wrap (too thin for right + mid item to fit)
All three items are vertically stacked and centered
Tried having two layers of flex using justify-content: first with space-between, second with center.
.container {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
}
.subcontainer {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.item {
border: 1px solid black;
height: 100px;
}
<div class="container">
<div class="subcontainer">
<div class="item">abc abc abc abc abc abc</div>
<div class="item">def def def def def def</div>
</div>
<div class="item">right right right</div>
</div>
http://jsfiddle.net/b3z18rLn/9/
Unfortunately, the right item does not center upon wrapping, and remains left aligned.
JSFiddle
You can wrap your third item inside another Flexbox container and use media queries:
/* flex-wrap will put right-subcontainer on a new row when you
decrease the viewport's width.*/
.container {
display: flex;
flex-wrap: wrap;
}
/* flex-grow of 1 will enable this container to take up the
entire row when the left and right subcontainers are
row by row.
flex-wrap is used to allow the second item to go onto a
new row at smaller widths. */
.left-subcontainer {
display: flex;
flex-grow: 1;
flex-wrap: wrap;
}
/* Again, flex-wrap is used to give the right subcontainer
the ability to take up the entire row.
flex-end changes the items from positioning left-to-right
to right-to-left.*/
.right-subcontainer {
display: flex;
flex-grow: 1;
justify-content: flex-end;
}
.item {
border: 1px solid black;
width: 300px;
height: 300px;
}
/* You will need to adjust the arguments for these media queries.
Also, if you do decide to use media queries for this approach,
I would suggest reversing the CSS logic by having the CSS
selectors tackle mobile design first and use media queries
to tackle design at larger screen sizes. */
/* The first wrap/breakpoint is at this width. I am telling the
right container to be center-aligned at the first breakpoint. */
#media only screen and (max-width: 925px) {
.right-subcontainer {
justify-content: center;
}
}
/* Then, I tell the left container to be center-aligned at the second
breakpoint. */
#media only screen and (max-width: 1320px) {
.left-subcontainer {
justify-content: center;
}
}
<div class="container">
<div class="left-subcontainer">
<div class="item">abc abc abc abc abc abc</div>
<div class="item">def def def def def def</div>
</div>
<div class="right-subcontainer">
<div class="item">right right right</div>
</div>
</div>
This question already has answers here:
Make container shrink-to-fit child elements as they wrap
(4 answers)
CSS when inline-block elements line-break, parent wrapper does not fit new width
(2 answers)
Closed 3 years ago.
A simplified plunkr to show the problem:
https://plnkr.co/edit/mHTHLEumQ04tInFVAz3z?p=preview
If you resize the right viewport until the two containers no longer fit on the same row, right one moves to a new line.
However the parent inline-flex container width does not change, throwing the top "header" element off - the "button" in "header" should be right aligned with the last item in the container below.
The two (or more) items have fixed width but no space between them. Those are the only elements with fixed width or height.
How can I force the flex container width to fit/shrink when items wrap to a new row (without using js, pure HTML/CSS)?
.main-flex {
display: -webkit-inline-flex;
display: inline-flex;
-webkit-flex-direction: column;
flex-direction: column;
}
.flex-container {
flex-grow: 1;
display: -webkit-inline-flex;
display: inline-flex;
-webkit-flex-direction: row;
flex-direction: row;
flex-wrap: wrap;
}
<div style="margin-top: 100px;" class="main-flex">
<div>
<span>header</span>
<span style="float:right">button</span>
</div>
<div class="flex-container">
<div style="height: 400px; width:250px; border: 1px solid black;"></div>
<div style="height: 400px; width:250px; border: 1px solid black;"></div>
</div>
</div>
In CSS, the parent container doesn't know when its children wrap. Hence, it continues scaling its size oblivious to what's going on inside.
Put another way, the browser renders the container on the initial cascade. It doesn't reflow the document when a child wraps.
That's why the container doesn't shrink-wrap the narrower layout. It just continues on as if nothing wrapped, as evidenced by the reserved space on the right.
More details here: Make container shrink-to-fit child elements as they wrap
But you don't need the container to shrink for your layout to work. It can be built with a few adjustments to your HTML and CSS.
.main-flex {
display: inline-flex;
flex-wrap: wrap;
}
.flex-container {
display: flex;
flex-direction: column;
}
.flex-container>div {
height: 400px;
width: 250px;
border: 1px solid black;
}
.flex-container:nth-child(2)>span {
align-self: flex-end;
}
<div class="main-flex">
<div class="flex-container">
<span>header</span>
<div></div>
</div>
<div class="flex-container">
<span>button</span>
<div></div>
</div>
</div>
revised demo