CSS: Combining display:flex and overflow:auto kills padding [duplicate] - css

I have a list of items that I'm trying to arrange into a scrollable horizontal layout with flexbox.
Each item in the container has a margin left and right, but the right margin of the last item is being collapsed.
Is there a way to stop this happening, or a good workaround?
ul {
list-style-type: none;
padding: 0;
margin: 0;
display: flex;
height: 300px;
overflow: auto;
width: 600px;
background: orange;
}
ul li {
background: blue;
color: #fff;
padding: 90px;
margin: 0 30px;
white-space: nowrap;
flex-basis: auto;
}
<div class="container">
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
</div>

Potential Problem #1
The last margin is not being collapsed. It's being ignored.
The overflow property applies only to content. It doesn't apply to padding or margins.
Here's what it says in the spec:
11.1.1 Overflow: the overflow
property
This property specifies whether content of a block container element
is clipped when it overflows the element's box.
Now let's take a look at the CSS Box Model:
source: W3C
The overflow property is limited to the content box area. If the content overflows its container, then overflow applies. But overflow doesn't enter into the padding or margin areas (unless, of course, there is more content that follows).
Potential Problem #2
The problem with Potential Problem #1 is that it appears to fall apart outside of a flex or grid formatting context. For example, in a standard block layout, the last margin doesn't appear to collapse. So maybe overflow is permitted to cover margins / paddings, regardless of what it says in the spec.
div {
height: 150px;
overflow: auto;
width: 600px;
background: orange;
white-space: nowrap;
}
span {
background: blue;
color: #fff;
padding: 50px;
margin: 0 30px;
display: inline-block;
}
<div class="container">
<span>Item 1</span>
<span>Item 2</span>
<span>Item 3</span>
<span>Item 4</span>
</div>
Hence, maybe the problem is instead related to elements that are "over-constrained".
10.3.3 Block-level, non-replaced elements in normal
flow
The following constraints must hold among the used values of the other
properties:
margin-left + border-left-width + padding-left + width +
padding-right + border-right-width + margin-right = width of
containing block
If width is not auto and border-left-width + padding-left +
width + padding-right + border-right-width (plus any of
margin-left or margin-right that are not auto) is larger than
the width of the containing block, then any auto values for
margin-left or margin-right are, for the following rules, treated
as zero.
If all of the above have a computed value other than auto, the values are said to be "over-constrained" and one of the used values
will have to be different from its computed value. If the direction
property of the containing block has the value ltr, the specified
value of margin-right is ignored and the value is calculated so as
to make the equality true. If the value of direction is rtl,
this happens to margin-left instead
(emphasis added)
So, according to the CSS Visual Formatting Model, elements may be "over-constrained" and, as a result, a right margin gets tossed out.
Potential Workarounds
Instead of margin or padding, use a right border on the last element:
li:last-child {
border-right: 30px solid orange;
}
ul {
list-style-type: none;
padding: 0;
margin: 0;
display: flex;
height: 100px; /* adjusted for demo */
overflow: auto;
width: 600px;
background: orange;
}
ul li {
background: blue;
color: #fff;
padding: 90px;
margin: 0 30px;
white-space: nowrap;
flex-basis: auto;
}
li:last-child {
border-right: 30px solid orange;
}
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
Another solution uses a pseudo-elements instead of margins or padding.
Pseudo-elements on a flex container are rendered as flex items. The first item in the container is ::before and last item is ::after.
ul::after {
content: "";
flex: 0 0 30px;
}
ul {
list-style-type: none;
padding: 0;
margin: 0;
display: flex;
height: 100px; /* adjusted for demo */
overflow: auto;
width: 600px;
background: orange;
}
ul li {
margin: 0 30px;
background: blue;
color: #fff;
padding: 90px;
white-space: nowrap;
flex-basis: auto;
}
ul::after {
content: "";
flex: 0 0 30px;
}
ul::before {
content: "";
flex: 0 0 30px;
}
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>

Your problem is not the margin in itself. It's the scroll bar dimensioning only the visible content of the element.
One hack to solve it would be to create a visible element that occupies the margin
This solution handles this using a pseudo on the last child
ul {
list-style-type: none;
padding: 0;
margin: 0;
display: flex;
height: 300px;
overflow: auto;
width: 600px;
background: orange;
}
ul li {
background: blue;
color: #fff;
padding: 90px;
margin: 0 30px;
white-space: nowrap;
flex-basis: auto;
position: relative;
}
li:last-child:after {
content: "";
width: 30px;
height: 1px;
position: absolute;
left: 100%;
top: 0px;
}
<div class"container">
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
</div>

