Vertically center UL and horizontally align LI children - html

I want my UL to do the following things:
I want to have my UL vertically centered in Nav. I tried using a
wrapper with display: table; but that didn't work.
I want my LI's to be evenly spread horizontally across the width of
the UL, which I did with display: flex; just not perfectly.
And I need it to be independent from the height because that might change later on.
I have the following code:
nav {
width: 780px;
height: 50px;
text-align: center;
background-color: pink;
}
nav ul {
list-style-type: none;
display: flex;
}
nav ul li {
display: inline-block;
margin: 0 auto;
padding: 10px;
background-color: lightgreen;
}
<nav>
<ul>
<li>sample</li>
<li>sample</li>
<li>sample</li>
</ul>
</nav>
fiddle
I hope you can help me, Thanks in advance.

Just a bit of tweaking to your flexbox layout:
nav {
width: 780px;
height: 50px;
text-align: center;
background-color: pink;
}
nav ul {
height: 100%; /* take height of nav parent */
list-style-type: none;
padding-left: 0; /* remove default UL padding */
display: flex;
justify-content: space-around; /* horizontal alignment (applies to child elements) */
align-items: center; /* vertical alignment (applied to child elements) */
}
nav ul li {
/* display: inline-block; <-- not necessary */
/* margin: 0 auto; <-- not necessary */
padding: 10px;
background-color: lightgreen;
}
<nav>
<ul>
<li>sample</li>
<li>sample</li>
<li>sample</li>
</ul>
</nav>
Revised Fiddle

It can be done by using display:table & display:table-cell. Please check this updated Fiddle
nav {
width: 780px;
height: 50px;
text-align: center;
background-color: pink;
display: table;
}
nav ul {
list-style-type: none;
display: table-cell;
vertical-align: middle;
padding: 0;
}
nav ul li {
padding: 10px;
background-color: lightgreen;
width: 33.33%;
box-sizing: border-box;
float: left;
}

Related

CSS border bottom on Navigation bar

I have a navigation bar and I added a red line on the bottom when hovering any item of the list, but I want to move that red line under the header (something like "Services"), any idea how to achieve this?
I added an small sample in codepen so you can easily check the HTML and CSS code
header {
background-color: lightblue;
padding-top: 1rem;
position: sticky;
top: 0;
display: flex;
align-items: center;
justify-content: space-around;
}
header nav {
min-width: 50%;
}
header nav ul {
margin: 0;
height: 100%;
list-style: none;
padding-left: 0;
display: flex;
align-items: center;
justify-content: space-between;
}
header li:hover {
height: 100%;
border-bottom: 2px solid red;
}
<header>
<a href="/">
<p>Whatever logo</p>
</a>
<nav>
<ul>
<li>About us</li>
<li>Services</li>
<li>Pricing</li>
<li>Blog</li>
</ul>
</nav>
CONTACT
</header>
Link to check the code
You can fix the header height and also fix the height of navbar items.
Also, you had one issue where on hover li elements are moving. You can also fix that with always adding border with transparent color to the element, so the overall height of the element won't change on hover state.
Here is the fixed CSS
header {
background-color: lightblue;
position: sticky;
display: flex;
height: 60px;
align-items: center;
justify-content: space-around;
}
header nav {
min-width: 50%;
}
header nav ul {
margin: 0;
height: 100%;
list-style: none;
padding-left: 0;
display: flex;
align-items: center;
justify-content: space-between;
height: 60px;
}
header li {
display: flex;
align-items: center;
border-bottom: 2px solid transparent;
height: 60px;
}
header li:hover {
border-bottom: 2px solid red;
}
https://codepen.io/swarajgk/pen/JjZewPo?editors=1100
I think just giving height to all list elements the same as the header will work.
Like this:-
header {
background-color: lightblue;
padding-top: 1rem;
height: 3rem;
position: sticky;
top: 0;
display: flex;
align-items: center;
justify-content: space-around;
}
header nav {
min-width: 50%;
height : 100%;
}
header nav ul {
margin: 0;
height: 100%;
list-style: none;
padding-left: 0;
display: flex;
align-items: center;
justify-content: space-between;
}
header li{
height: inherit;
}
header li:hover {
border-bottom: 2px solid red;
}
<body>
<header>
<a href="/"
><p>Whatever logo</p></a>
<nav>
<ul>
<li>About us</li>
<li>Services</li>
<li>Pricing</li>
<li>Blog</li>
</ul>
</nav>
CONTACT
</header>
</body>
Hope this solves the issue.
header {
background-color: lightblue;
padding-top: 1rem;
height: 3rem;
position: sticky;
top: 0;
display: flex;
align-items: center;
justify-content: space-around;
}
header nav {
min-width: 50%;
height : 100%;
}
header nav ul {
margin: 0;
height: 100%;
list-style: none;
padding-left: 0;
display: flex;
align-items: center;
justify-content: space-between;
}
header li{
height: inherit;
}
header li:hover {
border-bottom: 2px solid red;
}
I'd suggest the following approach, with explanatory comments in the CSS:
/* removing default padding and margin from all
elements, and forcing the browser to use the
same sizing algorithm - border-box - to calculate
element sizes, including the padding and border
widths in the declared size: */
*, ::before, ::after {
box-sizing: border-box;
padding: 0;
margin: 0;
}
/* setting common properties for the two element
groups: */
header,
header nav ul {
/* using display: flex layout: */
display: flex;
/* forcing the flex-items within the flex parent
to take the full height of that parent: */
align-items: stretch;
}
header {
background-color: lightblue;
block-size: 3em;
position: sticky;
justify-content: space-around;
}
/* using :is() to combine the two selectors
header a,
header li
into one selector: */
header :is(a, li) {
/* using grid layout: */
display: grid;
/* positioning the - including text - content
at the center of the element: */
place-items: center;
}
header nav {
min-width: 50%;
}
header nav ul {
/* the <ul> isn't a flex-item so we have to specify
that we want it to take all available space on
the block-axis (equivalent to 'height' in left-to-right
languages such as English): */
block-size: 100%;
list-style: none;
justify-content: space-between;
}
header li {
/* to prevent the jumping content: */
border-bottom: 2px solid transparent;
}
header li:hover {
/* to style the color of the bottom border: */
border-bottom-color: red;
}
<header>
<a href="/">
<p>Whatever logo</p>
</a>
<nav>
<ul>
<li>About us</li>
<li>Services</li>
<li>Pricing</li>
<li>Blog</li>
</ul>
</nav>
CONTACT
</header>
JS Fiddle demo.
References:
align-items.
display.
justify-content.
place-items.
Bibliography:
"Aligning items in a flex container," MDN.
"Basic concepts of flexbox," MDN.
"Box alignment in grid layout," MDN.

