Can't center a fixed-positioned flexbox with margin: 0 auto - css

I have a problem centering a fixed-postioned flexbox by using margin: 0 auto;. I can change position into relative to make it look like what I want, but a fixed one is what I hope.
Please view it on JSBIN output, and if you'd like to see the code.
HTML
<header class="header l-container">
<div class="site-title"> Home</div>
<nav class="nav-box">
<ul class="menu-box">
<li>About</li>
<li>Blog</li>
<li>Contact</li>
</ul>
</nav>
</header>
CSS
/* change position into relative or fixed */
.header {
position: fixed;
z-index: 100;
}
/* some other settings below */
.l-container {
margin: 0 auto;
padding: 0 6rem;
max-width: 108rem;
}
.header,
.menu-box {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
.header {
-webkit-box-pack: justify;
-webkit-justify-content: space-between;
-ms-flex-pack: justify;
justify-content: space-between;
}
.site-title .link {
float: left;
}
.menu-box .link {
float: right;
}
ul {list-style: none;}
li {margin-left: 20px;}
.link {font-size: 20px;}
Note: I'd like to center the whole .header container and use flexbox to make the .site-title and .nav-box separated apart in both ends of .header.

How about adding left: 0 and right: 0 to your fixed .header? The max-width, margin and padding will still be applied, but it will be positioned from the left and right.
JSBin
.header {
position: fixed;
z-index: 100;
left: 0;
right: 0;
}

It will work
.header {
position: fixed;
z-index: 100;
left:0;
top:0;
}

Related

Flex while filling the first space with nothing [duplicate]

I would like to have A B and C aligned in the middle.
How can I get D to go completely to the right?
BEFORE:
AFTER:
ul {
padding: 0;
margin: 0;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
li {
display: flex;
margin: 1px;
padding: 5px;
background: #aaa;
}
li:last-child {
background: #ddd;
/* magic to throw to the right*/
}
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
https://jsfiddle.net/z44p7bsx/
Below are five options for achieving this layout:
CSS Positioning
Flexbox with Invisible DOM Element
Flexbox with Invisible Pseudo-Element
Flexbox with flex: 1
CSS Grid Layout
Method #1: CSS Positioning Properties
Apply position: relative to the flex container.
Apply position: absolute to item D.
Now this item is absolutely positioned within the flex container.
More specifically, item D is removed from the document flow but stays within the bounds of the nearest positioned ancestor.
Use the CSS offset properties top and right to move this element into position.
li:last-child {
position: absolute;
top: 0;
right: 0;
background: #ddd;
}
ul {
position: relative;
padding: 0;
margin: 0;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
li {
display: flex;
margin: 1px;
padding: 5px;
background: #aaa;
}
p {
text-align: center;
margin-top: 0;
}
span {
background-color: aqua;
}
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>true center</span></p>
One caveat to this method is that some browsers may not completely remove an absolutely-positioned flex item from the normal flow. This changes the alignment in a non-standard, unexpected way. More details: Absolutely positioned flex item is not removed from the normal flow in IE11
Method #2: Flex Auto Margins & Invisible Flex Item (DOM element)
With a combination of auto margins and a new, invisible flex item the layout can be achieved.
The new flex item is identical to item D and is placed at the opposite end (the left edge).
More specifically, because flex alignment is based on the distribution of free space, the new item is a necessary counterbalance to keep the three middle boxes horizontally centered. The new item must be the same width as the existing D item, or the middle boxes won't be precisely centered.
The new item is removed from view with visibility: hidden.
In short:
Create a duplicate of the D element.
Place it at the beginning of the list.
Use flex auto margins to keep A, B and C centered, with both D elements creating equal balance from both ends.
Apply visibility: hidden to the duplicate D
li:first-child {
margin-right: auto;
visibility: hidden;
}
li:last-child {
margin-left: auto;
background: #ddd;
}
ul {
padding: 0;
margin: 0;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
li {
display: flex;
margin: 1px;
padding: 5px;
background: #aaa;
}
p { text-align: center; margin-top: 0; }
span { background-color: aqua; }
<ul>
<li>D</li><!-- new; invisible spacer item -->
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>true center</span></p>
Method #3: Flex Auto Margins & Invisible Flex Item (pseudo-element)
This method is similar to #2, except it's cleaner semantically and the width of D must be known.
Create a pseudo-element with the same width as D.
Place it at the start of the container with ::before.
Use flex auto margins to keep A, B and C perfectly centered, with the pseudo and D elements creating equal balance from both ends.
ul::before {
content:"D";
margin: 1px auto 1px 1px;
visibility: hidden;
padding: 5px;
background: #ddd;
}
li:last-child {
margin-left: auto;
background: #ddd;
}
ul {
padding: 0;
margin: 0;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
li {
display: flex;
margin: 1px;
padding: 5px;
background: #aaa;
}
p { text-align: center; margin-top: 0; }
span { background-color: aqua; }
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>true center</span></p>
Method #4: Add flex: 1 to left and right items
Starting with Method #2 or #3 above, instead of worrying about equal width for the left and right items to maintain equal balance, just give each one flex: 1. This will force them both to consume available space, thus centering the middle item.
You can then add display: flex to individual items in order to align their content.
NOTE about using this method with min-height: Currently in Chrome, Firefox, Edge and possibly other browsers, the shorthand rule flex: 1 breaks down to this:
flex-grow: 1
flex-shrink: 1
flex-basis: 0%
That percentage unit (%) on flex-basis causes this method to break when min-height is used on the container. This is because, as a general rule, percentage heights on the children require an explicit height property setting on the parent.
This is an old CSS rule dating back to 1998 (CSS Level 2) which is still in effect in many browsers to some degree or another. For complete details see here and here.
Here's an illustration of the problem posted in the comments by user2651804:
#flex-container {
display: flex;
flex-direction: column;
background: teal;
width: 150px;
min-height: 80vh;
justify-content: space-between;
}
#flex-container>div {
background: orange;
margin: 5px;
}
#flex-container>div:first-child {
flex: 1;
}
#flex-container::after {
content: "";
flex: 1;
}
<div id="flex-container">
<div>very long annoying text that will add on top of the height of its parent</div>
<div>center</div>
</div>
The solution is to not use the percentage unit. Try px or just nothing at all (which is what the spec actually recommends, despite the fact that at least some of the major browsers have appended a percentage unit for whatever reason).
#flex-container {
display: flex;
flex-direction: column;
background: teal;
width: 150px;
min-height: 80vh;
justify-content: space-between;
}
#flex-container > div {
background: orange;
margin: 5px;
}
/* OVERRIDE THE BROWSER SETTING IN THE FLEX PROPERTY */
#flex-container > div:first-child {
flex: 1;
flex-basis: 0;
}
#flex-container::after {
content: "";
flex: 1;
flex-basis: 0;
}
/* OR... JUST SET THE LONG-HAND PROPERTIES INDIVIDUALLY
#flex-container > div:first-child {
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0;
}
#flex-container::after {
content: "";
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0;
}
*/
<div id="flex-container">
<div>very long annoying text that will add on top of the height of its parent</div>
<div>center</div>
</div>
Method #5: CSS Grid Layout
This may be the cleanest and most efficient method. There is no need for absolute positioning, fake elements or other hackery.
Simply create a grid with multiple columns. Then position your items in the middle and end columns. Basically, just leave the first column empty.
ul {
display: grid;
grid-template-columns: 1fr repeat(3, auto) 1fr;
grid-column-gap: 5px;
justify-items: center;
}
li:nth-child(1) { grid-column-start: 2; }
li:nth-child(4) { margin-left: auto; }
/* for demo only */
ul { padding: 0; margin: 0; list-style: none; }
li { padding: 5px; background: #aaa; }
p { text-align: center; }
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>| true center |</span></p>
The simplest solution will be to justify-content center to the parent container and giving margin-left auto to first and last child element.
ul {
display:flex;
justify-content:center;
}
.a,.d {
margin-left:auto;
}
<ul>
<li class="a">A</li>
<li>B</li>
<li>C</li>
<li class="d">D</li>
</ul>
Most easy way
.box{
display:flex;
justify-content:center;
}
.item1{
flex:1;
display: flex;
justify-content: center;
transform: translateX(10px);/*D element Width[if needed]*/
}
<div class="box">
<div class="item1">
<div>A</div>
<div>B</div>
<div>C</div>
</div>
<div class="item2">D</div>
</div>
Using the display:grid approach, you can simply put all of the ul children into the same cell and then set justify-self:
.ul {
display: grid;
}
.ul > * {
grid-column-start: 1;
grid-row-start: 1;
justify-self:center;
}
.ul > *:last-child {
justify-self: right;
}
/* Make Fancy */
.li {
display:inline-block;
margin: 1px;
padding: 5px;
background: #bbb;
}
<div class='ul'>
<span>
<span class='li'>A</span>
<span class='li'>B</span>
<span class='li'>C</span>
</span>
<span class='li'>D</span>
</div>
Inspired by the Method #5: CSS Grid Layout of #Michal Benjamin's solution and because I'm using Tailwind and as of now still don't have access to all the grid options by default. This seems to work:
ul {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
}
li {
align-self: center;
}
li:nth-child(1) {
justify-content: flex-start; /* OR margin-right: auto */
}
li:nth-child(3) {
justify-content: flex-end; /* OR margin-left:auto */
}
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
</ul>
PS: Not sure if mixing up flex and grid like this is a good idea!
If you want to make it aligned, you can simply attach an empty span and split the three child spans into them.
The easiest way:
.wrap {
display:flex;
}
.full-width {
width: 100%;
}
.centered {
display: flex;
justify-content:center;
}
.btn {
display: flex;
justify-content: end;
}
<div class="wrap">
<div class="full-width"></div>
<div class="full-width centered">
<div>A</div>
<div>B</div>
<div>C</div>
</div>
<div class="full-width btn">D</div>
</div>
Very clear question. I couldn't help but post the answer after a few hours of digging. We Could of solved this with tables, table-cell, absolute positions, transforms but we just had to do it with flexbox :)
.parent {
display: flex;
justify-content: flex-end;
}
.center {
margin: auto;
}
http://codepen.io/rgfx/pen/BLorgd
The accepted answer can be changed a bit because you can use grid template areas and do it without fake element
grid-template-areas '. b c'
grid-template-columns: 1fr 1fr 1fr
I expanded on Michael_B's answer
.center-flex__2-of-3 > :nth-child(1), .center-flex__2-of-3 > :nth-child(3) {
flex: 1;
}
.center-flex__2-of-3 > :nth-child(1) {
justify-content: flex-start;
}
.center-flex__2-of-3 > :nth-child(3) {
justify-content: flex-end;
}
.center-flex__1-of-2 > :nth-child(1) {
margin: auto;
}
.center-flex__1-of-2 > :nth-child(2) {
flex: 1;
justify-content: flex-end;
}
.center-flex__2-of-2 > :nth-child(1) {
flex: 1;
justify-content: flex-start;
}
.center-flex__2-of-2 > :nth-child(2) {
margin: auto;
}
.center-flex__1-of-2:before, .center-flex__1-of-1:before {
content: '';
flex: 1;
}
.center-flex__1-of-1:after, .center-flex__2-of-2:after {
content: '';
flex: 1;
}
[class*=center-flex] {
display: flex;
list-style: none;
margin: 0;
padding: 0;
border: 10px solid rgba(0, 0, 0, 0.1);
}
[class*=center-flex] > * {
display: flex;
}
li {
padding: 3px 5px;
}
2 of 3
<ul class="center-flex__2-of-3">
<span>
<li>Accusamus</li>
<li>Porro</li>
</span>
<span>
<li>Center</li>
<li>this</li>
</span>
<span>
<li>Accusamus</li>
<li>Porro</li>
<li>Culpa</li>
<li>Sit</li>
</span>
</ul>
<br><br>
1 of 2
<ul class="akex center-flex__1-of-2">
<span>
<li>Center</li>
<li>this</li>
</span>
<span>
<li>Accusamus</li>
<li>Porro</li>
<li>Culpa</li>
<li>Sit</li>
</span>
</ul>
<br><br>
2 of 2
<ul class="akex center-flex__2-of-2">
<span>
<li>Accusamus</li>
<li>Porro</li>
<li>Culpa</li>
<li>Sit</li>
</span>
<span>
<li>Center</li>
<li>this</li>
</span>
</ul>
<br><br>
1 of 1
<ul class="center-flex__1-of-1">
<span>
<li>Center</li>
<li>this</li>
</span>
</ul>
Here with the help of SASS as a codepen
ul {
padding: 0;
margin: 0;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
li {
display: flex;
margin: 1px;
padding: 5px;
background: #aaa;
}
li:last-child {
background: #ddd;
position:absolute;
right:10px;
}
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>

An alternative design without a scrollbar caused by padding

The code that appears below creates the following layout:
The important part is that the content, although centered on the screen when not overflowing, never overlaps the navbar and has its own scrollbar:
The problem is that this layout is achieved with the help of padding (marked by a comment in the code below), which results in the additional scrollbar on the right of the screen.
How can I design the same layout that would have only one scrollbar - the one in the content?
Please note that the solution should not break the following details:
The rounded corners and the shadow.
The title in the content block not participating in scrolling.
The image covering the whole scrollable content, so it scrolls together with the content.
In addition, it would be great if this can be achieved without as many nested div's as I have right now.
Edit: I am ready to go with the suggestion of #JHeth in the comments section. However, I would still be interested if someone can come up with an alternative design that does not rely on padding for centering.
Here is the code (CodePen):
* {
padding: 0;
margin: 0;
}
html {
font-size: 62.5%;
}
:root {
--navbar-height: 3rem;
}
.navbar {
width: 100%;
text-align: center;
font-size: 2rem;
line-height: var(--navbar-height);
background-color: lightgreen;
}
.centering {
position: absolute;
inset: var(--navbar-height) 0 0 0;
display: flex;
flex-direction: column;
align-items: center;
& .auto-margin {
margin: auto;
// For scrollable content
display: flex;
max-height: 100%;
padding-bottom: calc(var(--navbar-height)); // Causes scrolling
}
}
.content-block {
display: flex;
flex-direction: column;
.title {
font-size: 2rem;
position: sticky;
}
.content-outer-container {
display: flex;
flex-direction: column;
overflow-y: auto;
border-radius: 1em;
box-shadow: 0 1em 2em rgba(black, 0.4);
.content-container {
width: 300px;
overflow-y: auto;
.content {
position: relative;
padding: 1em;
&:before {
content: "";
z-index: -1;
position: absolute;
top: 0;
left: 0;
right: 0;
height: 100%;
background-position: center;
background-image:
url(http://www.freegreatpicture.com/files/147/18380-hd-color-background-wallpaper.jpg);
}
}
}
}
}
<div class="navbar">An Amazing Navbar</div>
<div class="centering">
<div class="auto-margin">
<div class="content-block">
<div class="title">My Title</div>
<div class="content-outer-container">
<div class="content-container">
<div class="content">
<h1>Line1</h1>
<h1>Line2</h1>
<h1>Line3</h1>
<h1>Line4</h1>
<h1>Line5</h1>
</div>
</div>
</div>
</div>
</div>
</div>
simply remove max-height:100%; to .centering .auto-margin and it'll works!
.centering .auto-margin {
margin: auto;
display: flex;
/* max-height: 100%; */
padding-bottom: calc(var(--navbar-height));
}

two-column sticky flexbox scrolling not working [duplicate]

This question already has an answer here:
Why is 'position: sticky' not working with Core UI's Bootstrap CSS
(1 answer)
Closed 1 year ago.
I'm having trouble getting my flexbox two-column setup to work.
Basically I just want the left column to be sticky while scrolling down the right one and then end scrolling at the exact same point.
It should also be collapsible as in the example below.
It's supposed to substitute this solutions i made using a regular grid which I'm unfortunately not able use anymore.
You can see my current progress below - I'm not really able to figure out what to do from here - as I'm a rookie I hoped you guys would know.
.wrapper {
display: flex;
flex-flow: row wrap;
overflow: auto;
gap: 2em;
justify-content: flex-start;
height: auto;
font-weight: bold;
text-align: center;
}
.wrapper > * {
padding: 10px;
flex: 1 100%;
}
.aside-1 {
position: -webkit-sticky;
position: sticky;
background: gold;
height: auto;
top: 0;
align-self: flex-start;
}
.aside-2 {
background: hotpink;
height: 900px;
top: 0;
}
#media all and (min-width: 300px) {
.aside { flex: 1 0 0; }
}
<section class="page-width">
<div class="wrapper">
<aside class="aside aside-1"><img width="100%" src="https://cdn.shopify.com/s/files/1/0044/2852/9698/files/242370040_4238706352865614_2798039132201744827_n.jpg"> Aside 1
</aside>
<aside class="aside aside-2">
Aside 2
</aside>
</div>
</section>
I've checked the forum without really finding what I need and hope that somebody would be able to help me :o) Thanks a million!
Remove overflow:auto on parent container of sticky element to make stickiness work
.wrapper {
display: flex;
flex-flow: row wrap;
gap: 2em;
justify-content: flex-start;
height: auto;
font-weight: bold;
text-align: center;
}
.wrapper > * {
padding: 10px;
flex: 1 100%;
}
.aside-1 {
position: -webkit-sticky;
position: sticky !important;
background: gold;
top: 0 !important;
align-self: flex-start;
}
.aside-2 {
background: hotpink;
height: 900px;
top: 0;
}
#media all and (min-width: 300px) {
.aside { flex: 1 0 0; }
}
.other-content{
margin-top: 2rem;
height: 20rem;
width: 100%;
background: red;
position:sticky;
top:0;
}
<section class="page-width">
<div class="wrapper">
<aside class="aside aside-1"><img width="100%" src="https://cdn.shopify.com/s/files/1/0044/2852/9698/files/242370040_4238706352865614_2798039132201744827_n.jpg"> Aside 1
</aside>
<aside class="aside aside-2">
Aside 2
</aside>
</div>
<div class="divider"></div>
<div class="other-content"></div>
</section>

How to center second div by parent, mentioning, there is first div [duplicate]

I would like to have A B and C aligned in the middle.
How can I get D to go completely to the right?
BEFORE:
AFTER:
ul {
padding: 0;
margin: 0;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
li {
display: flex;
margin: 1px;
padding: 5px;
background: #aaa;
}
li:last-child {
background: #ddd;
/* magic to throw to the right*/
}
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
https://jsfiddle.net/z44p7bsx/
Below are five options for achieving this layout:
CSS Positioning
Flexbox with Invisible DOM Element
Flexbox with Invisible Pseudo-Element
Flexbox with flex: 1
CSS Grid Layout
Method #1: CSS Positioning Properties
Apply position: relative to the flex container.
Apply position: absolute to item D.
Now this item is absolutely positioned within the flex container.
More specifically, item D is removed from the document flow but stays within the bounds of the nearest positioned ancestor.
Use the CSS offset properties top and right to move this element into position.
li:last-child {
position: absolute;
top: 0;
right: 0;
background: #ddd;
}
ul {
position: relative;
padding: 0;
margin: 0;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
li {
display: flex;
margin: 1px;
padding: 5px;
background: #aaa;
}
p {
text-align: center;
margin-top: 0;
}
span {
background-color: aqua;
}
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>true center</span></p>
One caveat to this method is that some browsers may not completely remove an absolutely-positioned flex item from the normal flow. This changes the alignment in a non-standard, unexpected way. More details: Absolutely positioned flex item is not removed from the normal flow in IE11
Method #2: Flex Auto Margins & Invisible Flex Item (DOM element)
With a combination of auto margins and a new, invisible flex item the layout can be achieved.
The new flex item is identical to item D and is placed at the opposite end (the left edge).
More specifically, because flex alignment is based on the distribution of free space, the new item is a necessary counterbalance to keep the three middle boxes horizontally centered. The new item must be the same width as the existing D item, or the middle boxes won't be precisely centered.
The new item is removed from view with visibility: hidden.
In short:
Create a duplicate of the D element.
Place it at the beginning of the list.
Use flex auto margins to keep A, B and C centered, with both D elements creating equal balance from both ends.
Apply visibility: hidden to the duplicate D
li:first-child {
margin-right: auto;
visibility: hidden;
}
li:last-child {
margin-left: auto;
background: #ddd;
}
ul {
padding: 0;
margin: 0;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
li {
display: flex;
margin: 1px;
padding: 5px;
background: #aaa;
}
p { text-align: center; margin-top: 0; }
span { background-color: aqua; }
<ul>
<li>D</li><!-- new; invisible spacer item -->
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>true center</span></p>
Method #3: Flex Auto Margins & Invisible Flex Item (pseudo-element)
This method is similar to #2, except it's cleaner semantically and the width of D must be known.
Create a pseudo-element with the same width as D.
Place it at the start of the container with ::before.
Use flex auto margins to keep A, B and C perfectly centered, with the pseudo and D elements creating equal balance from both ends.
ul::before {
content:"D";
margin: 1px auto 1px 1px;
visibility: hidden;
padding: 5px;
background: #ddd;
}
li:last-child {
margin-left: auto;
background: #ddd;
}
ul {
padding: 0;
margin: 0;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
li {
display: flex;
margin: 1px;
padding: 5px;
background: #aaa;
}
p { text-align: center; margin-top: 0; }
span { background-color: aqua; }
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>true center</span></p>
Method #4: Add flex: 1 to left and right items
Starting with Method #2 or #3 above, instead of worrying about equal width for the left and right items to maintain equal balance, just give each one flex: 1. This will force them both to consume available space, thus centering the middle item.
You can then add display: flex to individual items in order to align their content.
NOTE about using this method with min-height: Currently in Chrome, Firefox, Edge and possibly other browsers, the shorthand rule flex: 1 breaks down to this:
flex-grow: 1
flex-shrink: 1
flex-basis: 0%
That percentage unit (%) on flex-basis causes this method to break when min-height is used on the container. This is because, as a general rule, percentage heights on the children require an explicit height property setting on the parent.
This is an old CSS rule dating back to 1998 (CSS Level 2) which is still in effect in many browsers to some degree or another. For complete details see here and here.
Here's an illustration of the problem posted in the comments by user2651804:
#flex-container {
display: flex;
flex-direction: column;
background: teal;
width: 150px;
min-height: 80vh;
justify-content: space-between;
}
#flex-container>div {
background: orange;
margin: 5px;
}
#flex-container>div:first-child {
flex: 1;
}
#flex-container::after {
content: "";
flex: 1;
}
<div id="flex-container">
<div>very long annoying text that will add on top of the height of its parent</div>
<div>center</div>
</div>
The solution is to not use the percentage unit. Try px or just nothing at all (which is what the spec actually recommends, despite the fact that at least some of the major browsers have appended a percentage unit for whatever reason).
#flex-container {
display: flex;
flex-direction: column;
background: teal;
width: 150px;
min-height: 80vh;
justify-content: space-between;
}
#flex-container > div {
background: orange;
margin: 5px;
}
/* OVERRIDE THE BROWSER SETTING IN THE FLEX PROPERTY */
#flex-container > div:first-child {
flex: 1;
flex-basis: 0;
}
#flex-container::after {
content: "";
flex: 1;
flex-basis: 0;
}
/* OR... JUST SET THE LONG-HAND PROPERTIES INDIVIDUALLY
#flex-container > div:first-child {
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0;
}
#flex-container::after {
content: "";
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0;
}
*/
<div id="flex-container">
<div>very long annoying text that will add on top of the height of its parent</div>
<div>center</div>
</div>
Method #5: CSS Grid Layout
This may be the cleanest and most efficient method. There is no need for absolute positioning, fake elements or other hackery.
Simply create a grid with multiple columns. Then position your items in the middle and end columns. Basically, just leave the first column empty.
ul {
display: grid;
grid-template-columns: 1fr repeat(3, auto) 1fr;
grid-column-gap: 5px;
justify-items: center;
}
li:nth-child(1) { grid-column-start: 2; }
li:nth-child(4) { margin-left: auto; }
/* for demo only */
ul { padding: 0; margin: 0; list-style: none; }
li { padding: 5px; background: #aaa; }
p { text-align: center; }
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>| true center |</span></p>
The simplest solution will be to justify-content center to the parent container and giving margin-left auto to first and last child element.
ul {
display:flex;
justify-content:center;
}
.a,.d {
margin-left:auto;
}
<ul>
<li class="a">A</li>
<li>B</li>
<li>C</li>
<li class="d">D</li>
</ul>
Most easy way
.box{
display:flex;
justify-content:center;
}
.item1{
flex:1;
display: flex;
justify-content: center;
transform: translateX(10px);/*D element Width[if needed]*/
}
<div class="box">
<div class="item1">
<div>A</div>
<div>B</div>
<div>C</div>
</div>
<div class="item2">D</div>
</div>
Using the display:grid approach, you can simply put all of the ul children into the same cell and then set justify-self:
.ul {
display: grid;
}
.ul > * {
grid-column-start: 1;
grid-row-start: 1;
justify-self:center;
}
.ul > *:last-child {
justify-self: right;
}
/* Make Fancy */
.li {
display:inline-block;
margin: 1px;
padding: 5px;
background: #bbb;
}
<div class='ul'>
<span>
<span class='li'>A</span>
<span class='li'>B</span>
<span class='li'>C</span>
</span>
<span class='li'>D</span>
</div>
Inspired by the Method #5: CSS Grid Layout of #Michal Benjamin's solution and because I'm using Tailwind and as of now still don't have access to all the grid options by default. This seems to work:
ul {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
}
li {
align-self: center;
}
li:nth-child(1) {
justify-content: flex-start; /* OR margin-right: auto */
}
li:nth-child(3) {
justify-content: flex-end; /* OR margin-left:auto */
}
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
</ul>
PS: Not sure if mixing up flex and grid like this is a good idea!
If you want to make it aligned, you can simply attach an empty span and split the three child spans into them.
The easiest way:
.wrap {
display:flex;
}
.full-width {
width: 100%;
}
.centered {
display: flex;
justify-content:center;
}
.btn {
display: flex;
justify-content: end;
}
<div class="wrap">
<div class="full-width"></div>
<div class="full-width centered">
<div>A</div>
<div>B</div>
<div>C</div>
</div>
<div class="full-width btn">D</div>
</div>
Very clear question. I couldn't help but post the answer after a few hours of digging. We Could of solved this with tables, table-cell, absolute positions, transforms but we just had to do it with flexbox :)
.parent {
display: flex;
justify-content: flex-end;
}
.center {
margin: auto;
}
http://codepen.io/rgfx/pen/BLorgd
The accepted answer can be changed a bit because you can use grid template areas and do it without fake element
grid-template-areas '. b c'
grid-template-columns: 1fr 1fr 1fr
I expanded on Michael_B's answer
.center-flex__2-of-3 > :nth-child(1), .center-flex__2-of-3 > :nth-child(3) {
flex: 1;
}
.center-flex__2-of-3 > :nth-child(1) {
justify-content: flex-start;
}
.center-flex__2-of-3 > :nth-child(3) {
justify-content: flex-end;
}
.center-flex__1-of-2 > :nth-child(1) {
margin: auto;
}
.center-flex__1-of-2 > :nth-child(2) {
flex: 1;
justify-content: flex-end;
}
.center-flex__2-of-2 > :nth-child(1) {
flex: 1;
justify-content: flex-start;
}
.center-flex__2-of-2 > :nth-child(2) {
margin: auto;
}
.center-flex__1-of-2:before, .center-flex__1-of-1:before {
content: '';
flex: 1;
}
.center-flex__1-of-1:after, .center-flex__2-of-2:after {
content: '';
flex: 1;
}
[class*=center-flex] {
display: flex;
list-style: none;
margin: 0;
padding: 0;
border: 10px solid rgba(0, 0, 0, 0.1);
}
[class*=center-flex] > * {
display: flex;
}
li {
padding: 3px 5px;
}
2 of 3
<ul class="center-flex__2-of-3">
<span>
<li>Accusamus</li>
<li>Porro</li>
</span>
<span>
<li>Center</li>
<li>this</li>
</span>
<span>
<li>Accusamus</li>
<li>Porro</li>
<li>Culpa</li>
<li>Sit</li>
</span>
</ul>
<br><br>
1 of 2
<ul class="akex center-flex__1-of-2">
<span>
<li>Center</li>
<li>this</li>
</span>
<span>
<li>Accusamus</li>
<li>Porro</li>
<li>Culpa</li>
<li>Sit</li>
</span>
</ul>
<br><br>
2 of 2
<ul class="akex center-flex__2-of-2">
<span>
<li>Accusamus</li>
<li>Porro</li>
<li>Culpa</li>
<li>Sit</li>
</span>
<span>
<li>Center</li>
<li>this</li>
</span>
</ul>
<br><br>
1 of 1
<ul class="center-flex__1-of-1">
<span>
<li>Center</li>
<li>this</li>
</span>
</ul>
Here with the help of SASS as a codepen
ul {
padding: 0;
margin: 0;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
li {
display: flex;
margin: 1px;
padding: 5px;
background: #aaa;
}
li:last-child {
background: #ddd;
position:absolute;
right:10px;
}
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>

CSS Flexbox - Same height when a column contains multiple parts?

I have a simple question. I have a basic flex-box layout. One column takes up 2/3 of the layout, the other takes up a third. Both of them have a purple semi-transparent header (.85) with their contents are in an opaque black box.
http://codepen.io/StuffieStephie/pen/XdoBqL
body {
background: url('http://www.amazingwallpaperz.com/wp-content/uploads/Black-and-Purple-Abstract-Cool-Backgrounds-Wallpaper.jpg') center center;
background-size: cover;
font-family: 'Open Sans';
}
#featuredSlide, #featuredSlide img {
width: 100%;
max-width: 800px;
margin: 0 auto;
}
.container {
display: -webkit-flex;
display: flex;
justify-content: space-between;
color: #fff;
}
.sect {
box-sizing: border-box;
width: 32%;
-webkit-flex: 1;
flex: 1;
margin: 30px; text-align: center;
}
.sect + .sect {
margin-left: 10px;
}
.sect.feat {width: 65%;
-webkit-flex: 2;
flex: 2;
}
.sect .cont {
background:#414141;
padding-top: 40px;
padding-bottom: 30px;
border-radius: 0 0 5px 5px;
}
.sect h2 {
background:#414141;
background-color: rgba(52,41,109,.85);
margin-bottom: 0;
text-align: center;
text-transform: uppercase;
font-size: 2em;
font-weight: 300;
padding: 30px 10px;
border-radius: 5px 5px 0 0;
}
<head><link href='http://fonts.googleapis.com/css?family=Open+Sans:300,400,600' rel='stylesheet' type='text/css'>
</head>
<body>
<div class="container">
<div class="sect feat">
<h2> Featured Guests & Programming</h2>
<div class="cont">
<!-- SLIDE SHOW -->
<div id="featuredSlide" class="owl-carousel">
<img src="http://placehold.it/800x300/5d64a8">
</div> <!-- CLOSING SLIDE SHOW DIV TAG --></div>
</div>
<div class="sect">
<h2> News </h2>
<div class="cont">Some thrilling article</div>
</div>
</div>
<div class="clearfix"></div>
</body>
Both .sect elements are the same height. I want both .sect .cont elements to be the same height. I know I can make them look the same height by setting a background-color to .sect but that will ruin the transparency of my headers.
Any thoughts?
You can add flex-direction: column; to your .sect class, and give your .cont class a flex-grow: 1. This will make the .cont div's take up the remaining height of the .sect class.
.sect {
display: flex;
flex-direction: column;
}
.cont {
flex-grow: 1;
}
CodePen
You absolutely can do this with css only. Add the following to your .sect properties:
overflow: hidden;
position: relative;
border-radius:5px;
and add this to make the heights match:
.sect + .sect .cont::after {
background: #414141 none repeat scroll 0 0;
content: "";
height: 3000px;
left: 0;
position: absolute;
width: 100%;
}
You should also then be able to take out your border radii from the h2 and .cont as well.

Resources