You can set width and overflow on the div container, and set display: inline-flex rather than flex on the ul, so that the size of the flex box will be calculated based on the items inside, and all padding and margin will apply without any issues.
.container {
width: 600px;
overflow: auto;
}
.container ul {
list-style: none;
padding: 0;
margin: 0;
display: inline-flex;
background: orange;
}
.container li {
padding: 60px;
margin: 0 30px;
white-space: nowrap;
background: blue;
color: #fff;
}
<div class="container">
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
</div>

See the solution. I remove white-space, flex-basis and margin, to provide you a pure flexbox solution.
It relays on flex-flow: row(horizontal), justify-content: space-around (your margin) and no more!! The width is changed to 1200px since the padding of 90px set the total width of the boxes more than your 600px (defined in your snippet).
ul {
list-style-type: none;
padding: 0;
margin: 0;
display: flex;
flex-flow: row ;
justify-content: space-around;
height: 300px;
overflow: auto;
width: 1200px;
background: orange;
}
ul li {
background: blue;
color: #fff;
padding: 90px;
}
<div class"container">
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
</div>

Related

I am trying to center align the menu

I am a newbie in CSS. I am learning by playing with the code of a WordPress theme.
Last time I posted this issue but I contracted covid and was hospitalized for more than two weeks. I have deleted the old question and broken the initial question into two parts. This is the first part.
To remove the Site-Name on the left side. I used display: none.
<div id="header-left">
<div id="hgroup" class="logo-disable">
<h1 id="site-title">
Catch Kathmandu
</h1>
<h2 id="site-description"> Catch Kathmandu Theme is a fully responsive WordPress theme that looks elegant on any devices.</h2>
</div><!-- #hgroup -->
</div>
#header-left {
-webkit-text-size-adjust: 100%;
color: #404040;
line-height: 1.8;
text-rendering: optimizeLegibility;
word-wrap: break-word;
border: 0;
font-family: inherit;
font-size: 100%;
font-style: inherit;
font-weight: inherit;
margin: 0;
outline: 0;
padding: 0;
vertical-align: baseline;
float: left;
max-width: 100%;
display: none;
}
To center-align the menu on the right side.
<div id="header-right" class="header-sidebar widget-area">
<aside class="widget widget_nav_menu">
<div id="primary-menu-wrapper" class="menu-wrapper">
<div class="menu-toggle-wrapper">
<button id="menu-toggle" class="menu-toggle" aria-controls="main-menu" aria-expanded="false"><span class="menu-label">Menu</span></button>
</div><!-- .menu-toggle-wrapper -->
<div class="menu-inside-wrapper">
<nav id="site-navigation" class="main-navigation" role="navigation" aria-label="Primary Menu" aria-expanded="false">
<ul id="menu-primary-items" class="menu nav-menu"><li class="current-menu-item">Home</li><li class="page_item page-item-2">About</li><li class="page_item page-item-182">Home</li><li class="page_item page-item-46 page_item_has_children" aria-haspopup="true">Parent Page<button class="dropdown-toggle" aria-expanded="false"><span class="screen-reader-text">expand child menu</span></button><ul class="children"><li class="page_item page-item-49">Sub-page</li></ul></li></ul> </nav><!-- .main-navigation -->
</div>
#header-right {
-webkit-text-size-adjust: 100%;
color: #404040;
line-height: 1.8;
text-rendering: optimizeLegibility;
word-wrap: break-word;
border: 0;
font-family: inherit;
font-size: 100%;
font-style: inherit;
font-weight: inherit;
margin: 0;
outline: 0;
padding: 0;
vertical-align: baseline;
padding-top: 50px;
float: right;
margin-right: 33%;
}
I reached my center alignment by reducing the margin-right from 50% then to 33%. Though the sweet spot is between 32% to 33%.
I also tried center-align the menu with pixels(margin-right :400px).
The difference between both methods is visible when I reduce the screen size. 33% mostly remains center-align but the px changes the position of the menu, as the screen changes.
Is there any other way I could center the menu?
There are many ways to center items depending on their block type.
You can use display flex on the parent and then add a justify-content: center to center the children items on the page horizontally, see flex axis - in basic concepts of flex for more info.
Then you can use flex property on the children and can add a number to that property to tell CSS how much of the parents width that child will take up.
For example if I set both to child elements to flex: 1 they will take up 50%, if there were three child elements all with a flex: 1, they would then take up 33% of their parents width. I can also place a percentage on the flex property as well => .header set flex: 60% and .nav-parent set flex: 40%, they will then take up their set percentages of the parents width.
Furthermore I can add display: flex properties to the child elements as well to further center their contents, as I have done on the .menu class which is a child of the .nav-parent. These can then be further align and centered using the axis centering properties for flex, justify-content and align-items. The good thing is that these properties are dynamic in that they scale to fit browser sizes as well.
.nav-section {
display: flex;
justify-content: center;
font-family: sans-serif;
align-items: center;
padding: 1rem;
}
.header h1 {
line-height: 1px;
}
.header {
flex: 60%;
}
.nav-parent {
flex: 40%;
}
.header span {
font-size: .8rem;
font-weight: 100;
font-style: italic;
}
ul li {
list-style: none;
}
ul li ~ li {
margin-left: .5rem;
}
.btn {
flex: 1;
padding: .5rem 0;
text-align: center;
}
.menu {
display: flex;
justify-content: center;
color: #555;
font-size: .8rem;
}
.active {
background: skyblue;
}
<div class="nav-section">
<div class="header">
<h1>Catch Kathmandu</h1>
<span>Catch Kathmandu Theme is a fully responsive WordPress theme that looks elegant on any device.</span>
</div>
<div class="nav-parent">
<ul class="menu">
<li class="home active btn">Home</li>
<li class="about btn">About</li>
<li class="contact btn">Contact</li>
<li class="parent btn">Page</li>
</ul>
</div>
</div>
Is there any other way I could center the menu?
There are a good handful of ways you can center the menu.
If your menu is a block-level element with an explicitly declared width, one of the most basic techniques is applying the keyword auto to margin-right and margin-left:
.my-menu {
margin-top: 12px; // <= Just an example, you can use any value
margin-right: auto;
margin-bottom: 12px; // <= Just an example, you can use any value
margin-left: auto;
}
the CSS shorthand for these four declarations is:
.my-menu {
margin: 12px auto 12px auto;
}
or, since the vertical and horizontal values are the same, you can declare:
.my-menu {
margin: 12px auto;
}
Working Example:
.my-menu {
display: block;
margin: 12px auto;
}
.my-menu.vertical {
width: 100px;
}
.my-menu.horizontal {
width: 396px;
padding: 0;
}
.my-menu.horizontal li {
display: inline-block;
padding: 0 6px;
}
.my-menu.horizontal li::before {
content: '•';
display: inline-block;
padding-right: 6px;
font-size: 20px;
}
<ul class="my-menu vertical">
<li>List Item 1</li>
<li>List Item 2</li>
<li>List Item 3</li>
<li>List Item 4</li>
</ul>
<ul class="my-menu horizontal">
<li>List Item 1</li>
<li>List Item 2</li>
<li>List Item 3</li>
<li>List Item 4</li>
</ul>

