当父级失去悬停时,保持 ul 可见(如果可能的话,纯 css)



我对css很陌生。我想在从父级悬停到 ul 时保持 ul 可见。我不知道该怎么做。

网页标记

<drop-down class="dropdown">
    <span>Dropdown menu<i class="fa fa-cog"></i></span>
    <ul>
        <li>
            <a href="#">Github<i class="fa fa-github"></i></a>
        </li>
        <li>
            <a href="#">BitBucket<i class="fa fa-bitbucket"></i></a>
        </li>
        <li>
            <a href="#">Dropbox<i class="fa fa-dropbox"></i></a>
        </li>
        <li>
            <a href="#">Google drive<i class="fa fa-google"></i></a>
        </li>
    </ul>
</drop-down>

.CSS

drop-down {
    background-color: #e9e9e9;
    border: 1px solid #d2c2c2;
    border-radius: 2px;
    display: flex;
    flex-flow: column nowrap;
    height: 40px;
    justify-content: center;
    position: relative;
    width: 160px;
}
drop-down:hover { cursor: pointer; }
drop-down > span {
    align-items: center;
    color: #555;
    display: flex;
    font-family: 'segoe ui';
    font-size: .9rem;
    justify-content: space-between;
    padding: 0px .75rem;
    pointer-events: none;
}
drop-down > span > i {
    color: inherit;
}
drop-down ul {
    background-color: #e9e9e9;
    border: 1px solid #d2c2c2;
    border-radius: 2px;
    box-shadow: 0px 2px 5px 1px rgba(0,0,0,.15);
    display: block;
    right: 10%;
    list-style: none;
    padding: .5rem 0;
    position: absolute;
    opacity: 0;
    pointer-events: none;
    visibility: hidden;
    top: 160%;
    transition: all .2s ease-out;
    width: 100%;
    z-index: 999;
}
drop-down ul > li {
    color: #555;
    display: block;
}
drop-down ul > li:hover {
    background-color: #007095;
    color: rgba(255,255,255,.9);
}
drop-down ul > li > a {
    align-items: center;
    color: inherit;
    display: flex;
    font-family: 'segoe ui';
    font-size: .95rem;
    justify-content: space-between;
    padding: .5rem .75rem;
    text-decoration: none;
}
drop-down ul > li > a > i {
    color: inherit;
}
drop-down:focus {
    outline: none;
}
drop-down:hover ul {
    pointer-events: auto;
    opacity: 1;
    top: 120%;
    visibility: visible;
}

你可以看到它在这个小提琴上运行:http://jsfiddle.net/vt1y9ruo/1/

我可以用javascript做到这一点,但我不想把它用于小事。

这是一个工作小提琴: http://jsfiddle.net/vt1y9ruo/8/

它通过在按钮和列表之间插入一个不可见的桥梁来工作。

drop-down:hover ul, #ulwrap:hover ul {
    pointer-events: auto;
    opacity: 1;
    top:120%;
    visibility: visible;
}
#ulwrap {
    display: block;
    height:0;
    width:100%;
    position:absolute;
}
drop-down:hover #ulwrap, #ulwrap:hover {
    height:100px;
}

如果你想使用CSS的悬停功能来做到这一点,按钮和列表之间的间隙就是杀死你的原因。 要么消除这个差距,要么使用 JS

附带说明一下,将JS用于小事没有害处,这就是它的用途,只是让它变得漂亮且可重用

好吧,纯 css 解决方案(非常感谢@JBux)有点脏(标记)。我终于选择了JS解决方案,为此创建了一个自定义标签:

const helper = new Helper(); // helper functions
var ddProto = Object.create(HTMLElement.prototype);
ddProto.properties = {
    list: null,
    options: null,
    value: null,
    icon: null,
    index: -1,
};
ddProto.initEvents = function() {
    var self = this;
    // mouse over button
    this.addEventListener('mouseover', function(e) {
        if(!helper.hasClass(this, 'dropdown-active'))
            helper.addClass(this, 'dropdown-active');
    });
    // mouseleave over button
    this.addEventListener('mouseleave', function(e){
        var rect = this.getBoundingClientRect();
        var left = e.pageX;
        var bottom = e.pageY;
        // if mouse is out of X axis of button and if mouse is
        // out (only of top) of Y axis of button, hide ul
        if(left < rect.left || left >= rect.right || bottom < rect.top) {
            helper.delClass(this, 'dropdown-active');
        }
    });
    // list loses hover
    this.properties.list.addEventListener('mouseleave', function(e) {
        if(helper.hasClass(self, 'dropdown-active'))
            helper.delClass(self, 'dropdown-active');
    });
    // elements click
    [].forEach.call(this.properties.options, function(e) {
        e.addEventListener('click', function(event){
            event.preventDefault();
            // set the text of selected value to button
            helper.text(self.properties.value, e.innerText);
            // set the position of selected value
            self.properties.index = helper.position(e.parentNode);
            // set the <i> class name to the button (fontawesome)
            self.properties.icon.className = this.children[0].className;
            // hide ul
            helper.delClass(self,'dropdown-active');
        },true);
    });
};
ddProto.value = function() {
    return this.properties.value;
};
ddProto.index = function() {
    return this.properties.index;
}
ddProto.createdCallback = function() {
    this.properties.list = this.querySelector('ul');
    this.properties.options = this.querySelectorAll('ul > li > a');
    this.properties.value = this.querySelector('span');
    this.properties.icon = this.querySelector('span > i');
    this.initEvents();
};
document.registerElement('drop-down', {prototype: ddProto});

工作小提琴:http://jsfiddle.net/m2dtmr24/2/

非常感谢。

您可以检查的是+选择器(更多内容在这里)

简而言之,它允许您将样式添加到彼此相邻的元素中。实际的 css 可能如下所示:

.dropdown{
  display: none;
}    
.button:hover+.dropdown{
  display: block;
}

仅当.dropdown位于DOM的正下方.button时,此操作才有效

动画可能更难,但您可以通过例如在opacity上使用transition来实现类似的东西,并切换opacity而不是display

最新更新