How to center an unordered list

I've tried multiple times now and I can't figure out how to place my unordered list in the middle of my div.
1: Describes how it looks like right now
2: Describes how I wish it to look like
HTML:
<div id="wrapper">
<div class="container">
<img src="flower.jpg"/>
</div>
<div class="header">
<ul>
<li>Home</li>
<li>News</li>
<li>Contact</li>
<li>About</li>
</ul>
</div>
CSS:
#wrapper {
position:absolute;
background-color: white;
width:100%;
height:100%;
top:0px;
left:0px;
}
img {
width: 100%;
height: 100%;
display: block;
}
.header {
width: 100%;
height: 100px;
background-color: green;
}
.header a {
color: black;
text-decoration: none;
margin: 50px;
padding: 10px;
font-size: 40px;
text-align: center;
}
ul {
list-style-type: none;
position: absolute;
}
li {
float: left;
}
What am I doing wrong? I've tried these in multiple elements:
position: relative/absolute
text-align: center
margin
padding
display: inline
Thanks for the help <3
You can change the styles for the ul element to match the code below:
ul {
list-style-type: none;
position: absolute;
left: 0;
right: 0;
display: flex;
justify-content: center;
}
You can achieve this with flex:
.header {
display: flex;
width: 100%;
height: 100px;
background-color: green;
justify-content: center;
}
Note: you can also change the value of justify-content. A very good explanation about flex and the different properties is this one: https://css-tricks.com/snippets/css/a-guide-to-flexbox/
ul {
display: flex;
justify-content:center;
text-align: center;
list-style-type:none;
width:80%;//depending on how wide you want it and note justify center wont work
unless you specify width on most cases
}
You can do that using flex, like this:
ul {
display: flex;
flex-direction: row;
justify-content: center;
list-style-type:none;
}
You can also try space-around value for justify-content property, and items will have space before, between, and after them.
Here is the working example: https://jsfiddle.net/tLc9zmoy/26/

Stretch items elements height in a Flexbox nav with fixed height