Use CSS to position two elements at the same location and make container large enough to hold them

So I have two (or potentially more) elements that I want to occupy the same space. They need to fit inside a container element whose size should be automatically made large enough to contain them. I currently have a couple of possibilities that don't quite work, shown below:
.first {
display: inline-block;
position: relative;
border: 1px solid black;
padding: 1px;
}
.first > li {
display: block;
padding: 0px;
margin: 0px;
position: relative;
}
.second {
display: inline-block;
position: relative;
border: 1px solid black;
padding: 1px;
}
.second > li {
display: block;
padding: 0px;
margin: 0px;
position: absolute;
}
.third {
display: inline-block;
border: 1px solid black;
padding: 1px;
}
.third > li {
padding: 0px;
margin: 0px;
float: left;
margin-right: -100%;
}
<div style="float:right; width: 75%">(Attempt 1: note that the two items are not superimposed, but the container is large enough to hold them)</div>
<ul class="first">
<li>Item number 1</li>
<li>Item number 2</li>
</ul>
<br><br>
<div style="float:right; width: 75%">(Attempt 2: note that this time they are superimposed, but no space is allocated in the container for them)</div>
<ul class="second">
<li>Item number 1</li>
<li>Item number 2</li>
</ul>
<br><br><br><br>
Edited to add a third attempt:<br>
<ul class="third">
<li>Item number 1</li>
<li>Item number 2</li>
</ul>
Ideally I'm looking for a pure CSS solution, but it only needs to work on webkit-based browsers (i.e. chrome / safari).
Updated: add a third attempt that gets the two items overlapping, but allocates enough space to hold both of them side by side, which still doesn't really get me where I want to be.
For reference: I don't know the sizes of the items in advance, so can't (for example) size the container to hold the largest and make the rest overlap it.
like this?
ul {
display: inline-block;
position: relative;
border: 1px solid black;
padding:0; margin:0;
}
ul li {
display: block;
position: absolute;
top:0; left:0;
}
ul li:nth-child(1) {
position:relative;
}
<ul>
<li>Item number 1</li>
<li>Item number 2</li>
</ul>
absolute positioning:
Setting position: absolute on all <li> elements, then setting position: relative on the .current (there are many ways to select a dominant <li> and using a class is just one of them) <li> gives what I think you're after.
We can then set the visibility of every <li> to hidden, and set the visibility of .current to visible to reduce the visual clutter:
ul {
display: inline-block;
padding: .2em .3em;
list-style: none;
border: 2px solid black;
}
li {
position: absolute;
visibility: hidden;
}
li.current {
position: relative;
visibility: visible;
}
<ul>
<li>a</li>
<li>abc</li>
<li>abcdefg</li>
<li>foo bar baz</li>
<li>i dunno lol</li>
<li class="current">42</li>
</ul>
This approach is effectively identical to using display none and list-item:
ul {
display: inline-block;
padding: .2em .3em;
list-style: none;
border: 2px solid black;
}
li {
display: none;
}
li.current {
display: list-item;
}
<ul>
<li>a</li>
<li>abc</li>
<li>abcdefg</li>
<li>foo bar baz</li>
<li>i dunno lol</li>
<li class="current">42</li>
</ul>
Or for the container to always be wide enough for the longest string:
Setting the height of every <li> to 0 and giving just the .current its initial height back to push the <ul>'s border out, we get something like this:
ul {
display: inline-block;
padding: .2em .3em;
list-style: none;
border: 2px solid black;
}
li {
height: 0;
visibility: hidden;
}
li.current {
height: initial;
visibility: visible;
}
<ul>
<li>a</li>
<li>abc</li>
<li>abcdefg</li>
<li>foo bar baz</li>
<li>i dunno lol</li>
<li class="current">42</li>
</ul>
Using JavaScript :O
Although the question calls for a CSS solution, where that might be impossible or unreliable, we can always rely on JS.
In the case that both the width and height of the child <li>s may be different, and that the container should be both wide and high enough for every child, JS provides.
The method below uses getComputedStyle to get the width and height of the relatively rendered <li> elements, and sets position: absolute on them all as they're read.
The parent <ul> then has its width and height set to the largest width and heights of the child <li>s.
The result is a <ul> that's wide and high enough to contain every child <li>, but with all the children positioned absolutely;
var widths = [], heights = [];
// loop through all the li elements
document.querySelectorAll( "li" ).forEach( function( v ) {
// get the computed styles for each li element
var ecs = window.getComputedStyle( v );
// push the width into the widths array
widths.push( ecs.width );
// push the height into the heights array
heights.push( ecs.height );
// set position:absolute on this li element
v.style.position = "absolute";
} );
document.querySelector( "ul" ).setAttribute( "style",
/* sort the widths array and pop the last (and therefore largest) value
then apply it to the width of the ul. */
"width:" + widths.sort().pop() +
/* sort the heights array and pop the last (and therefore largest) value
then apply it to the height of the ul. */
";height:" + heights.sort().pop()
);
ul {
display: inline-block;
padding: .2em .3em;
list-style: none;
border: 2px solid black;
}
li {
visibility: hidden;
}
li.current {
visibility: visible;
}
<ul>
<li>a</li>
<li>abc</li>
<li>abcdefg<br>1234567</li>
<li>foo bar baz</li>
<li>i dunno lol</li>
<li class="current">42</li>
</ul>
display: flex and visibility: hidden
I was wondering if visibility: collapse might be useful, and found a CSS-tricks.com article linking to a csswg.org draft suggesting that visiblity: collapse may be used on <li>s with display: flex to acheive pretty much exactly what you're after.
I couldn't get it to work, and noticed that their own example was not using either display: flex or visibility: collapse!
They are instead manipulating the heights of the children.
Since it is a draft, this may become a useable solution down the road.
I am unfamiliar with the use of flexboxes (deep shame) so wouldn't be surprised if a solution using them exists. I just don't (at this time) know it.
Why not do it like this:
.second > li {
display: inline-block;
padding: 0px;
margin: 0px;
position: absolute;
border-top: 1px solid black;
border-bottom: 1px solid black;
padding: 1px;
left:0;
}
.second > li:first-child {
border-left: 1px solid black;
}
.second > li:last-child {
border-right: 1px solid black;
}
<ul class="second">
<li>Item number 1</li>
<li>Item number 2 greater length</li>
</ul>
First, you should include your two elements inside a container div that you want to have and write property as:
position: absolute;
top: 0;
left: 0;
And, make your container position property as:
position: relative

