I have a list which has six li elements. These by default all appear on one row.
On screen resize 540px, I want the last li item (item 6) to go onto another row, but be center aligned (so below item 3).
Unsure what I'm doing wrong here:
.container {
display: flex;
justify-content: center;
}
ul {
display: inline-block;
list-style: none;
margin: 0;
padding: 0;
line-height: 1em;
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
ul li {
margin-right: .5em;
border: 1px solid #a2a4a5;
padding: 15px;
}
#media (max-width: 540px) {
ul li {
border: 1px solid blue;
align-items: center;
}
}
<div class="container">
<ul>
<li>Text 1</li>
<li>Text 2</li>
<li>Text 3</li>
<li>Text 4</li>
<li>Text 5</li>
<li>Text 6</li>
</ul>
</div>
Try to add
justify-content: center
Or
justify-content: space-between //This will look close to what you actually have in responsive mode
to your ul
There is no way to achieve it without touching to all the other flex items
You need the container to have a height of 100%, I used 100vh here for simplicity.
Your flex element also need to have a height of 100%, and because the flex-direction is row, you should use align-items: center to vertically center the content
.container {
display: flex;
height: 100vh;
justify-content: center;
}
ul {
display: inline-block;
list-style: none;
justify-content: center;
align-items: center;
margin: 0;
padding: 0;
line-height: 1em;
display: flex;
height: 100%;
flex-direction: row;
flex-wrap: wrap;
}
ul li {
margin-right: .5em;
border: 1px solid #a2a4a5;
padding: 15px;
}
#media (max-width: 540px) {
ul li {
border: 1px solid blue;
align-items: center;
}
}
<div class="container">
<ul>
<li>Text 1</li>
<li>Text 2</li>
<li>Text 3</li>
<li>Text 4</li>
<li>Text 5</li>
<li>Text 6</li>
</ul>
</div>
Related
This question already has answers here:
Vertically center ul in div
(5 answers)
Closed 3 years ago.
I have this unordered list and I want to display it vertically and also make it completely centered inside the parent container. I've managed to make it display vertically and be centered on the x-axis, but not on the y-axis. "vertical-alignment: middle;" doesn't seem to do what I want.
Consider this html-code:
div {
margin: auto;
width: 90%;
height: 200px;
background-color: lightblue;
}
ul {
list-style: none;
height: 100%;
width: 100;
padding: 0;
text-align: center
}
ul li {
display: inline;
margin-right: 20px;
vertical-align: middle;
}
<div>
<ul>
<li>List Item 1</li>
<li>List Item 2</li>
<li>List Item 3</li>
</ul>
</div>
To vertically align on y-axis add the below given css to ul:
display:flex;
justify-content:center;
align-items:center;
And remove width:100; from ul tag.
Demo
div {
margin: auto;
width: 90%;
height: 200px;
background-color: lightblue;
}
ul {
list-style: none;
height: 100%;
padding: 0;
display:flex; /*add this */
justify-content:center; /*add this */
align-items:center; /*add this */
text-align: center
}
ul li {
display: inline;
margin-right: 20px;
vertical-align: middle;
}
<div>
<ul>
<li>List Item 1</li>
<li>List Item 2</li>
<li>List Item 3</li>
</ul>
</div>
You can use display: flex for the div and margin: auto for the ul. And remove height and width rules from ul. here's the working Fiddle
<div>
<ul>
<li>List Item 1</li>
<li>List Item 2</li>
<li>List Item 3</li>
</ul>
</div>
div {
display: flex;
margin: auto;
width: 90%;
height: 200px;
background-color: lightblue;
}
ul {
margin: auto;
list-style: none;
padding: 0;
text-align: center
}
ul li {
display: inline;
margin-right: 20px;
vertical-align: middle;
}
To align vertically u can use line-height.
use line-height instead of height in div tag.
div {
margin: auto;
width: 90%;
line-height: 200px; /*change this */
background-color: lightblue;
}
div {
margin: auto;
width: 90%;
line-height: 200px;
background-color: lightblue;
}
ul {
list-style: none;
height: 100%;
padding: 0;
text-align: center
}
ul li {
display: inline;
margin-right: 20px;
vertical-align: middle;
}
<div>
<ul>
<li>List Item 1</li>
<li>List Item 2</li>
<li>List Item 3</li>
</ul>
</div>
I have some cosmetic content which I would like to align between flex items which are justified with space-between.
The items have dynamic width.
The result in the following demo is what i'm looking for, except that since the content is purely cosmetic - I want to use generated content for them rather than actual elements.
ul {
display: flex;
justify-content: space-between;
align-items: center;
list-style: none;
padding: 0;
}
li:nth-child(odd) {
background-color: lime;
padding: 10px 20px
}
li:nth-child(even) {
margin: 0 auto;
}
<ul class="wpr">
<li>this is item 1</li>
<li>X</li>
<li>item 2</li>
<li>X</li>
<li>item 3 is considerably wider</li>
<li>X</li>
<li>item 4</li>
</ul>
Codepen demo (resize to see the effect)
I have attempted to do this by using absolute positioning - but I don't know if there is a mechanism to center the content between the items this way:
ul {
display: flex;
justify-content: space-between;
align-items: center;
list-style: none;
padding: 0;
}
li {
background-color: lime;
padding: 10px 20px;
position: relative;
}
li:after {
content: 'X';
position: absolute;
right: -50%; /* this obviously won't produce the correct centering */
}
<ul class="wpr">
<li>this is item 1</li>
<li>item 2</li>
<li>item 3 is considerably wider</li>
<li>item 4</li>
</ul>
Is it possible with CSS to add this content using generated content instead of actual elements?
Here is an idea with a small drawback because I had to omit the item in the last li:
ul {
display: flex;
justify-content: space-between;
align-items: center;
list-style: none;
padding: 0;
}
li {
display: flex;
align-items:center;
flex:1;
}
li span {
background-color: lime;
padding: 10px 20px;
white-space:nowrap;
}
li:after {
content: "X";
flex: 1;
text-align:center;
}
li:last-child {
flex:initial;
}
li:last-child::after {
content:none;
}
<ul class="wpr">
<li><span>this is item 1</span></li>
<li><span>item 2</span></li>
<li><span>item 3 is considerably wider</span></li>
<li><span>item 4</span></li>
</ul>
You can do it cleanly and efficiently with absolute positioning:
ul {
display: flex;
align-items: center;
list-style: none;
padding: 0;
}
li {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
padding: 10px 20px;
border: 1px dashed red;
position: relative;
}
li + li::before { /* #1 */
content: "X";
position: absolute;
right: 100%;
transform: translateX(50%); /* #2 */
}
<ul class="wpr">
<li>this is item 1</li>
<li>item 2</li>
<li>item 3 is considerably wider</li>
<li>item 4</li>
</ul>
revised codepen
Notes:
The adjacent sibling combinator (+) targets an element that immediately follows another element. In this case, the pseudo-element will only apply to li elements that follow another li. This will naturally exclude the ::before from the first li.
For an explanation of how this centering method works, see this post: Element will not stay centered, especially when re-sizing screen
One improvement i can suggest is replacing
li:after {
content: "X";
flex: 1;
text-align:center;
}
li:last-child {
flex:initial;
}
li:last-child::after {
content:none;
}
with
li:not(:last-child)::after {
content: "X";
flex: 1;
text-align:center;
}
This question already has answers here:
Make flex items take content width, not width of parent container
(3 answers)
Closed 5 years ago.
I would like to have the flex children rendered inline-block so that border-bottom is under the li's width instead of the container's width.
Apparently flex children can't be set as inline-block?
Is there a workaround to this problem?
.menu {
display: flex;
flex-flow: column;
list-style: none;
padding: 0;
}
.menu > li {
display: inline-block;
margin-bottom: 1rem;
border-bottom: 3px solid black;
}
<ul class="menu">
<li>Tab 1</li>
<li>Tab 2</li>
<li>Tab 3</li>
</ul>
https://codepen.io/joshuajazleung/pen/EbwZmJ
Add align-items: flex-start to the container:
.menu {
display: flex;
flex-flow: column;
align-items: flex-start; /* NEW */
list-style: none;
padding: 0;
}
.menu > li {
margin-bottom: 1rem;
border-bottom: 3px solid black;
}
<ul class="menu">
<li>Tab 1</li>
<li>Tab 2</li>
<li>Tab 3</li>
</ul>
OR... switch from display: flex to display: inline-flex.
.menu {
display: inline-flex;
flex-flow: column;
list-style: none;
padding: 0;
}
.menu > li {
margin-bottom: 1rem;
border-bottom: 3px solid black;
}
<ul class="menu">
<li>Tab 1</li>
<li>Tab 2</li>
<li>Tab 3</li>
</ul>
More details here: Make flex items take content width, not width of parent container
I'm trying to create a navigation bar, a logo at the left and the links centered in the remaining space. I followed the instructions in this thread:
In CSS Flexbox, why are there no "justify-items" and "justify-self" properties?
and used margin:auto; for the ul in order to get it centered. This worked fine so far but when I add margin or padding anywhere inside the ul the list of links wraps. I tried box-sizing:border-box; for the ul but no success. How can I fix this?
Fiddle: http://jsfiddle.net/30sy5dmy/5/
nav img {
height: 60px;
}
nav {
display: flex;
align-items: center;
justify-content: space-between;
}
.links {
margin: auto;
}
nav ul li {
display: inline-block;
list-style: none;
margin: 0 2%;
}
<nav>
<img src="https://teststein.000webhostapp.com/Logo.png">
<ul class="links">
<li>Link 1</li>
<li>Link 2</li>
<li>Link 2</li>
<li>Link 2</li>
</ul>
</nav>
The list items are wrapping because you're using percentage margins.
When you give the items horizontal margins of 2%, the browser calculates the length of that 2% after the size of the container has been determined. In other words, the percentages are not factored into the container width.
Therefore, when the 2% length is added to the items, the total length exceeds that of the container and wrapping occurs.
Solution #1: white-space: nowrap
One way to fix the problem is by suppressing line breaks in the container using the white-space property. This forces all items to stay on the same line, overflowing the container if necessary.
nav {
display: flex;
align-items: center;
justify-content: space-between;
border: 1px dashed black; /* for demo only */
}
nav img {
height: 60px;
}
.links {
margin: auto;
white-space: nowrap; /* NEW */
padding: 0; /* optional; remove default indentation on list elements */
border: 1px dashed red; /* for demo only */
}
nav ul li {
display: inline-block;
list-style: none;
margin: 0 2%;
}
<nav>
<img src="http://lorempixel.com/output/nature-q-c-60-60-1.jpg">
<ul class="links">
<li>Link 1</li>
<li>Link 2</li>
<li>Link 2</li>
<li>Link 2</li>
</ul>
</nav>
Solution #2: Don't use percentage values
If you use any value other than percentages, the list items won't wrap because, unlike percentage values, they can expand the container for accommodation.
nav {
display: flex;
align-items: center;
justify-content: space-between;
border: 1px dashed black; /* for demo only */
}
nav img {
height: 60px;
}
.links {
margin: auto;
padding: 0; /* optional; remove default indentation on list elements */
border: 1px dashed red; /* for demo only */
}
nav ul li {
display: inline-block;
list-style: none;
margin: 0 1em; /* adjustment */
}
<nav>
<img src="http://lorempixel.com/output/nature-q-c-60-60-1.jpg">
<ul class="links">
<li>Link 1</li>
<li>Link 2</li>
<li>Link 2</li>
<li>Link 2</li>
</ul>
</nav>
Solution #3: Use flexbox
An initial setting of a flex container is flex-direction: row and flex-wrap: nowrap. This means that flex items will line up horizontally and cannot wrap.
nav {
display: flex;
align-items: center;
justify-content: space-between;
border: 1px dashed black; /* for demo only */
}
nav img {
height: 60px;
}
.links {
margin: auto;
padding: 0; /* optional; remove default indentation on list elements */
border: 1px dashed red; /* for demo only */
display: flex; /* new */
}
nav ul li {
display: inline-block;
list-style: none;
margin: 0 1em; /* adjustment; avoid percentage margins on flex items;
see this post:
https://stackoverflow.com/q/36783190/3597276 */
}
<nav>
<img src="http://lorempixel.com/output/nature-q-c-60-60-1.jpg">
<ul class="links">
<li>Link 1</li>
<li>Link 2</li>
<li>Link 2</li>
<li>Link 2</li>
</ul>
</nav>
Solution #4: Clean and Efficient Method
This solution attempts to use the least possible code to achieve the goal. Hope it helps.
nav { display: flex; align-items: center; }
nav img { height: 60px; }
a:first-of-type { margin-left: auto; }
a:last-of-type { margin-right: auto; }
a + a { margin-left: 1em; }
<nav>
<img src="http://lorempixel.com/output/nature-q-c-60-60-1.jpg">
Link 1
Link 2
Link 2
Link 2
</nav>
Simply add display: flex to the links, and then, as using percent for margins on flex items doesn't render the same cross browser, use i.e. viewport units instead.
nav img {
height: 60px;
}
nav {
display: flex;
align-items: center;
}
.links {
display: flex;
margin: auto;
}
nav ul li {
list-style: none;
margin: 0 2vw;
}
<nav>
<img src="http://lorempixel.com/output/nature-q-c-60-60-1.jpg">
<ul class="links">
<li>Link 1</li>
<li>Link 2</li>
<li>Link 2</li>
<li>Link 2</li>
</ul>
</nav>
This question already has an answer here:
Keep one element centered between two elements of different widths in flexbox
(1 answer)
Closed 6 years ago.
For an odd number of flex items I want the middle one to be in perfect center and other items just flow around it. The middle item has fixed width, all the rest are fluid and must stick to the middle item so the paddings are fixed.
/* CSS */
.flex-holder {
display: flex;
justify-content: center;
}
.middle-item {
width: 75px;
}
<!-- HTML -->
<ul class="flex-holder">
<li>Item 1</li>
<li>Some item</li>
<li class="middle-item">Middle</li>
<li>Very long text item</li>
<li>Test</li>
</ul>
Is it actually possible with flexbox? If no, please suggest another solution.
One solution would be to use position: absolute on middle element and center it with transform: translate() but there will be overflow of elements on small window size which you can fix with media queries.
.flex-holder {
display: flex;
justify-content: space-around;
position: relative;
list-style: none;
padding: 0;
}
.middle-item {
width: 75px;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
<ul class="flex-holder">
<li>Item 1</li>
<li>Some item</li>
<li class="middle-item">Middle</li>
<li>Very long text item</li>
<li>Test</li>
</ul>
Another solution that will get result close to desired result is to wrap li's left and right of middle li in ul's and set flex: 1 on them so they take equal size and set middle div always in center.
ul, .wrap {
display: flex;
justify-content: space-around;
position: relative;
list-style: none;
flex: 1;
padding: 0;
}
.middle-item {
width: 75px;
background: lightblue;
text-align: center;
}
<ul class="flex-holder">
<li class="wrap">
<ul>
<li>Item 1</li>
<li>Some item</li>
</ul>
</li>
<li class="middle-item">Middle</li>
<li class="wrap">
<ul>
<li>Very long text item</li>
<li>Test</li>
</ul>
</li>
</ul>
The simpliest way if the middle-item is in the middle (same number of items at rigth and left):
.flex-holder {
display: flex;
justify-content: center;
list-style: none;
padding:0;
}
.flex-holder li {
flex: 1;
border: 1px solid red;
}
li.middle-item {
flex: 0 0 100px;
background-color: #ccc;
}
<ul class="flex-holder">
<li>Item 1</li>
<li>Some text</li>
<li class="middle-item">Middle</li>
<li>Very long text item bla bla bla bla bla bla.</li>
<li>Test</li>
</ul>
Also you can force to the middle nesting elements. For example:
body {
background: url(http://placehold.it/1x200) no-repeat center;
}
.flex-holder {
display: flex;
list-style: none;
padding: 0;
}
.flex-holder li {
display: flex;
flex: 1;
border: 1px solid red;
justify-content: flex-end;
padding: 0 1em;
}
.flex-holder li div {
border: 1px solid green;
padding: 0 1em;
}
li.middle-item {
flex: 0 0 auto;
background-color: #ccc;
text-align: center;
justify-content: center;
}
li.middle-item ~ li {
justify-content: flex-start;
}
<ul class="flex-holder">
<li>
<div>Item 1 </div>
<div> Some item</div>
</li>
<li class="middle-item">Middle</li>
<li>
<div>
Very long text item </div>
</li>
</ul>