This is how it looks now.
I want the välj div to be centered below the other ones.
I am using flexbox.
What I have done now is to wrap all the divs in a container, and then add:
display: flex;
align-items: center;
justify-content: center;
to the container
the row of divs also have a container around it. With the value:
display: flex;
flex-flow: row;
justify-content: center;
align-content: center;
align-items: center;
The last "button" div (välj), has the value align-self: center;.
Am I missing something, or should now it be centered by now?
The align-* properties in Flexbox (align-items/content/self) defines how the browser distributes space between and around flex items along the cross-axis of their container.
So in your case, where the container has row direction, the align-self: center will center the button vertically, though if its parent doesn't have a height higher than the flex item, one won't visually see it.
Based on you say there is one row div around the price items and one around the button, you have two main options to center the button:
Change the container to column direction and the align-self: center will center the button horizontally.
Replace align-self: center with margin: auto
The below works with a flexbox for the row only.
.item {
width: 20%;
height: 50px;
background: blue;
border: thin solid red;
}
.row {
display: flex;
justify-content: center;
align-items: center;
}
.row:not(:last-child) {
margin-bottom: 1em;
}
.container {
width: 100%;
}
<div class="container">
<div class="row">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
<div class="row">
<button>Button</button>
</div>
</div>
While #Gerard's answer does work. It did not for me, on my site. Since I have a bunch of inherited css from code writen years ago. This, however, did work.
.sub-slider {
width: 100%;
display: flex;
flex-flow: column;
}
.slider {
display: flex;
flex-flow: row;
justify-content: center;
align-content: center;
align-items: center;
}
.sub-slider-btn-wrp {
align-self: center;
}
.item {
width: 20%;
height: 50px;
background: blue;
border: thin solid red;
}
<div class="sub-slider">
<div class="slider">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
<div class="sub-slider-btn-wrp">
<button>Button</button>
</div>
</div>
Related
I'm making an observation more so than stating a problem, if only to help anyone who's also noticed. I'm following a tutorial on flexbox when I accidently comment out display: flex on body{}. The container expands from 120px (flex-direction: column) wide to 100% of the viewport, horizontally. Display: grid also expands to 100% of the horizontal viewport. This observation is enough for me to post the question because I struggle working with flexbox and I end up applying padding and margin manually. I wonder if anyone else has any observations that are not explicitly stated in flexbox documentation.
<div class="flex-container">
<div class="item">item 1</div>
<div class="item">item 2</div>
<div class="item">item 3</div>
</div>
.flex-container {
display: flex;
flex-direction: column;
align-items: center;
}
.item {
background-color: blue;
color: white;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100px;
width: 100px;
margin: 10px;
}
Why does display: flex shrink the container?
When an element has display: flex applied—making it a flex container—certain default settings come into play. Two of these settings are flex-direction: row on the container and flex-basis: auto on the items.
With display: flex on the body element, the flex item (.flex-container) is automatically set to flex-basis: auto, which is the width of the content. That's why the nested container "shrinks".
When display: flex is removed, the body element reverts back to display: block. Its child (.flex-container) is no longer a flex item and takes the default width: 100% of block elements.
If you want a flex item to expand to 100% width, just give it flex-grow: 1 or flex: 1.
body {
display: flex;
}
.flex-container {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
border: 1px solid red;
}
.item {
background-color: blue;
color: white;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100px;
width: 100px;
margin: 10px;
}
<div class="flex-container">
<div class="item">item 1</div>
<div class="item">item 2</div>
<div class="item">item 3</div>
</div>
In the CSS flexible box layout module, it says:
the collapsed flex item is removed from rendering entirely, but leaves behind a "strut"
Does that behave just like visibility: hidden? If the answer is yes, then why was visibility: collapse introduced?
Note on browser support: As of July 2017, Chrome (59) does not support visibility: collapse. The code samples below with collapse work in Firefox and Edge, but fail in Chrome (they behave just like hidden). UPDATE: As of July 2020, this is note is still valid. Chrome and Safari treat visibility: collapse like hidden. caniuse.com
Flex items are laid out in a row or column, depending on flex-direction.
Each row / column is considered a flex line.
In the examples below, a flex container has four flex items in row-direction. The fourth item wraps, creating a second flex line:
.container {
display: flex;
flex-wrap: wrap;
width: 200px;
border: 1px dashed black;
}
.box {
height: 50px;
flex: 0 0 50px;
margin: 5px;
background-color: lightgreen;
display: flex;
justify-content: center;
align-items: center;
}
<div class="container">
<div class="box box1">1</div>
<div class="box box2">2</div>
<div class="box box3">3</div>
<div class="box box4">4</div>
</div>
display: none
With display: none, a flex item isn't rendered by the browser.
If all items on the flex line have display: none, the line also collapses, which affects the rest of the layout. Surrounding elements may shift when a flex line collapses.
With display: none applied to the third item, the fourth item takes its place on the upper line, and the lower line collapses:
.container {
display: flex;
flex-wrap: wrap;
width: 200px;
border: 1px dashed black;
}
.box {
height: 50px;
flex: 0 0 50px;
margin: 5px;
background-color: lightgreen;
display: flex;
justify-content: center;
align-items: center;
}
.box3 { display: none; }
<code>display: none</code>
<div class="container">
<div class="box box1">1</div>
<div class="box box2">2</div>
<div class="box box3">3</div>
<div class="box box4">4</div>
</div>
visibility: hidden
With visibility: hidden, a flex item is rendered by the browser but is fully transparent. It's hidden from view but takes up the space it would normally use in the layout. Hence, surrounding elements see this item as fully intact.
In this example, when the last two boxes have visibility: hidden, the rest of the layout (including the second flex line) remains unchanged.
.container {
display: flex;
flex-wrap: wrap;
width: 200px;
border: 1px dashed black;
}
.box {
height: 50px;
flex: 0 0 50px;
margin: 5px;
background-color: lightgreen;
display: flex;
justify-content: center;
align-items: center;
}
.box3 { visibility: hidden; }
.box4 { visibility: hidden; }
<code>visibility: hidden</code>
<div class="container">
<div class="box box1">1</div>
<div class="box box2">2</div>
<div class="box box3">3</div>
<div class="box box4">4</div>
</div>
visibility: collapse
With visibility: collapse, a flex item is not rendered (same as display: none), but the flex algorithm checks the cross size of the item and then uses that data to keep the flex line stable (i.e., what the cross size of the line would be if the flex item was visible).
The difference with display: none is that collapse allows one piece of the item – its cross size – to be preserved. This is referred to in the spec as the strut.
So if all flex items on the line have visibility: collapse, the cross size of the line (whether it be the width or height) does not collapse, and the rest of the layout isn't affected.
Note that although collapse guarantees the stability of the line's cross size, it provides no such assurance for the line's main size. This is a key difference between collapse and hidden.
Below are some examples. (As mentioned above, these won't work in Chrome. Test in FF or Edge.)
In this example, the first two items have visibility: collapse.
.container {
display: flex;
flex-wrap: wrap;
width: 200px;
border: 1px dashed black;
}
.box {
height: 50px;
flex: 0 0 50px;
margin: 5px;
background-color: lightgreen;
display: flex;
justify-content: center;
align-items: center;
}
.box1, .box2 {
visibility: collapse;
}
<code>visibility: collapse</code>
<div class="container">
<div class="box box1">1</div>
<div class="box box2">2</div>
<div class="box box3">3</div>
<div class="box box4">4</div>
</div>
The layout renders like display: none. The second line collapses because the main size of the items is gone, allowing the last item to move up naturally.
In the following example, all items get visibility: collapse. Hence, the second line collapses because the items' main size is gone, but the cross size of the first line remains.
.container {
display: flex;
flex-wrap: wrap;
width: 200px;
border: 1px dashed black;
}
.box {
height: 50px;
flex: 0 0 50px;
margin: 5px;
background-color: lightgreen;
display: flex;
justify-content: center;
align-items: center;
}
.box {
visibility: collapse;
}
<code>visibility: collapse</code>
<div class="container">
<div class="box box1">1</div>
<div class="box box2">2</div>
<div class="box box3">3</div>
<div class="box box4">4</div>
</div>
jsFiddle
It actually depends on the element. If used on a table sub-element, collapse will hide the element as well as the space it occupied.
collapse will behave like hidden if used on any element that is not a table sub-element
How can I fix the meta class to the bottom left corner of the flex container while keeping the heading element h1 vertically centered?
.container {
height: 200px;
background: red;
display: flex;
align-items: center;
}
<div class="container">
<h1>Hello, world!</h1>
<div class="meta">intro</div>
</div>
Take it out of flow and position it relatively to the container.
.container {
height: 200px;
background: red;
display: flex;
align-items: center;
position: relative;
}
.meta {
position: absolute;
bottom: 0;
left: 0;
}
<div class="container">
<h1>Hello, world!</h1>
<div class="meta">intro</div>
</div>
Switch to flex-direction: column
Apply justify-content: space-between
Insert an invisible "spacer" item to balance out both ends
.container {
height: 200px;
background: red;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.invisible { visibility: hidden; }
<div class="container">
<div class="invisible">intro</div>
<h1>Hello, world!</h1>
<div class="meta">intro</div>
</div>
Note that flex alignment properties work by distributing available space in the container. This means that justify-content: space-between can precisely center the middle item (h1) only if both adjacent items are equal height. For more details see Box #71 here.
It seems that Chrome doesn't handle justify-content: space-around correctly when the content overflows the flex container, and the container is not set up to allow wrapping, but instead horizontal scrolling.
Some of the content overflows on the left side of the flex container, and is cut off. I want it to overflow on the right side, so that I can reach it by scrolling horizontally.
Here is an example:
#container {
display: flex;
width: 500px;
justify-content: space-around;
border: solid black;
overflow: auto;
}
.item {
min-width: 200px;
margin: 10px;
background-color: red;
display: table;
font-size: 48pt;
text-align: center;
}
<div id="container">
<div class="item">1</div><div class="item">2</div>
<div class="item">3</div><div class="item">4</div>
<div class="item">5</div><div class="item">6</div>
</div>
That's because when there isn't enough space, space-around behaves like center:
If the leftover free-space is negative or there is only a single flex
item on the line, this value is identical to center.
And center behaves like you describe:
If the leftover free-space is negative, the flex items will overflow
equally in both directions.
Instead, you can use space-between:
If the leftover free-space is negative or there is only a single flex
item on the line, this value is identical to flex-start.
Of course, then you won't have half-size spaces on neither end of the flex line. You can insert pseudo-element to have full-size spaces, though.
#container {
display: flex;
justify-content: space-between; /* Instead of space-around */
}
#container::before, #container::after {
content: ''; /* Insert space before the first item and after the last one */
}
.container {
display: flex;
width: 500px;
border: solid black;
justify-content: space-between;
overflow: auto;
margin: 10px 0;
}
.container::before, .container::after {
content: '';
}
.item {
margin: 10px;
background-color: red;
display: table;
font-size: 48pt;
text-align: center;
}
.big > .item {
min-width: 200px;
}
<div class="container big">
<div class="item">1</div><div class="item">2</div>
<div class="item">3</div><div class="item">4</div>
<div class="item">5</div><div class="item">6</div>
</div>
<div class="container">
<div class="item">1</div><div class="item">2</div>
<div class="item">3</div><div class="item">4</div>
<div class="item">5</div><div class="item">6</div>
</div>
Since the container is limited in width and you want overflowing flex items to be accessed via horizontal scrolling, why use justify-content: space-around?
Try justify-content: flex-start:
Revised Codepen
To understand why overflowing flex items may be inaccessible via scroll, see this answer.
If you're interested in a Javascript workaround for the original code, see this post:
When centering horizontally, li's get cut off
What would be the best way, given any number of elements in a container, to align some elements to the left and some to the right while centering both left and right content vertically?
For example, given this markup:
<div class="action">
<div class="message">This is our message</div>
<div class="comment">Comments for the message</div>
<div class="person">John Doe</div>
<div class="date">01/18/2013</div>
<div class="time">12:35 PM</div>
</div>
Can the message and comment be left aligned in the action container while the person, date and time are right aligned with both left and right content vertically centered? Can this be done without new markup and with any content length for each element?
Thanks.
Some CSS would do the trick. Have the containing div position: relative, and float the children div's either left or right. Also center-align the text.
.container{
position: relative;
}
.left{
float: left;
width: 50%;
background-color: Silver;
text-align: center;
}
.right{
float: right;
width: 50%;
background-color: Yellow;
text-align: center;
}
Fiddle Example
With a minimal change to existing markup (introduction of two div tags, one for each column), this becomes rather trivial if you use Munawwar's flex-helper.
HTML:
<div class="hbox flex">
<div class="left vbox main-center">
<div class="message">
<p>This is our message.</p>
<p>It spans many lines.</p>
<p>Or rather, paragraphs.</p>
<p>Additional waffle.</p>
<p>Syrup, bacon, a banana.</p>
<p>Tall glass of milk.</p>
</div>
<div class="comment">Comments for the message.</div>
</div>
<div class="right vbox main-center">
<div class="person">John Doe</div>
<div class="date">01/18/2013</div>
<div class="time">12:35 PM</div>
</div>
</div>
CSS:
/*Example-specific CSS*/
/*left column*/
.left {
width: 80%;
background-color: Silver;
text-align: center;
}
/*right column*/
.right {
width: 20%;
background-color: Yellow;
text-align: center;
}
/*Minimal use of Munawwar's flex-helper*/
/* https://github.com/Munawwar/flex-helper */
/*Stack child items vertically*/
.vbox {
display: flex;
/*Align children vetically*/
flex-direction: column;
align-content: flex-start;
/*Prevent extending beyond boundaries*/
overflow: hidden;
}
/*Stack child items horizontally*/
.hbox {
display: flex;
/*Align children horizontally*/
flex-direction: row;
align-content: flex-start;
/*Wrap items to next line on main-axis*/
flex-wrap: wrap;
/*Prevent extending beyond boundaries*/
overflow: hidden;
}
/*Stretch item along parent's main-axis*/
.flex {
flex: 1;
}
/*Stack child items to the main-axis center*/
.main-center {
justify-content: center;
}
JSFiddle demo
No waffles were harmed in the production of this answer, though some may have been eaten.