Flex container not adjusting to content [duplicate]

This question already has answers here:
When flexbox items wrap in column mode, container does not grow its width
(9 answers)
Closed 5 years ago.
I learned here:
Multi columns list by css
how to make a self adjusting multi column list. However there is one problem left: The container doesn't adjust it's width to it's content:
https://jsfiddle.net/rkofktdz/3/
ul {
height: 40px;
display:inline-flex;
flex-direction: column;
flex-wrap: wrap;
border: 2px solid black;
background-color: grey;
padding: 0;
}
li {
list-style: none;
}
a {
display: inline-block;
width: 60px;
}
<ul>
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
<li>item 4</li>
</ul>
I can extend the container (ul) by applying a fixed width but I would like to have it self adjusting.
This is part of a three level menu being a bit more complex:
http://nachrichtentisch.de/
Please check if this is what you wanted to achieve:
https://jsfiddle.net/rkofktdz/4/
ul {
display:flex;
flex-wrap: wrap;
}
li {
list-style: none;
flex-direction: column;
display: flex;
border: 2px solid black;
background-color: grey;
height: 40px;
padding: 0;
margin: 0 10px;
}
a {
display: inline-block;
width: 60px;
}

When the flex container overflow, the last item's right margin was cut off [duplicate]

I have a list of items that I'm trying to arrange into a scrollable horizontal layout with flexbox.
Each item in the container has a margin left and right, but the right margin of the last item is being collapsed.
Is there a way to stop this happening, or a good workaround?
ul {
list-style-type: none;
padding: 0;
margin: 0;
display: flex;
height: 300px;
overflow: auto;
width: 600px;
background: orange;
}
ul li {
background: blue;
color: #fff;
padding: 90px;
margin: 0 30px;
white-space: nowrap;
flex-basis: auto;
}
<div class="container">
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
</div>
Potential Problem #1
The last margin is not being collapsed. It's being ignored.
The overflow property applies only to content. It doesn't apply to padding or margins.
Here's what it says in the spec:
11.1.1 Overflow: the overflow
property
This property specifies whether content of a block container element
is clipped when it overflows the element's box.
Now let's take a look at the CSS Box Model:
source: W3C
The overflow property is limited to the content box area. If the content overflows its container, then overflow applies. But overflow doesn't enter into the padding or margin areas (unless, of course, there is more content that follows).
Potential Problem #2
The problem with Potential Problem #1 is that it appears to fall apart outside of a flex or grid formatting context. For example, in a standard block layout, the last margin doesn't appear to collapse. So maybe overflow is permitted to cover margins / paddings, regardless of what it says in the spec.
div {
height: 150px;
overflow: auto;
width: 600px;
background: orange;
white-space: nowrap;
}
span {
background: blue;
color: #fff;
padding: 50px;
margin: 0 30px;
display: inline-block;
}
<div class="container">
<span>Item 1</span>
<span>Item 2</span>
<span>Item 3</span>
<span>Item 4</span>
</div>
Hence, maybe the problem is instead related to elements that are "over-constrained".
10.3.3 Block-level, non-replaced elements in normal
flow
The following constraints must hold among the used values of the other
properties:
margin-left + border-left-width + padding-left + width +
padding-right + border-right-width + margin-right = width of
containing block
If width is not auto and border-left-width + padding-left +
width + padding-right + border-right-width (plus any of
margin-left or margin-right that are not auto) is larger than
the width of the containing block, then any auto values for
margin-left or margin-right are, for the following rules, treated
as zero.
If all of the above have a computed value other than auto, the values are said to be "over-constrained" and one of the used values
will have to be different from its computed value. If the direction
property of the containing block has the value ltr, the specified
value of margin-right is ignored and the value is calculated so as
to make the equality true. If the value of direction is rtl,
this happens to margin-left instead
(emphasis added)
So, according to the CSS Visual Formatting Model, elements may be "over-constrained" and, as a result, a right margin gets tossed out.
Potential Workarounds
Instead of margin or padding, use a right border on the last element:
li:last-child {
border-right: 30px solid orange;
}
ul {
list-style-type: none;
padding: 0;
margin: 0;
display: flex;
height: 100px; /* adjusted for demo */
overflow: auto;
width: 600px;
background: orange;
}
ul li {
background: blue;
color: #fff;
padding: 90px;
margin: 0 30px;
white-space: nowrap;
flex-basis: auto;
}
li:last-child {
border-right: 30px solid orange;
}
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
Another solution uses a pseudo-elements instead of margins or padding.
Pseudo-elements on a flex container are rendered as flex items. The first item in the container is ::before and last item is ::after.
ul::after {
content: "";
flex: 0 0 30px;
}
ul {
list-style-type: none;
padding: 0;
margin: 0;
display: flex;
height: 100px; /* adjusted for demo */
overflow: auto;
width: 600px;
background: orange;
}
ul li {
margin: 0 30px;
background: blue;
color: #fff;
padding: 90px;
white-space: nowrap;
flex-basis: auto;
}
ul::after {
content: "";
flex: 0 0 30px;
}
ul::before {
content: "";
flex: 0 0 30px;
}
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
Your problem is not the margin in itself. It's the scroll bar dimensioning only the visible content of the element.
One hack to solve it would be to create a visible element that occupies the margin
This solution handles this using a pseudo on the last child
ul {
list-style-type: none;
padding: 0;
margin: 0;
display: flex;
height: 300px;
overflow: auto;
width: 600px;
background: orange;
}
ul li {
background: blue;
color: #fff;
padding: 90px;
margin: 0 30px;
white-space: nowrap;
flex-basis: auto;
position: relative;
}
li:last-child:after {
content: "";
width: 30px;
height: 1px;
position: absolute;
left: 100%;
top: 0px;
}
<div class"container">
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
</div>
You can set width and overflow on the div container, and set display: inline-flex rather than flex on the ul, so that the size of the flex box will be calculated based on the items inside, and all padding and margin will apply without any issues.
.container {
width: 600px;
overflow: auto;
}
.container ul {
list-style: none;
padding: 0;
margin: 0;
display: inline-flex;
background: orange;
}
.container li {
padding: 60px;
margin: 0 30px;
white-space: nowrap;
background: blue;
color: #fff;
}
<div class="container">
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
</div>
See the solution. I remove white-space, flex-basis and margin, to provide you a pure flexbox solution.
It relays on flex-flow: row(horizontal), justify-content: space-around (your margin) and no more!! The width is changed to 1200px since the padding of 90px set the total width of the boxes more than your 600px (defined in your snippet).
ul {
list-style-type: none;
padding: 0;
margin: 0;
display: flex;
flex-flow: row ;
justify-content: space-around;
height: 300px;
overflow: auto;
width: 1200px;
background: orange;
}
ul li {
background: blue;
color: #fff;
padding: 90px;
}
<div class"container">
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
</div>

Spread elements evenly using Flexbox

I'm starting with Flexbox and I'm trying to center a row with three columns to the center of the document. I've tried the following code (Written in Sass) but as you can see in the screenshot the three elements are not perfectly centered (they don't have the same space between them):
HTML for the header:
<header>
<nav>
<ul>
<li>ELE 1</li>
<li>ELEMENT 2</li>
<li>ELEMENT 3</li>
</ul>
</nav>
</header>
SCSS for the header:
header {
height: 80px;
width: 100%;
background-color: $dark-grey;
}
nav {
height: inherit;
max-width: 800px;
margin: auto;
text-align: center;
display: flex;
align-items: center;
& ul {
width: 100%;
display: flex;
& li {
flex: 1 0 auto;
& a, a:visited {
color: $white-alpha;
}
& a.active {
color: $white;
}
}
}
}
I've recreated the problem in this CodePen, as you can see the real example. What I'm doing wrong? Thanks.

Resources