带有 JQuery 动画的 CSS3 菜单无法正确格式化和显示

CSS3 Menu with JQuery Animation not formating and displaying correctly

本文关键字:格式化 显示 动画 JQuery CSS3 菜单 带有      更新时间:2023-09-26

我在以下位置为此问题创建了一个jfiddle:JSFiddle显示菜单问题

我正在尝试使用 jquery 和 css3 创建一个很酷的菜单,主要是因为熟悉。我愿意切换到完整的 CSS3,但我不太确定如何做到这一点。 我有几个问题似乎无法解决。代码如下:

JavaScript:

(function ($) {
    $.fn.hoverIntent = function (f, g) {
        // default configuration options
        var cfg = {
            sensitivity: 7,
            interval: 100,
            timeout: 0
        };
        // override configuration options with user supplied object
        cfg = $.extend(cfg, g ? {
            over: f,
            out: g
        } : f);
        // instantiate variables
        // cX, cY = current X and Y position of mouse, updated by mousemove event
        // pX, pY = previous X and Y position of mouse, set by mouseover and polling interval
        var cX, cY, pX, pY;
        // A private function for getting mouse position
        var track = function (ev) {
            cX = ev.pageX;
            cY = ev.pageY;
        };
        // A private function for comparing current and previous mouse position
        var compare = function (ev, ob) {
            ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
            // compare mouse positions to see if they've crossed the threshold
            if ((Math.abs(pX - cX) + Math.abs(pY - cY)) < cfg.sensitivity) {
                $(ob).unbind("mousemove", track);
                // set hoverIntent state to true (so mouseOut can be called)
                ob.hoverIntent_s = 1;
                return cfg.over.apply(ob, [ev]);
            } else {
                // set previous coordinates for next time
                pX = cX;
                pY = cY;
                // use self-calling timeout, guarantees intervals are spaced out properly (avoids JavaScript timer bugs)
                ob.hoverIntent_t = setTimeout(function () {
                    compare(ev, ob);
                }, cfg.interval);
            }
        };
        // A private function for delaying the mouseOut function
        var delay = function (ev, ob) {
            ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
            ob.hoverIntent_s = 0;
            return cfg.out.apply(ob, [ev]);
        };
        // A private function for handling mouse 'hovering'
        var handleHover = function (e) {
            // next three lines copied from jQuery.hover, ignore children onMouseOver/onMouseOut
            var p = (e.type == "mouseover" ? e.fromElement : e.toElement) || e.relatedTarget;
            while (p && p != this) {
                try {
                    p = p.parentNode;
                } catch (e) {
                    p = this;
                }
            }
            if (p == this) {
                return false;
            }
            // copy objects to be passed into t (required for event object to be passed in IE)
            var ev = jQuery.extend({}, e);
            var ob = this;
            // cancel hoverIntent timer if it exists
            if (ob.hoverIntent_t) {
                ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
            }
            // else e.type == "onmouseover"
            if (e.type == "mouseover") {
                // set "previous" X and Y position based on initial entry point
                pX = ev.pageX;
                pY = ev.pageY;
                // update "current" X and Y position based on mousemove
                $(ob).bind("mousemove", track);
                // start polling interval (self-calling timeout) to compare mouse coordinates over time
                if (ob.hoverIntent_s != 1) {
                    ob.hoverIntent_t = setTimeout(function () {
                        compare(ev, ob);
                    }, cfg.interval);
                }
                // else e.type == "onmouseout"
            } else {
                // unbind expensive mousemove event
                $(ob).unbind("mousemove", track);
                // if hoverIntent state is true, then call the mouseOut function after the specified delay
                if (ob.hoverIntent_s == 1) {
                    ob.hoverIntent_t = setTimeout(function () {
                        delay(ev, ob);
                    }, cfg.timeout);
                }
            }
        };
        // bind the function to the two event listeners
        return this.mouseover(handleHover).mouseout(handleHover);
    };
})(jQuery);
$(function () {
    var config = {
        sensitivity: 3, // number = sensitivity threshold (must be 1 or higher)
        interval: 200, // number = milliseconds for onMouseOver polling interval
        over: doOpen, // function = onMouseOver callback (REQUIRED)
        timeout: 200, // number = milliseconds delay before onMouseOut
        out: doClose // function = onMouseOut callback (REQUIRED)
    };
    function doOpen() {
        $(this).addClass("hover");
        $('ul:first', this).css('visibility', 'visible');
    }
    function doClose() {
        $(this).removeClass("hover");
        $('ul:first', this).css('visibility', 'hidden');
    }
    $("ul.dropdown li").hoverIntent(config);
    $("ul.dropdown li ul li:has(ul)").find("a:first").append(" &raquo; ");
    $("ul.dropdown li ul li:has(ul)").find("span:first").append(" &raquo; ");
});