I have a navigation, with fixed height, that use the flexbox layout module. It have two items (ul elements) where in one I want that its li tags take all the height of the nav and the other one I want that its li tags behave normally. I tought that assigning display:block to the li tags that I want they take all the height of the nav would work, but it behaves as a display:inline-block.
nav {
display: flex;
justify-content: space-between;
align-items: center;
background-color: #000;
height: 65px;
}
nav ul {
list-style-type: none;
padding-left: 0;
}
nav ul li {
float: left;
}
nav ul.item1 li {
display: block;
background-color: red;
}
nav ul.item2 li {
display: inline-block;
background-color: green;
}
<nav>
<ul class="item1">
<li>#1</li>
<li>#2</li>
<li>#3</li>
</ul>
<ul class="item2">
<li>#4</li>
<li>#5</li>
<li>#6</li>
</ul>
</nav>
Short answer is to use nested flexbox.
Remove align-items: center; from nav, so that flex items can stretch (default behavior) to the same height as the container.
Reset the margin by adding ul { margin: 0; }, so that no top and bottom margins.
Remove all the float and inline-block, you don't need it in flexbox layout.
Apply display: flex; to all - nav, ul, and li.
Finally add align-items: center; to the li to center the text vertically.
nav {
display: flex;
justify-content: space-between;
background-color: black;
height: 65px;
}
nav ul {
list-style: none;
padding: 0;
margin: 0;
display: flex;
}
nav li {
display: flex;
align-items: center;
}
nav ul.item1 li {
background-color: red;
}
nav ul.item2 li {
background-color: green;
}
<nav>
<ul class="item1">
<li>#1</li>
<li>#2</li>
<li>#3</li>
</ul>
<ul class="item2">
<li>#4</li>
<li>#5</li>
<li>#6</li>
</ul>
</nav>
Update
Modified version for just the left side fully stretches to height, and the right side behaves as inline elements.
nav {
display: flex;
justify-content: space-between;
background-color: black;
height: 65px;
}
nav ul {
list-style: none;
padding: 0;
margin: 0;
display: flex;
}
nav li {
display: flex;
}
nav ul.item1 li {
align-items: center;
background-color: red;
}
nav ul.item2 {
align-items: center;
}
nav ul.item2 li {
background-color: green;
}
<nav>
<ul class="item1">
<li>#1</li>
<li>#2</li>
<li>#3</li>
</ul>
<ul class="item2">
<li>#4</li>
<li>#5</li>
<li>#6</li>
</ul>
</nav>
Just add height: 100% to both the ul and li.
nav {
display: flex;
justify-content: space-between;
align-items: center;
background-color: #000;
height: 65px;
}
nav ul {
list-style-type: none;
padding-left: 0;
height: 100%;
display: flex;
align-items: center;
}
nav ul li {
float: left;
display: flex;
align-items: center;
}
nav ul.item1 li {
background-color: red;
height: 100%;
}
nav ul.item2 li {
background-color: green;
}
<nav>
<ul class="item1">
<li>#1</li>
<li>#2</li>
<li>#3</li>
</ul>
<ul class="item2">
<li>#4</li>
<li>#5</li>
<li>#6</li>
</ul>
</nav>

List exceeds width of parent container

I want to build a navigation in the header containing three items where the first two ones are aligned left and the third one is aligned right. Tried it by use of flexbox but there is an arror: The ul is exceeding the width of it's parent container.
header {
width: 100%;
background: #417690;
margin-left: 10px;
margin-right: 10px;
font-size: 20px;
height: 70px;
}
header ul {
height: 100%;
width: 100%;
display: flex;
flex-direction: row;
align-items: center;
/* justify-content: center; */
}
header ul li {
display: inline-block;
padding-right: 15px;
margin-left: 10px;
}
.filler {
flex-grow: 1;
}
<header>
<ul>
<li>Logo</li>
<li>New article</li>
<li class="filler"></li>
<li>username</li>
</ul>
</header>
How can I fix this?
Tested in FF and Opera.
Reset margin to zero and add box-sizing: border-box to all elements to include the padding in the size calculations. You may also reset the padding for the ul element - see demo below:
* { /* ADDED */
box-sizing: border-box;
}
header {
width: 100%;
background: #417690;
/*margin-left: 10px;
margin-right: 10px;*/
font-size: 20px;
height: 70px;
}
header ul {
height: 100%;
width: 100%;
display: flex;
flex-direction: row;
align-items: center;
/* justify-content: center; */
padding: 0; /* ADDED */
}
header ul li {
display: inline-block;
padding-right: 15px;
margin-left: 10px;
}
.filler {
flex-grow: 1;
}
<header>
<ul>
<li>Logo</li>
<li>New article</li>
<li class="filler"></li>
<li>username</li>
</ul>
</header>
Try this:
header ul {
box-sizing: border-box;
padding: 0;
}

On hover, li items should take full height of the container

I'd like to make the li elements tall as the height of the header.
CodePen
*,
::before,
::after {
border-box: box-sizing;
margin: 0; padding: 0;
}
header {
display: flex;
flex-flow: row wrap;
justify-content: space-between;
align-items: center;
background: yellow;
height: 7.5vh;
}
.navigation li {
display: inline-block;
padding: 0 1em;
}
.navigation li:hover {
text-align: center;
background-color: white;
}
<header>
<h1>Logo</h1>
<nav>
<ul class="navigation">
<li>Home</li>
<li>About</li>
<li>Products</li>
<li>Contact</li>
</ul>
</nav>
</header>
One way to achieve this is to utilize the line-height property and make it the same as the height you defined for your <header>:
.navigation li:hover {
text-align: center;
background-color: white;
line-height: 7.5vh;
}
Here's an updated CodePen. Hope this helps! Let me know if you have any questions.
Add display:block in .navigation li:hover.