简体   繁体   中英

CSS menu bar centered with dropdown

Working on a menu bar that has counter active css classes. I need the menu bar centered and the drop downs to be under the proper list item. I can get one or the other but not both to work at the same time. The menu bar changes sizes, so putting a static margin left on it will not work. This is what the menu bar should look like but it's not centered. 在此处输入图片说明

And this is what happens when i remove the float: left from #mainmenu ul li{}. It's now centered, but the items that belong under the user name are all shifted left.

在此处输入图片说明

Why does this happen? and how do i get around it?

html:

<div id="mainmenu">
    <?php
    if(Yii::app()->user->name)
    $display_name = Yii::app()->user->name;
    if(strlen($display_name) > 11){
        $display_name = substr($display_name,0,9);
        $display_name =$display_name.'...';
    }
    ?>
    <?php $this->widget('zii.widgets.CMenu',array(
        'items'=>array(
            array('label'=>'Home', 'url'=>array('/site/index')),
            array('label'=>'My Tickets', 'url'=>array('/ticket/mytickets'), 'visible'=>!Yii::app()->user->isGuest),
            array('label'=>'About', 'url'=>array('/site/page', 'view'=>'about')),
            array('label'=>'Contact', 'url'=>array('/site/contact')),
            array('label'=>'Schools', 'url'=>array('/school'), 'visible'=>Yii::app()->user->id == 'admin'),
            array('label'=>'Teams', 'url'=>array('/team'), 'visible'=>Yii::app()->user->id == 'admin'),
            array('label'=>'Login', 'url'=>array('/site/login'), 'visible'=>Yii::app()->user->isGuest),
            array('label'=>'Games', 'url'=>array('/game'), 'visible'=>Yii::app()->user->id == 'admin'),
            array('label'=>'Users', 'url'=>array('/user'), 'visible'=>Yii::app()->user->id == 'admin'),
            array('label'=>'Tickets', 'url'=>array('/ticket'), 'visible'=>Yii::app()->user->id == 'admin'),
            array('label'=>'Team Placement', 'url'=>array('/tournamentresults'), 'visible'=>Yii::app()->user->id == 'admin'),
            array('label'=>$display_name, 'url'=>array('#'), 'visible'=>!Yii::app()->user->isGuest,
                    'items' => array(
                array('label'=>'Edit User', 'url'=>array('/company/index')),
                array('label'=>'Log-out', 'url'=>array('/site/logout'))
    ),


            ),
        ),
    )); ?>
</div><!-- mainmenu -->

Generated HTML code:

<div id="mainmenu">
   <ul id="yw0">
    <li class="active"><a href="/index.php/site/index">Home</a></li>
    <li><a href="/index.php/ticket/mytickets">My Tickets</a></li>
    <li><a href="/index.php/site/page?view=about">About</a></li>
    <li><a href="/index.php/site/contact">Contact</a></li>
    <li><a href="/index.php/site/#">SirRahal</a>
        <ul>
            <li><a href="/index.php/company/index">Edit User</a></li>
            <li><a href="/index.php/site/logout">Log-out</a></li>
        </ul>
    </li>
    </ul>    
</div>

CSS code:

 #mainmenu
{
height:33px;
margin: auto;
text-align:center;
}

#mainmenu ul li
{
display: inline;
float: left;
margin: auto;
}

#mainmenu ul li a
{
color: #fbf3e1;
font-size:14px;
padding-top:5px;
padding-bottom:5px;
width:217px;
background: #33332c;
}

#mainmenu ul li ul {
display: none;
position: absolute;
margin-left: -20px;
}

#mainmenu ul li:hover > ul {
display: block;
}

#mainmenu ul li a:hover, #mainmenu ul li.active a
{
color: #f5921e;
border-bottom: solid 5px #f5921e;
text-decoration:none;
border-bottom-right-radius: 5px;
border-bottom-left-radius: 5px;
}

The biggest key, in my opinion, to building a CSS dropdown/flyout menu is using absolute positioned elements inside relative positioned elements and where to use them. What's even more important is to understand how these two positioning schemes relate to one another. Once you do, you can build all sorts of dropdown/flyout menus.

You will want to set position: relative to all of your menu li whether they contain a submenu or not. Doing so will not affect their position unless you start using top, right, bottom, left CSS properties.

.menu li {
     position: relative;
}

Now you will want to set the position of all ul that are a child of an li in your menu to position: absolute . We also don't want them to show right away so hide them with display: none .

.menu li > ul {
     display: none;
     position: absolute;
}