CSS3:

.main_nav {
    background-color:#ffffff;
    text-align:center;
    float:left;
    height:50px;
}
.main_nav ul{
    list-style:outside none none !important;
    text-align: center;
    display: inline;
    width: 80%;
}
/*
    LEVEL ONE
*/
ul.dropdown                         { position: relative; white-space: nowrap;text-wrap: none;}
ul.dropdown li                      { font-weight: bold; float: left;  background: #ffffff; color: #4b2c17; }
ul.dropdown a:hover                 { color: #ffffff; }
ul.dropdown a:active                { color: #ffa500; }
ul.dropdown li a                    { display: block; padding: 4px 8px; border-right: 1px solid #333;
                                      color: #222; }
ul.dropdown li:last-child a         { border-right: none; } /* Doesn't work in IE */
ul.dropdown li.hover,
ul.dropdown li:hover                { background: rgb(214, 210, 0); color: #ffffff; position: relative; }
ul.dropdown li.hover a              { color: black; }
ul.dropdown li:hover h4             {background: #ffffff;color: #4b2c17;}

/*
    LEVEL TWO
*/
ul.dropdown ul                      { visibility: hidden; position: absolute; top: 100%; left: 0; padding-left: 0px !important;}
ul.dropdown ul li                   { font-weight: normal; background: #ffffff; color: #4b2c17;
                                      border-bottom: 1px solid #222; float: none; }
                                    /* IE 6 & 7 Needs Inline Block */
ul.dropdown ul li a                 { border-right: none; width: 100%; display: inline-block; }
/*
    LEVEL THREE
*/
ul.dropdown ul ul                   { left: 100%; top: 0; }
ul.dropdown li:hover > ul           { visibility: visible; }
/*
    LEVEL Four
*/
ul.dropdown ul ul ul                { left: 100%; top: 0; }
ul.dropdown ul ul li:hover > ul         { visibility: visible; }

和 HTML:

<div class="main_nav">
    <ul class="dropdown">
        <li><a href="/main">Home</a></li>
        <li><a href="/edituser">User</a>
            <ul class="sub_menu">
                <li class="subnavhead"><h3>New Users</h3></li>
                <li><a href="/register">Add New User</a></li>
                <li><a href="/validateuser">Validate Users</a></li>
                <li class="subnavhead"><h3>Current Users</h3></li>
                <li><a href="/edituser">Edit User Information</a></li>
            </ul>
        </li>
        <li class="topnav"><a href="#">Head 2</a>
            <ul class="sub_menu">
                <li><a target="new" href="#">Subhead 1</a></li>
                <li class="subnavhead"><h4><span>Section Group</span></h4>
                    <ul class="thirdnav">
                        <li><a href="#">Subgroup head 1</a>
                            <ul class="thirdnav">
                                <li><a href="#">Subgroup item 1</a></li>
                                <li><a href="#">Subgroup item 2</a></li>
                          </ul>
                        </li>
                        <li><a href="#">Subgroup head 2</a>
                           <ul class="thirdnav">
                               <li><span>Subgroup item head 1</span>
                                    <ul class="thirdnav">
                                        <li><a href="#">third level 1</a></li>
                                        <li><a href="#">third level 2</a></li>
                                    </ul>
                               </li>
                            </ul>
                        </li>
                    </ul>
                </li>
            </ul>
        </li>
    </ul>
</div>

这些代码应该生成一个多级菜单,能够跟踪突出显示的内容;但是,其中有几个异常行为,我目前无法修复。

首先是主导航栏的宽度。 无论我尝试定义的宽度参数如何,我都无法让菜单展开以填充菜单栏,甚至 80%。

第二个是下拉菜单组件上 LI 的宽度。 如您所见,我能够防止行换行,但是如图所示,<li>不会拉伸最长文本的宽度。 除此之外,你会看到亮点不一致,我不知道为什么。 我尝试了多种变体,但没有成功。

最后一个问题是为什么那个愚蠢的>>出现在 sugroup head 2 下的最后一个 html 链接上。 逻辑不符合这一点,但它似乎出现了。

任何帮助将不胜感激!

谢谢!Jon

如果我正确理解了这些问题,我认为我已经解决了 2 和 3。关于第 1 期我根本不明白你的意思......您希望整个菜单占据整个页面的宽度?如果您能澄清一下,那将非常有帮助。

无论如何,对于第 2 期(再次,如果我理解正确的话),您可以通过禁用包装并将width设置为 100% 来使菜单占用最长项目的宽度:

ul.dropdown ul li {
    font-weight: normal;
    background: #ffffff;
    color: #4b2c17;
    border-bottom: 1px solid #222;
    width: 100%;
    white-space:nowrap;
}

对于第 3 期,Prachit 说得对。:has jQuery 选择器与.find相结合给您带来了麻烦,因为"第三级 1"的a标签是与您的选择器$("ul.dropdown li ul li:has(ul)").find(" a:first")匹配的li的第一个后代a标签。在这种情况下,您应该只查找与您的选择器匹配的li的直接子项,因此您的行将变为:

$("ul.dropdown li ul li:has(ul)").find("> a:first").append(" &raquo; ");

无论如何,我在这里更新了你的小提琴:http://jsfiddle.net/tzn1x7uq/5/

希望我能帮上忙。

其他答案似乎对问题2和3有很好的解决方案。使用position:absolute时,儿童的身高和宽度不像平时那样粘附。使用white-space: nowrap将纠正这一点(尽管使用width:100%不会有所作为)。

这一行:

$("ul.dropdown li ul li:has(ul)").find("> a:first").append(" &raquo; ");

工作正常,除了:has()之外还有其他方法可以解决这个问题,但它有效。您可以通过从以下规则中删除background来更正"标题 2">"部分组"的悬停问题:

ul.dropdown li:hover h4 {background: #ffffff;color: #4b2c17;}

最后是无法设置宽度的问题。有几件事需要发生。首先,请确保设置文档的宽度:

html, body{
   width: 100%;
}

接下来,您需要将相同添加到所有父项(百分比宽度仅在父项也具有定义的宽度时才有效)。所以从.main_nav开始:

.main_nav {
   width: 100%; //add
   background-color:#ffffff;
   text-align:center;
   height:50px;
}

您遇到问题的最大原因是因为.main_nav ul被设置为display: inlineinline不会不尊重孩子的宽度/高度,因此打电话width: 100%不会对它产生影响。更改为inline-block或仅block,现在添加宽度:

.main_nav ul{
   width: 100%; //add
   list-style:outside none none !important;
   text-align: center;
   display: inline-block; //add
   padding: 0; //clear the default padding set on ul elements
}

接下来,您的列表项是浮动的,您需要清除这些项。通常overflow:hidden是清除浮点数的好方法,但在这种情况下,您的子导航将"溢出"您的内容,因此最好使用 clearfix:

.main_nav ul:after{
   content: "";
   display: block;
   clear: both;
}

现在,您可以在li上设置大小:

ul.dropdown li { width:33%; font-weight: bold; float: left;  background: #ffffff; color: #4b2c17; }

由于您的样式是通过共享定位条件继承的,因此您需要为子导航li s 使用width: 100%覆盖之前的33%宽度:

ul.dropdown ul li { font-weight: normal; background: #ffffff; color: #4b2c17; border-bottom: 1px solid #222; float: none; width: 100%; //add }

现在,您的列表将采用整个宽度。您还有其他问题,例如,使用visibility: hidden不是一个好主意。虽然该元素被"隐藏"在视线之外,但它仍然占用页面上的空间(如果您向右滚动并且有很多多余的空间,您将看到)。还有一个事实是,你的"head 2"菜单有太多的子导航和向右延伸,以至于把它塞进角落并不理想。您可能需要重新访问其显示方式。也许让它向下下降而不是两个右边。也只是一个UI/UX提示,拥有如此多级别的下拉列表对于用户来说并不受欢迎。但这将取决于你。从结构上讲,这可能需要很多工作,你应该利用类名,这样你就不会让孩子继承不必要的风格,但我希望这能让你走上正确的道路:

小提琴

 you can use it.
<style>
body {
  padding: 20px 50px 150px;
  font-size: 13px;
  text-align: center;
/*  background: #E3CAA1;*/
}
ul.dr_menu {
  text-align: left;
  display: inline;
  margin: 0;
  padding: 15px 4px 17px 0;
  list-style: none;
  /*-webkit-box-shadow: 0 0 5px rgba(0, 0, 0, 0.15);
  -moz-box-shadow: 0 0 5px rgba(0, 0, 0, 0.15);
  box-shadow: 0 0 5px rgba(0, 0, 0, 0.15);*/
}
ul.dr_menu li {
  font: bold 12px/18px;
  display: inline-block;
  margin-right: -4px;
  position: relative;
  padding: 15px 20px;
/*  background: #fff;*/
  cursor: pointer;
  -webkit-transition: all 0.2s;
  -moz-transition: all 0.2s;
  -ms-transition: all 0.2s;
  -o-transition: all 0.2s;
  transition: all 0.2s;
}
ul.dr_menu li:hover {
  background: #0b86c8;
  color: #fff;
}
ul.dr_menu li ul {
  padding: 0;
  position: absolute;
  top: 48px;
  left: 0;
  width: 150px;
  -webkit-box-shadow: none;
  -moz-box-shadow: none;
  box-shadow: none;
  display: none;
  opacity: 0;
  visibility: hidden;
  -webkit-transiton: opacity 0.2s;
  -moz-transition: opacity 0.2s;
  -ms-transition: opacity 0.2s;
  -o-transition: opacity 0.2s;
  -transition: opacity 0.2s;
}
ul.dr_menu li ul li { 
  background: #0b86c8; 
  display: block; 
  color: #fff;
  text-shadow: 0 -1px 0 #000;
}
ul.dr_menu li ul li:hover { background: #666; }
ul.dr_menu li:hover ul {
  display: block;
  opacity: 1;
  visibility: visible;
}
</style>

<body>
<ul class="dr_menu">
    <li>
        Add Management
        <ul>
          <li>My Add</li>
        </ul>
    </li>
    <li>
        API Management
        <ul>
          <li>Create API</li>
          <li>Manage API</li>
          <li>Test API</li>
          <li>Document API</li>
        </ul>
    </li>
</ul>
</body>
  1. 主导航栏的宽度不会扩展,因为.main_navfloat: left;,所以如果你以百分比将宽度添加到li,它不会扩散。您可以将width添加到.main_nav,然后以百分比li,它将沿.main_nav宽度分布。

  2. 在下拉列表中设置li width以获得所需的宽度下拉列表。不确定你的意思是突出显示不一致,如果你的意思是额外的空格,那是因为标题标签h3h4有一些默认的paddingmargin。将 marginpadding 设置为 0 以进行h3h4

  3. 显示>>是因为您在 $("ul.dropdown li ul li:has(ul)").find("a:first").append(" &raquo; "); 中使用了has选择器。 如果 tag 存在于其后代中的任何位置,而不仅仅是作为直接子项,则has匹配。

这是

你要找的吗? http://jsfiddle.net/tzn1x7uq/7/

1一. 主菜单是100%宽度:width: 100%; /*ADDED LINE*/

1b. 菜单链接占用更多空间:

ul.dropdown li a { 
    display: block; padding: 4px 30px; border-right: 1px solid #333; color: #222; 
}  /*ADDED padding 30px*/
  1. 防止换行:

    ul li {white-space: nowrap;} /*ADDED LINE*/
    

2b. 奇怪的突出显示内容:

h3{ margin: 0px;}

你也有<h4><span>text here</span></h4>,我改成了<h3>Text here</h3>

  1. &raquo;引起的随机>>

    /* COMMENTED OUT: GAVE YOU THE >> things
    $("ul.dropdown li ul li:has(ul)").find("a:first").append(" &raquo; ");
    $("ul.dropdown li ul li:has(ul)").find("span:first").append(" &raquo;    ");
    */
    

希望这有帮助!

您可以使用仅使用CSS好友来获得悬停效果。

<div id="navigation">
<ul class="menu">
    <li><a href="/main">Home</a></li>
    <li><a href="/edituser">User</a>
        <ul class="sub-menu">
            <li>
                <h3>New Users</h3>
                <a href="/register">Add New User</a>
            </li>
            <li><a href="/validateuser">Validate Users</a></li>
            <li>
                <h3>Current Users</h3>
                <a href="/edituser">Edit User Information</a>
            </li>
        </ul>
    </li>  
    <li><a href="/edituser">User 2</a>
        <ul class="sub-menu">
            <li>
                <h3>New Users</h3>
                <a href="/register">Add New User</a>
                <ul class="sub-menu">
                    <li>
                        <h3>New Users 2</h3>
                        <a href="/register">Add New User</a>
                        <ul class="sub-menu">
                            <li>
                                <h3>New Users 3</h3>
                                <a href="/register">Add New User</a>
                            </li>
                            <li><a href="/validateuser">Validate Users</a></li>
                            <li>
                                <h3>Current Users</h3>
                                <a href="/edituser">Edit User Information</a>
                            </li>
                        </ul>
                    </li>
                    <li><a href="/validateuser">Validate Users</a></li>
                    <li>
                        <h3>Current Users</h3>
                        <a href="/edituser">Edit User Information</a>
                    </li>
                </ul>
            </li>
            <li><a href="/validateuser">Validate Users</a></li>
            <li>
                <h3>Current Users</h3>
                <a href="/edituser">Edit User Information</a>
            </li>
        </ul>
    </li>
    <li><a href="/edituser">User 3</a>
        <ul class="sub-menu">
            <li>
                <h3>New Users</h3>
                <a href="/register">Add New User</a>
            </li>
            <li><a href="/validateuser">Validate Users</a></li>
            <li>
                <h3>Current Users</h3>
                <a href="/edituser">Edit User Information</a>
            </li>
        </ul>
    </li>
</ul>

对于 CSS

#navigation:before,
#navigation:after { clear: both; content: ' '; display: block; }
#navigation ul { padding: 0; }
#navigation li { float: left; list-style: none; position: relative; } 
#navigation li a { display: block; padding: 5px 15px; text-decoration: none; white-space: nowrap; }
#navigation li a:hover { background-color: #222; color: #fff; }
#navigation li ul,
#navigation li:hover ul ul,
#navigation li li:hover ul ul { display: none; position: absolute; }
#navigation li:hover ul,
#navigation li li:hover ul,
#navigation li li li:hover ul { display: block; }
#navigation li li { float: none; } 
#navigation ul ul ul { left: 100%; top: 0;}
h3 { margin: 0; }

js 小提琴演示