I am trying to style - on one line - a group of buttons on the left, a navigation list in the middle, and a group of buttons on the right. I have grouped the navigation buttons for when the layout should change. Question is how to get the navigation structure on the same line in the center of the parent element?
I have made both overarching div elements into "display: inline" elements, and also the navigation.
Do I need to use absolute positioning of the nav for this to work? Why?
How can I center the nav horizontally?
My HTML:
// you need to have font smoothing on to avoid blurred and jagged lines
html{
background-color: rgb(235, 235, 235);
}
#main_body{
width: 1200px;
margin: auto;
background-color: white;
}
// first line header styling
#header_topnav{
width: 96%;
height: fit-content;
}
// button div, navigation and button div
.topnav_button{
width: 45px;
height: 35px;
margin-top: 18px;
margin-bottom: 10px;
}
// make div inline element to get it on one line
#left_buttons{
display: inline;
position: relative;
}
// make div inline element to get it on one line
// no other way than to go with left or margin
#right_buttons{
display: inline;
position: relative;
margin-left: 87.5%;
// left: 86.5%;
}
// vertical centering
ul {
margin: auto;
}
// for horizontal nav menu
li {
display: inline;
float: left;
margin-left: 10px;
}
// display block so clickable area is larger
li a {
display: block;
}
// how do you center this horizontally?
// do I have to make position absolute? can't I keep it in between the button sections?
#top_navmenu {
position: absolute;
display: inline;
margin-top: 28px;
}
<div id="main_body">
<header>
<section id="header_topnav">
<div id="left_buttons">
<button class="topnav_button"></button>
<button class="topnav_button"></button>
</div>
<nav id="top_navmenu">
<ul>
<li><a>F+</a></li>
<li><a>POLITIK</a></li>
</ul>
</nav>
<div id="right_buttons">
<button class="topnav_button"></button>
</div>
</section>
</header>
</div>
You don't need to use position: absolute. You can achieve this with flexbox.
Just add display:flex on the wrapper ( #header_topnav ) and flex-grow: 1 on the middle menu. This way the menu will occupy all the available space between the left and right buttons.
Also when sharing code here on SO please be sure you share valid code.
HTML code is missing some closing tags
// is not a valid comment in CSS. Use /* comment */ instead.
See below
html {
background-color: rgb(235, 235, 235);
}
#main_body {
width: 100%;
margin: auto;
background-color: white;
}
#header_topnav {
height: fit-content;
display: flex;
flex-wrap: wrap;
flex-direction: row;
}
.topnav_button {
width: 45px;
height: 35px;
margin-top: 18px;
margin-bottom: 10px;
}
#left_buttons {
display: inline;
position: relative;
}
#right_buttons {
position: relative;
}
ul {
margin: auto;
display: flex;
flex-direction: row;
}
li {
margin-left: 10px;
}
li a {
display: block;
}
#top_navmenu {
margin-top: 28px;
flex-grow: 1;
display: flex;
align-items: center;
}
<div id="main_body">
<header>
<section id="header_topnav">
<div id="left_buttons">
<button class="topnav_button"></button>
<button class="topnav_button"></button>
</div>
<nav id="top_navmenu">
<ul>
<li><a>F+</a></li>
<li><a>POLITIK</a></li>
</ul>
</nav>
<div id="right_buttons">
<button class="topnav_button"></button>
</div>
</section>
</header>
</div>
Related
Building out a navbar that will look something like this:
|----------------------------------------------------------|
| link Logo link link |
|----------------------------------------------------------|
My thought process for creating this layout is to have a html structure that looks like:
<nav>
<div></div>
<div>
link
logo
link
</div>
<div>
link
</div>
</nav>
and then with CSS, I would do something like:
display: grid;
grid-template-columns: 200px auto 200px;
...
My question here is: is there a better way to recreate this layout? I don't like how I use an empty div to create the space.
I know I can remove the empty div and put something like margin-left: 200px on the 2nd div but that seems kinda hacky as well.
Appreciate the input.
From the comments from the original question, I was able to find the grid-column-start property and that was exactly what I needed. I appreciate everyone commenting but I feel like the ones saying to use a library/frameworks to build a navbar is overkill. Knowing how to actually build these layouts are what makes you a better developer.
This is what I ended up doing:
<div class="navbar">
<div class="navbar--content">
<div class="navbar--content--middle">
<div class='row row__align-center row__center'>
shop now
logo
FAQ
</div>
</div>
<div class="navbar--content--right">
user img
bag
</div>
</div>
</div>
And the css:
.navbar {
&--content {
padding: 20px 0;
display: grid;
grid-template-columns: 200px auto 200px;
align-items: center;
&--middle {
grid-column-start: 2;
a {
width: 100px;
text-decoration: none;
font-weight: 600;
&:first-child {
margin-right: 100px;
}
&:nth-child(2) {
display: flex;
flex-flow: column nowrap;
justify-content: center;
}
&:last-child {
margin-left: 100px;
}
}
}
&--right {
text-align: right;
a {
&:first-child img {
height: 30px;
margin-right: 10px;
}
&:last-child img {
height: 35px;
}
}
}
}
}
This is a tricky design. You have to use multiple concept of CSS to achieve this design for example pseudo and position absolute will help you. You can check with other framework but again as per your design you need to write custom CSS as per limitation. I have written optimized CSS & markup of this design for you using pseudo elements and "position:absolute" for the fourth div. Please try code (you can change width of nav as per your requirement) and let me know if you need any more information or have any queries. Thanks in advance.
nav {
width: 100%;
max-width: 600px;
margin: 0 auto;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
position: relative;
border-top: .05em #000 dashed;
border-bottom: .05em #000 dashed;
}
nav .lft-rgt-seperator {
position: absolute;
width: 103%;
height: 14px;
border-top:4px solid #fff;
border-bottom:4px solid #fff;
top: 50%;
-webkit-transform: translateY(-50%);
transform: translateY(-50%);
z-index: 2;
}
nav:before {
content:"";
width:.05em;
height: 49px;
position: absolute;
top: -6px;
left: -4px;
background: #000;
}
nav:after {
content:"";
width:.05em;
height: 49px;
position: absolute;
top:-6px;
right:-4px;
background: #000;
}
nav ul {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
width: 100%;
z-index: 4;
}
nav ul li {
margin: 8px 15px;
}
nav ul li a, nav .lftlink a {
color: #000;
text-decoration: none;
font-size:18px;
cursor: pointer
}
nav ul li a:hover, nav .lftlink a:hover {
text-decoration: underline;
}
nav .lftlink {
position: absolute;
right:20px;
top: 50%;
-webkit-transform: translateY(-50%);
transform: translateY(-50%);
z-index: 5;
}
<nav>
<div class="lft-rgt-seperator">
</div>
<ul>
<li>
Link
</li>
<li>
Logo
</li>
<li>
Link
</li>
</ul>
<div class="lftlink">
Link
</div>
</nav>
Here's a basic implementation based on your code. It's basically a combination of CSS Grid Layout and Flexible Box Layout.
Inside the main <nav> container use grid-template-columns to distribute the available width using the fr unit. Then use flexbox to layout the content inside each of the <div> containers:
nav {
display: grid;
grid-template-columns: 2fr 1fr;
}
.links-and-logo,
.just-link {
display: flex;
justify-content: flex-end;
}
<nav>
<div class="links-and-logo">
Link
<img src="https://source.unsplash.com/100x100/?technology" alt="Nature">
Link
</div>
<div class="just-link">
Link
</div>
</nav>
I'm trying to align all navigation links, besides the logo, to the right side of the container/navigation. I want to keep 1rem margin on both sides so that the content has some space to breathe.
I've tried using the code below but nothing on the page changes:
.menu:not(:first-child){
text-align: right;
}
<body>
<div class="body-wrap">
<header class="header">
<nav role="navigation">
<ul class="menu">
<li class="home-link"><img src="https://www.nicolefenton.com/_/images/dec/circle-menu.svg" height="12" width="12" alt=""></li>
<li>About</li>
<li>Writing</li>
<li>Speaking</li>
<li>Projects</li>
</ul>
</nav>
</header>
</div>
</body>
* { box-sizing: inherit; margin: 0; padding: 0; }
body {
position: relative;
line-height: 1.5em;
min-width: 320px;
margin: 0 auto;
color: #222222;
border: 30px solid #ffffff;
background-color: #f8f7f3;
}
.body-wrap {
display: flex;
min-height: 100vh;
display: box;
}
.header {
width: 100%;
max-width: 960px;
margin-right: 1rem;
margin-left: 1rem;
}
.menu {
display: flex;
position: absolute;
top: -0.83rem;
width: 100%;
max-width: 960px;
}
.menu:not(:first-child){
text-align: right;
}
li {
flex-grow: 1;
position: relative;
margin-right: 1em;
display: inline-block;
}
I expect all the nav links to align to the right when using the :not(:first-child) selector.
This:
.menu:not(:first-child)
selects class menu items that aren't a first child.
What you want is:
.menu :not(:first-child)
which selects non-first-child elements within a .menu class.
Notice the space.
Or better yet, make it more obvious what you really mean:
.menu li:not(:first-child)
You might just have to change to this if all you are looking to do is align the text to the right.
.menu li:not(:first-child){
text-align: right;
}
This is my code and tried everything I could think of to place my image in the top middle and links on the top right corner.
Whatever I try doesn't align them in the same div and makes things wacky.
Here is my code:
#header img{
display: block;
margin: 0 auto;
width: 150px;
height: 90px;
}
.login a{
float: right;
text-decoration: none;
font-size: 18px;
padding: 10px;
}
<div id="header">
<img src="img/raystratos.png"/>
<div class="login">
Sign Up
Log In
Shopping Cart
</div>
</div>
Try absolute positioning:
#header { position: relative; }
.login { position: absolute; top: 0; right: 0;}
You can use flex to do this and also if you want to divide this row into 3 equal width columns you add another div inside the container and then add flex:1 property to each child element inside the #header.
#header {
display: flex;
justify-content: space-between;
}
#header img{
display: block;
margin: 0 auto;
width: 150px;
height: 90px;
flex: 1;
}
.equalFlex {
flex: 1;
}
.login a{
text-decoration: none;
font-size: 18px;
padding: 10px;
flex: 1;
}
.login{
flex: 1;
}
<div id="header">
<div class="equalFlex"></div>
<img src="img/raystratos.png"/>
<div class="login">
Sign Up
Log In
Shopping Cart
</div>
</div>
I have created a header with one div as a main menu of website and added into it some divs as main menu items. My question is: how to center vertically and horizontally inner divs which are headers of main menu placed in main menu items? I have tried many solutions like transformations and flex style of display but unfortunately nothing works. Why there is not something like Horizontal / VerticalAlignment from XAML in CSS?
body {
margin: 0;
}
header {
height: 50px;
background-color: lightgrey;
}
#main-menu {
margin: 0 auto;
width: 1000px;
height: inherit;
}
.main-menu-item {
float: left;
width: 100px;
height: inherit;
}
.main-menu-header {
display: block;
height: inherit;
}
.main-submenu {
width: inherit;
word-wrap: break-word;
/*display: none;*/
list-style: none;
margin-left: -40px;
margin-top: 0px;
}
<body>
<header>
<div id="main-menu">
<div class="main-menu-item" onmouseover="ChangeDisplayOfSelectedSubmenu(0, 'block')" onmouseout="ChangeDisplayOfSelectedSubmenu(0, 'none')">
<div class="main-menu-header">MenuItem1</div>
<ul class="main-submenu">
<li>SubMenuItem1</li>
<li>SubMenuItem2</li>
<li>SubMenuItem3</li>
</ul>
</div>
<div class="main-menu-item" onmouseover="ChangeDisplayOfSelectedSubmenu(1, 'block')" onmouseout="ChangeDisplayOfSelectedSubmenu(1, 'none')">
<div class="main-menu-header">MenuItem2</div>
<ul class="main-submenu">
<li>SubMenuItem1</li>
<li>SubMenuItem2</li>
<li>SubMenuItem3</li>
</ul>
</div>
<div class="main-menu-item" onmouseover="ChangeDisplayOfSelectedSubmenu(2, 'block')" onmouseout="ChangeDisplayOfSelectedSubmenu(2, 'none')">
<div class="main-menu-header">MenuItem3</div>
<ul class="main-submenu">
<li>SubMenuItem1</li>
<li>SubMenuItem2</li>
<li>SubMenuItem3</li>
</ul>
</div>
</div>
</header>
Use the padding top and padding bottom simply?
Try the CSS line-height Property Follor this : https://www.w3schools.com/cssref/pr_dim_line-height.asp
You can use a css old trick, use this:
header{
height:50px;
display:block;
}
#main-menu{
position:aboslute;
top:50px;
margin-top:-25px;
}
Change your CSS to the following -
body {
margin: 0;
}
header {
height: 50px;
background-color: lightgrey;
}
#main-menu {
height: inherit;
display: flex;
align-items: center;
align-content: center;
justify-content: center;
}
.main-menu-item {
float: left;
width: 100px;
/* height: 100%; */
text-align: center;
}
.main-menu-header {
display: block;
height: inherit;
}
.main-submenu {
width: inherit;
word-wrap: break-word;
/*display: none;*/
list-style: none;
margin-left: -40px;
margin-top: 0px;
}
Using flexbox property here to achieve the desired effect
Practicing on anchor tags and drop down menu. In the following code, the dropdown is not working. Don't know why. The div containing text "This is dropdown menu" should appear exactly below the div containing text "This is text. Its in center" whenever the later is hovered upon. Both the divs are of same width.
html,body {
margin: 0px;
height: 100%;
/* [disabled]width: 100%; */
left: 0px;
top: 0px;
background-color: rgba(255,255,255,1);
}
.wrapper {
text-align: center;
margin-top: 0;
margin-left: auto;
height: 100%;
max-width: 960px;
background-color: rgba(0,0,0,1);
margin-right: auto;
position: relative;
}
.link1 {
height: auto;
width: 50%;
color: rgba(255,255,255,1);
margin-right: auto;
margin-left: auto;
background-color: rgba(204,204,204,1);
}
.link1 a {
text-decoration: none;
display: block;
}
.link1 a:hover {
text-decoration: underline;
background-color: rgba(255,0,0,1);
}
.link1 a:hover .dropdown {
display: block;
}
.dropdown
{
height: 25%;
width: 50%;
background-color: rgba(204,204,204,1);
margin-right: auto;
margin-left: auto;
text-align: center;
display: none;
}
<div class="wrapper">
<div class="link1">
This is text. Its in center
</div>
<div class="dropdown">This is dropdown menu</div>
</div>
Your css selector .link1 a:hover .dropdown selects the element with the class dropdown which has to be inside of an a element in a hover state (a:hover), which is inside an element with a class of link1.
This doesn't match your html markup.
To get it work, you can change your html to this:
<div class="wrapper">
<div class="link1">
<a href="http://www.hotmail.com">
This is text. Its in center
<div class="dropdown">This is dropdown menu</div>
</a>
</div>
</div>
Hope it helped.
Lexith is partly right, you need to add the dropdown within the container div, you can then select the sibling of the hovered a link.
Like so;
CSS -
.link1 a:hover + .dropdown {
display: block;
}
HTML -
<div class="link1">
This is text. Its in center
<div class="dropdown">This is dropdown menu</div>
</div>
CSS update -
This allows the dropdown to stay open when hovering on it
.dropdown:hover,
.link1 a:hover + .dropdown {
display: block;
}
This means it doesnt have any of the a tag styling. View my code pen