Applying position relative to the containing element of an absolute positioned element helps contain the absolute positioned element. Not only that but the absolute positioned element will base it's positioning off of the relative positioned parent element, which is what we want. Setting top: 0 and left: 0 will cause a ul that is a child of an li to start in the same upper left hand location as it's parent elements upper left hand corner.

The two rules I have provided so far are the fundamental building blocks of a dropdown/flyout menu in CSS.

From this point forward it will all depend on your design goals as to what else you need to add to your CSS.

I'm going to (mostly) use generic code the rest of the way in the hopes that yourself and others can build off of the basic principles to obtain your own specific results. That said I will base the rest of the code off of what you have supplied. Some superficial styling like borders will be ignored, you can add that later.

HTML

Here is the HTML I'm going to use. Add in anchor elements as needed.

<ul class="menu">
    <li>One</li>
    <li>Two
        <ul>
            <li>Sub Two A</li>
            <li>Sub Two B</li>
        </ul>
    </li>
    <li>Three</li>
</ul>
  • Your top level menu is inline so let's use float: left to do that.
  • They're also fixed width. You're doing this through your anchor tags <a> which is fine, I'm going to use the li .
  • Your text is centered.
.menu li {
     float: left;
     position: relative;
     text-align: center;
     width: 100px;
}

**SEE EDIT BELOW FOR VARIABLE LI ANSWER**

Since you are using fixed width navigation elements you can center your navigation with margin: 0 auto . Using auto for margin left and right to center an element requires a width to be set! Just add up the full width of your top level li and you'll have your width you'll need to center the navigation. Don't forget to include any padding, margin, border etc. in the width calculation.

My example uses three li at 100px width.

.menu {
    width: 300px; /* width of the 3 li */
    margin: 0 auto; /* centers ul when width is specified */
}

Now we will position the submenu ul .

  • For top you need to push the submenu ul down the height of the containing li . I'm going to assume 25px is the height of the li .
  • For left you want it to start at the same edge as the containing li so use 0.
.menu li > ul {
     display: none;
     left: 0;
     position: absolute;
     top: 25px;
}

Now let's display the submenu ul when the parent li is hovered.

.menu li:hover > ul {
    display: block;
}

CSS

The final CSS.

.menu {
    width: 300px; /* width of the 3 li */
    margin: 0 auto; /* centers ul when width is specified */
}
.menu li {
    float: left;
    line-height: 25px; /* assumed height of li */
    position: relative;
    text-align: center;
    width: 100px;
}
.menu li > ul {
    display: none;
    left: 0;
    position: absolute;
    top: 25px;
}
.menu li:hover > ul {
    display: block;
}

Here is a jsFiddle with some basic styling that wraps it all together.

There you go! A primer to CSS dropdown/flyout menus. As usual your needs will require some modifications or additions to what I have supplied. If you understand the fundamentals you'll go a long way in developing more in-depth and robust solutions.

**EDIT**

Just noticed you have variable number of li in your navigation. Make the changes where appropriate. It is a combination of relative positioning with percentage positions.

.menu {
    float: left;
    position: relative;
    left: 50%;
}
.menu li {
    float: left;
    line-height: 25px; /* assumed height of li */
    position: relative;
    right: 50%;
    text-align: center;
    width: 100px;
}
/* undo the right positioning for submenu li so it aligns properly */
.menu li > ul li {
    right: auto;
}

Here is an updated jsFiddle .

Replace your CSS like this, using your LI elements for styling rather than your A elements:

body {
    width:100%;
}
#mainmenu {
    display: block;
    width:100%;
}
#mainmenu ul {
    width:100%;
}
#mainmenu ul li {
    display: inline-block;
    position:relative;
    margin: auto;
    width:19%;
    background: #33332c;
    padding-top:5px;
    padding-bottom:5px;
}
#mainmenu ul li a {
    color: #fbf3e1;
    font-size:14px;
}
#mainmenu ul li ul {
    display: none;
    position: absolute;
}
#mainmenu ul li:hover > ul {
    display: block;
    width:auto;
    position:absolute;
    top:30px;
    left:0;
    background: #33332c;
    padding:10px;
}
#mainmenu ul li:hover > ul li {
    display: block;
    width:150px;
    height:auto;
}
#mainmenu ul li a:hover, #mainmenu ul li.active a {
    color: #f5921e;
    border-bottom: solid 5px #f5921e;
    text-decoration:none;
    border-bottom-right-radius: 5px;
    border-bottom-left-radius: 5px;
}

You may need some additional adjustments, but there you have the basics

See fiddle here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM