简体   繁体   English

javascript - 将内容移动到视图中而不滚动容器

[英]javascript - move content into view without scrolling the container

Our shopping site has a dropdown menu with main categories and sub-categories.我们的购物网站有一个包含主要类别和子类别的下拉菜单。 When you hover over a main category, the sub-category menu pops out on the right.当您将鼠标悬停在主类别上时,子类别菜单会在右侧弹出。 The issue is that both menus are contained in the same scrolling container.问题是两个菜单都包含在同一个滚动容器中。 So you scroll down to find a main category below the current viewport, you hover over a main category and the sub-category pops up on the left, but you have scrolled down, so you only see part of none of the sub-categories.因此,您向下滚动以找到当前视口下方的主要类别,将鼠标悬停在主要类别上,子类别会在左侧弹出,但您已向下滚动,因此您只能看到部分子类别。 So our current fix, which is not really working is to scroll the container to the top of the sub-categories, which is also the top of the categories.因此,我们当前的解决方法是将容器滚动到子类别的顶部,这也是类别的顶部,但实际上并不奏效。 So now your mouse is over a different category and a different set of sub-categories pop out.所以现在您的鼠标位于不同的类别上,并且会弹出一组不同的子类别。 So basically you cannot view sub-categories for categories below the viewport.所以基本上你不能在视口下方查看类别的子类别。 Ideally we would make them seperate containers with seperate scrollbars.理想情况下,我们将使它们具有单独的滚动条的单独容器。 But that will not look good at all and will not be acceptable.但这看起来一点都不好,也不会被接受。

Note: This only happens when the browser window height is shrunk far enough to cause a vertical scroll bar.注意:这仅在浏览器窗口高度缩小到足以导致垂直滚动条时发生。 Obviously if the window is big enough, no scroll bar is needed and we have no issues.显然,如果窗口足够大,就不需要滚动条,我们就没有问题。

Here is what it currently looks like.这是它目前的样子。 You hover over the 'Electrical' category and the sub-category pops out to the right.您将鼠标悬停在“电气”类别上,子类别会弹出到右侧。 在此处输入图片说明

We are using javascript and vue.js, no jquery.我们使用的是 javascript 和 vue.js,没有 jquery。 I learned this code will scroll the sub-category menu into view, which is not what we want.我了解到这段代码会将子类别菜单滚动到视图中,这不是我们想要的。

var el = document.querySelector('.nav-flyout-menu');
      el.scrollIntoView(true);

I think what I want is to actually move, as in set style.top of the sub-category menu to top of the current viewport.我想我想要的是实际移动,就像将子类别菜单的 style.top 设置为当前视口的顶部一样。 I played around with that a little and couldn't anything to work right.我玩了一点,但无法正常工作。 Does anyone know how we can successfully solve this issue.有谁知道我们如何成功解决这个问题。 Is setting the style.top dynamically the best method?动态设置 style.top 是最好的方法吗? How do I figure out what to set it to?我如何弄清楚将它设置为什么? I have tried something like this:我试过这样的事情:

var topBound = document.querySelector('.nav-flyout-menu').getBoundingClientRect().top;
if(topBound < 0) {
  let newTop = Math.abs(topBound) + 42;
  document.querySelector('.nav-flyout-menu').style.top = newTop + "px";
}

This code worked sometimes and sometimes not.此代码有时有效,有时无效。

Update: As requested, here is a fiddle that I have created showcasing my issue.更新:根据要求,这是我创建的一个展示我的问题的小提琴 It is not exactly like our site, but I think it is close enough.它并不完全像我们的网站,但我认为它已经足够接近了。 Make the example height small enough to force a scroll bar and hover over each category.使示例高度足够小以强制滚动条并将鼠标悬停在每个类别上。 When you scroll down to view the bottom categories, you won't be able to see the top of the subcategories.当您向下滚动查看底部类别时,您将无法看到顶部的子类别。 That is exactly the problem we are currently facing.这正是我们目前面临的问题。 I think I want to change the top value when it shows the current subcategory.我想我想在显示当前子类别时更改top值。 But I can't figure out how to calculate that top value.但我不知道如何计算最高值。 I used jQuery just to whip out the fiddle example, but we are not using jQuery on our site.我使用 jQuery 只是为了制作小提琴示例,但我们没有在我们的网站上使用 jQuery。

 $("a.dropdown-item").hover( function () { $(".nav-flyout-menu").removeClass("show"); let category = $.trim($(this).text()); category = category.replace(/\\s+/g, '-').toLowerCase(); $("." + category).addClass("show"); }, function () { } )
 .navbar { width: 100%; display: flex; position: relative; padding: 0.5rem 1rem; background-color: #0000cc; flex-direction: row; } .navbar a { color: #ffffff; } .navbar .dropdown-menu a { color: #000000; } ul { list-style: none; } .dropdown-menu { position: absolute; top: 100%; left: 0; z-index: 1000; display: block; float: left; min-width: 10rem; padding: .5rem 0; margin: 0; font-size: 1rem; color: #212529; text-align: left; list-style: none; background-color: #fff; background-clip: padding-box; border: 1px solid rgba(0,0,0,.15); border-bottom: .5rem solid #cc0000; padding-right: 1.5rem; } .navbar-nav .dropdown-menu { position: static; float: none; } .navbar-container .dropdown-menu { max-height: calc(100vh - 150px); overflow-y: auto; } .dropdown-item { display: block; width: 100%; padding: .5rem 1.5rem; clear: both; text-align: inherit; white-space: nowrap; background-color: transparent; border: 0; } .nav-flyout-root { position: relative; display: inline-block; float: left; } .nav-flyout-menu { display: none; flex-direction: column; float: left; min-width: 10rem; padding: .5rem 0; margin: 0; font-size: 1rem; color: #212529; text-align: left; list-style: none; background-color: #fff; background-clip: padding-box; } .nav-flyout-menu.show { display: inline-flex; } .flyout-menu-item { font-weight: 400; color: #212529; text-align: inherit; white-space: nowrap; background-color: transparent; border: 0; display: block; width: 100%; padding: .5rem 1.5rem; clear: both; } .submenu div { display: block; } .dropdown-item:focus, .dropdown-item:hover, .dropdown-item a:focus, .dropdown-item a:hover { color: #fff!important; text-decoration: none; background-color: #430984; }
 <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.2.1/css/bootstrap.min.css" rel="stylesheet"/> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div class="navbar-container"> <div class="navbar"> <ul> <li> <a href="#">First</a> <div class="dropdown-menu"> <div class="d-flex"> <div class="nav-flyout-root"> <a class="dropdown-item"> Computers </a> <a class="dropdown-item"> Laptops </a> <a class="dropdown-item"> Monitors </a> <a class="dropdown-item"> Hard Drives </a> <a class="dropdown-item"> Keyboards </a> <a class="dropdown-item"> Mice </a> <a class="dropdown-item"> Computers </a> <a class="dropdown-item"> Laptops </a> <a class="dropdown-item"> Monitors </a> <a class="dropdown-item"> Hard Drives </a> <a class="dropdown-item"> Keyboards </a> <a class="dropdown-item"> Mice </a> </div> <div class="nav-flyout-menu position-relative computers"> <div class="flyout-menu-header text-nowrap"> <a href="#">All Computers</a> </div> <div class="d-flex flex-grow-1 flex-column submenu"> <div> <a href="#" class="flyout-menu-item">Dell</a> </div> <div> <a href="#" class="flyout-menu-item">HP</a> </div> <div> <a href="#" class="flyout-menu-item">Asus</a> </div> <div> <a href="#" class="flyout-menu-item">Compaq</a> </div> <div> <a href="#" class="flyout-menu-item">Dell</a> </div> <div> <a href="#" class="flyout-menu-item">Samsung</a> </div> <div> <a href="#" class="flyout-menu-item">Acer</a> </div> </div> </div> <div class="nav-flyout-menu position-relative laptops"> <div class="flyout-menu-header text-nowrap"> <a href="#">All Laptops</a> </div> <div class="d-flex flex-grow-1 flex-column submenu"> <div> <a href="#" class="flyout-menu-item">Acer</a> </div> <div> <a href="#" class="flyout-menu-item">HP</a> </div> <div> <a href="#" class="flyout-menu-item">Sony</a> </div> <div> <a href="#" class="flyout-menu-item">Compaq</a> </div> <div> <a href="#" class="flyout-menu-item">Vaio</a> </div> <div> <a href="#" class="flyout-menu-item">Apple</a> </div> <div> <a href="#" class="flyout-menu-item">Acer</a> </div> </div> </div> <div class="nav-flyout-menu position-relative monitors"> <div class="flyout-menu-header text-nowrap"> <a href="#">All Monitors</a> </div> <div class="d-flex flex-grow-1 flex-column submenu"> <div> <a href="#" class="flyout-menu-item">Qnix</a> </div> <div> <a href="#" class="flyout-menu-item">HP</a> </div> <div> <a href="#" class="flyout-menu-item">Sony</a> </div> <div> <a href="#" class="flyout-menu-item">Dell</a> </div> <div> <a href="#" class="flyout-menu-item">Asus</a> </div> <div> <a href="#" class="flyout-menu-item">22"</a> </div> <div> <a href="#" class="flyout-menu-item">23"</a> </div> </div> </div> <div class="nav-flyout-menu position-relative hard-drives"> <div class="flyout-menu-header text-nowrap"> <a href="#">All Hard Drives</a> </div> <div class="d-flex flex-grow-1 flex-column submenu"> <div> <a href="#" class="flyout-menu-item">Western Digital</a> </div> <div> <a href="#" class="flyout-menu-item">Samsung</a> </div> <div> <a href="#" class="flyout-menu-item">HP</a> </div> <div> <a href="#" class="flyout-menu-item">Seagate</a> </div> <div> <a href="#" class="flyout-menu-item">Kingston</a> </div> <div> <a href="#" class="flyout-menu-item">Crucial</a> </div> <div> <a href="#" class="flyout-menu-item">SSD</a> </div> </div> </div> <div class="nav-flyout-menu position-relative keyboards"> <div class="flyout-menu-header text-nowrap"> <a href="#">All Keyboards</a> </div> <div class="d-flex flex-grow-1 flex-column submenu"> <div> <a href="#" class="flyout-menu-item">Logitech</a> </div> <div> <a href="#" class="flyout-menu-item">Microsoft</a> </div> <div> <a href="#" class="flyout-menu-item">Gearhead</a> </div> <div> <a href="#" class="flyout-menu-item">Razer</a> </div> <div> <a href="#" class="flyout-menu-item">Cherry MX</a> </div> <div> <a href="#" class="flyout-menu-item">Mech Blue</a> </div> <div> <a href="#" class="flyout-menu-item">Mech Red</a> </div> </div> </div> <div class="nav-flyout-menu position-relative mice"> <div class="flyout-menu-header text-nowrap"> <a href="#">All Mice</a> </div> <div class="d-flex flex-grow-1 flex-column submenu"> <div> <a href="#" class="flyout-menu-item">Steel Series</a> </div> <div> <a href="#" class="flyout-menu-item">Microsoft</a> </div> <div> <a href="#" class="flyout-menu-item">Logitech</a> </div> <div> <a href="#" class="flyout-menu-item">Razer</a> </div> <div> <a href="#" class="flyout-menu-item">Cooler Master</a> </div> <div> <a href="#" class="flyout-menu-item">HyperX</a> </div> <div> <a href="#" class="flyout-menu-item">Roccat</a> </div> </div> </div> </div> </div> </li> </ul> </div> </div>

You can add a class to the active sub-menu element您可以向活动子菜单元素添加一个类

var el = document.querySelector('.nav-flyout-menu');
el.classList.add("nav-active-sub-menu");

And control it's style with css.并用 css 控制它的样式。 Something like:就像是:

.nav-active-sub-menu{
    position: absolute;
    top: 0;
}

Let me know if that's what you mean.如果这就是你的意思,请告诉我。

Good luck!祝你好运!

Finally got this!终于拿到了! I knew this had to be able to be accomplished with some simple javascript.我知道这必须能够通过一些简单的 javascript 来完成。 I was right.我是对的。 Element.scrollTop was the key. Element.scrollTop是关键。 I don't think this would be possible with CSS alone, someone correct me if I am wrong.我认为单独使用 CSS 是不可能的,如果我错了,有人会纠正我。 We have an event listener for when a main menu item is hovered to show the submenu.当主菜单项悬停以显示子菜单时,我们有一个事件侦听器。 In that listener, I put this code:在那个监听器中,我放了这段代码:

let scrollTop = vm.$el.parentElement.parentElement.parentElement.scrollTop;
document.querySelector('.nav-flyout-menu').style.top = scrollTop + "px";

This seems to be working in all my tests.这似乎在我所有的测试中都有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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