I have a submenu underneath a menu that has the property display: flex, and the list items have the property flex-grow: 1
I would like to align the submenu so that the links are aligned with the parent like so:
This is working because I gave the submenu the property left: 19px. This works but the problem is that since the menu and its items are displayed flex, when the browser shrinks the width of the list item shrinks with it, so the submenu does not get aligned. Below is a screenshot when the browser shrunk 200px:
Is there a css class or anything I can do to have the submenu links align with the parent links on browser shrink? I could technically make a ton of media queries and change the left: but I thought I would ask if anyone has a better solution.
Here is my code. I stripped out alot but left the code that seemed necessary for this question.
#menu-main-menu {
display: flex;
}
#menu-main-menu li {
float: left;
flex-grow: 1;
text-align: center;
position: relative;
}
#menu-main-menu li a {
display: inline-block;
padding: 40.5px 0;
}
#menu-main-menu .menu-item-has-children .sub-menu {
position: absolute;
left: 19px;
}
<ul id="menu-main-menu">
<li class="menu-item-has-children">
Services
<ul class="sub-menu">
<li>Child Page</li>
<li>Child Page</li>
<li>Child Page</li>
</ul>
</li>
<li>Blog</li>
<li>Contact Us</li>
</ul>
The problem you describe in your question cannot be reproduced with the code you provided. However, based on your explanation, here are two things to consider:
An initial value of a flex container is flex-shrink: 1. This means that flex items are allowed to shrink in order to fit inside the container (preventing overflow). In order to disable shrinking, add flex-shrink: 0 to flex items.
Floats are ignored in a flex container.
Also, as general guidance, consider these rules, as well:
Absolutely positioned flex items do not participate in flex layout.
A flex item cannot, by default, shrink past the size of its content.
One of the factors above may be causing, or at least contributing, to your problem.
Related
I have a navigation column on the left side of the window and I need to position the last navigation item at the bottom of the column. However, I need that item also move up to its normal position below the second to last list item if the window is resized and the height decreases.
I'm using React and Material-UI's List and ListItem components to create this navigation column. They render as a <ul> with <li> tags inside.
I've tried using position: fixed, bottom: 0 on the last <li> tag which positions it correctly at the bottom, but when the window is resized, it overlaps the other list items.
I've also tried setting the <ul> to display: flex, flex-direction: column and then setting the last <li> margin-top to some value...but I really don't want to set a value for this because it's supposed to be responsive.
This is as close as I've made it - CodeSandbox. What CSS can I use to make the last list item at the bottom and move it up when the screen/window is resized?
You're almost there with flex. Use margin-top:auto on the last <li>:
html {height:100%}
body {
width: 50%;
height: 100%;
}
ul {
height:100%;
margin: 0;
padding: 0;
list-style-type: none;
display: flex;
flex-direction: column;
}
li {
border: solid;
padding: 0.5rem;
}
li:last-of-type {margin-top:auto}
<ul>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li class="right">THIS ONE FLEX END</li>
</ul>
I am learning css these days. I am designing a navbar by using css flexbox. Here is my html and css code, but they are not working on my browser.
Can anybody find any problem?
* {
margin: 0px;
padding: 0px;
}
/* Navigation Bar */
#navbar {
display: flex;
align-items: center;
flex-direction: row;
top: 0px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Website Page</title>
<link rel="stylesheet" href="/originals/style.css">
</head>
<body>
<nav id="navbar">
<div id="logo">
<img src="logo.png" alt="MyOnlineMeal.com">
</div>
<ul>
<li class="item">Home</li>
<li class="item">Services</li>
<li class="item">Our Clients</li>
<li class="item">Contact Us</li>
</ul>
</nav>
</body>
</html>
The display: flex property only applies to the direct children elements within the flex container. I'm guessing that you want the list items to also be "flexed" so in order to do that - you need to apply display flex to the ul as well as the nav.
In other words - the nav bar applies display flex to ONLY the div containing the image image and the ul. In order to align and space out the list items - the ul needs to also be a flex container. I am using space-around to space out the list items - but obviously you might need to alter the styling to suit your needs.
*{
margin: 0px;
padding: 0px;
}
/* Navigation Bar */
#navbar{
display: flex;
align-items: center;
flex-direction: row;
top: 0px;
}
#navbar ul{
display: flex;
align-items: center;
flex-direction: row;
top: 0px;
list-style: none;
flex-grow: 1;
justify-content: space-between;
margin-left: 32px
}
<nav id="navbar">
<div id="logo">
<img src="logo.png" alt="MyOnlineMeal.com">
</div>
<ul>
<li class="item">Home</li>
<li class="item">Services</li>
<li class="item">Our Clients</li>
<li class="item">Contact Us</li>
</ul>
</nav>
I am not sure what you are trying to achieve, I suppose you need all items in the navbar evenly distributed on a horizontal line on top of the page. If that is what you need, a few indications:
The main problem is that display: flex will distribute only the immediate children of the box with that property. In your case it means that your flex items are the logo div and the ul as a whole, and it will not distribute the items inside the ul. To achieve the latter effect, you would also need to set the ul display to flex.
You are using the align-items property to configure flex items alignment, but this property aligns items in the direction opposite to the flex direction. As your flex direction is row, align-items: center aligns them in center vertically, from top to bottom. You won't notice its effects here because your container by default has the same height as its content, so items can't be assigned different vertical positions. But if you specify a larger height for your flex container, you will notice that all flex items will appear in the middle of the flex container's height; that could be useful in the outer flex container to align the ul items in the middle of the logo's height.
You should try the property justify-content to align your flex items in the same direction of your flex container, in this case horizontally. Try checking different values for this property, like space-around or space-evenly to achieve the distribution you need.
The top property is not needed here, unless you use it with a positioned element. You need to use it together with some value for the position property.
A CSS flexbox handles the row and column alignment of direct children elements to the parent in which flexbox has been applied. For Example, In your code:
<nav id="navbar"> is the parent which contains direct children elements, <div id="logo"> and <ul>, anything inside <div id="logo"> and <ul> are not the direct children to <nav id="navbar">. So, if you observe the <div> containing logo and the <ul> containing list of links are aligned horizontally beside each other due to #navbar ul{ display: flex;}
In order to make your list of links appear beside each other horizontally much alike your logo and list, you will need to give <ul> element display flex because <ul> acts as the direct parent element to <li> elements ; and since default value of flex-direction is row you may or may not set the value for it, as you like.
Hope this helps clarifying your concepts. Keep Learning!
#navbar{
display: flex;
justify-content: space-between;
align-items: center;
}
#navbar > ul{
display: flex;
justify-content: space-between;
align-items: center;
}
#navbar > ul > li{
margin-right: 0.875rem;
list-style-type: none;
}
<nav id="navbar">
<div id="logo">
<img src="logo.png" alt="MyOnlineMeal.com">
</div>
<ul>
<li class="item">Home</li>
<li class="item">Services</li>
<li class="item">Our Clients</li>
<li class="item">Contact Us</li>
</ul>
</nav>
This question already has answers here:
Float:right reverses order of spans
(16 answers)
Closed 6 years ago.
So I've run into this problem a few times, how come my navigation menu is reversed?
.navigation li a {
display: inline-block;
text-decoration: none;
float: right;
margin-right: 10px;
}
ul {
list-style-type: none;
}
<div class="container-fluid">
<nav class="navigation">
<ul>
<li>About</li>
<li>Portfolio</li>
<li>Contact</li>
</ul>
</nav>
</div>
When put into action, the menu order is reversed, why is this happening?
You let the elements float to the right. Try to picture that..
The first element enters the document and floats all the way to the right, bumping into the side of the screen. The second enters and floats to the right as well, but bumps into the left side of the first, and stays there. And so on, and so on.
A better solution would be to use display: inline-block for the elements, and float-right for the parent (the ul).
But personally I'm not a big fan of floating at all, so I would use text-align on the ul. text-align keeps it a normal line of text, which can also include images or other inline and inline-block elements. By right-aligning the text, the order of the words is not changed, but any remaining white space is just added to the left instead of to the right of the line:
.navigation li a {
display: inline-block;
text-decoration: none;
float: right;
margin-right: 10px;
}
.navigation li {
display: inline-block;
}
.navigation ul {
text-align: right;
}
<div class="container-fluid">
<nav class="navigation">
<ul>
<li>About
</li>
<li>Portfolio
</li>
<li>Contact
</li>
</ul>
</nav>
This is happening because that's how float was designed. It will "float" the elements in the direction specified, in the order specified. If order is important, you can fix this in three ways:
Use the built-in Bootstrap alignment tools.
Apply float: right to the parent <ul> rather than each link.
Reverse the order of the elements.
In this case, you are floating elements to the right, in the order About > Portfolio > Contact. This is what happens:
About is floated right with no previous elements, so it sits against the farthest right wall of the parent container, <ul>.
Portfolio is floated right, but About is there already, so it gets as far right as it can, which puts it to the left of the previous element.
Contact is last to the party, so it ends up at the end of the line, farthest left.
I'm trying to work with grids which are whole numbers, that perfectly match up, e.g 20% for 5 menu items would fill 100%.
I have the following code:
#menu-primary-navigation li{display:inline-block;font-size:0;width:20%;}
#menu-primary-navigation li a{font-size:22px;}
I understand the issue of whitespace between ul li elements that means 20% elements will not fit into 100% due to the white space in between each element. However I thought I had got around this issue by making font-size:0; where the elements sit and then only setting the font size inside the element.
Yet you can see in my JSFiddle that the five menu items still do not fit perfectly to 100% of the container.
In my example, the width is 600px and each element is 20%. I can see from inspecting the elements that they are all equal to 120px. Well 120 x 5 = 600, so why does the last element always fall to the next line?
<div class="wrapper">
<ul id="menu-primary-navigation" class="menu">
<li class="menu-item">
Home
</li>
<li class="menu-item">
Tutorials
</li>
<li class="menu-item">
<a>Logo</a>
</li>
<li class="menu-item">
Projects
</li>
<li class="menu-item">
Articles
</li>
</ul>
</div>
http://jsfiddle.net/franhaselden/kq9o4t0v/
Using display: inline-block; is notoriously problematic in this situation. You could consider using display: table-cell; achieve the same result with less hassle.
HTML can remain the same, but try this CSS:
.wrapper{width:600px;}
ul,li{padding:0;margin:0;}
/* needed for use with display: table-cell; */
.menu{ display: table; width: 100%; }
/* changed to table-cell */
#menu-primary-navigation li{display:table-cell; text-align: center;}
#menu-primary-navigation li a{font-size:22px;}
However as I am supposed to be answering the question the part you went wrong is you need to set the font size on the parent i.e the ul in order to effect the white-space. Do note however, I think certain versions of IE will not like font-size: 0;
CSS:
.wrapper{width:600px;}
/* you need it set on the parent */
ul,li{padding:0;margin:0; font-size: 0; }
#menu-primary-navigation li{display: inline-block; width: 20%; text-align: center;}
#menu-primary-navigation li a{font-size:22px;}
You are setting font-size:0 on the li tag to remove whitespace. However the li's are contained in the ul, so you need to set the font-size there.
In your jsfiddle the issue is resolved by setting
.wrapper{width:600px;}
ul,li{padding:0;margin:0;font-size:0}
I'm creating a pure-CSS hover dropdown menu, based on a very basic idea idea.
The HTML:
<ul id="top">
<li>
Menu item 1</li>
<li>
This one has submenu
<div class="submenu">
<ul>...</ul>
<div>
</li>
</ul>
The CSS:
div.submenu {
display: none;
position: absolute;
}
ul#top > li:hover div.submenu { display:block; }
As far as I know, this is the bare minimum to get the idea working.
The problem is I want the submenu to be multi-column, without actually using CSS3 multiple columns.
So I decided to break my submenu into multiple lists and have them float: left like this:
<ul id="top">
<li>
Menu item 1</li>
<li>
This one has submenu
<div class="submenu">
<ul>...</ul>
<ul>...</ul>
<ul>...</ul>
<div>
</li>
</ul>
...and the CSS:
div.submenu ul { float:left; }
This worked well until the point when I got a pretty big submenu in the last main menu item, producing a result like this:
The problem is it is unacceptable to have the submenu fall outside the container. I decided to mark the second half of the main menu items as class="right", and align the submenu's right border to the parent item's right border.
li.right div.submenu { right: 0; }
/* this placed the submenu to the right of the entire page;
it needs a positioning context: */
ul#top li { position:relative; }
That last line causes the <ul>'s to stop floating and just get stacked on top of each other.
Is there a way to keep them floating without setting the <div class="submenu"> to a fixed width?
Interactive demo: http://codepen.io/oli-g-sk/pen/ociet
Edit: if this helps somehow, it is allowed to set the submenu list items .submenu > ul > li to a fixed width. In fact I'm already doing it in the demo.
Try removing float:left from div.submenu ul and add these two rules:
div.submenu {
white-space: nowrap;
}
div.submenu ul {
/* float:left; <-- remove this */
display: inline-block;
}
demo: http://codepen.io/anon/pen/ApxFd