【问题标题】:How can I display the correct scrollbar when dealing with nested overflows?处理嵌套溢出时如何显示正确的滚动条?
【发布时间】:2018-01-25 00:41:29
【问题描述】:

当您单击Services 菜单项时,一切正常,但父滚动条显示在子滚动条的顶部。我仍然可以在子菜单内正确滚动,但是这不是用可见滚动条模拟的。

当我从 .sidebar 容器中删除 overflow: auto; 时,子菜单滚动正常工作,但父菜单不能正常工作。

我如何确保可见滚动条是针对活动菜单的?

( function( $ ) {

	var sidebar = $( '.sidebar' );
  var menu = sidebar.find( '> ul, > div > ul' );

	// submenus
  ( function() {
  
  	if ( ! sidebar.length || ! menu.children().length || ! menu.length ) {
    	return;
    }
    
    var hasChildren = menu.find( '.has-children > a' );
    var goBack = menu.find( '.go-back' );
    var toggleSub = function( e ) {
    	e.preventDefault();
      var _this;
      
      if ( ! $( e.target ).closest( '.go-back' ).length ) {
      	_this = $( this );
      } else {
      	_this = $( this ).closest( '.sub-menu' ).prev();
      }
      
      _this.find( '~ .sub-menu' ).toggleClass( 'active' );
      _this.closest( 'ul' ).toggleClass( 'slide-out' );
    };
    
    hasChildren.on( 'click', toggleSub );
    goBack.on( 'click', toggleSub );
  
  } ) ();

} ) ( jQuery );
html, body {
  height: 100%;
  background: #f5f5f5;
  font-family: Arial, Helvetica, Helvetica Neue, sans-serif;
}

.sidebar {
  position: fixed;
  top: 0;
  left: 0;
  width: 280px;
  height: 100%;
  background: #fe6570;
  box-shadow: 2px 0px 4px 0px rgba(50,50,50,0.5);
  overflow: auto;
}

.sidebar ul li a {
  display: block;
  padding: 0 1rem;
  color: rgba(255, 255, 255, 0.8);
  line-height: 3.5rem;
  text-transform: capitalize;
  text-decoration: none;
  border-bottom: 1px solid rgba(230, 230, 230, 0.2);
  transition: transform 0.3s ease-in-out;
}

.sidebar ul .has-children > a {
  position: relative;
}

.sidebar ul .has-children > a:after,
.sidebar .go-back > a:before {
  content: '›';
  position: absolute;
  font-size: 1.5rem;
  right: 1rem;
}

.sidebar .go-back > a:before {
  content: '‹';
  position: relative;
  right: initial;
  left: 0;
  margin-right: 10px;
}

.sidebar .sub-menu {
  position: fixed;
  z-index: 1;
  top: 0;
  left: 0;
  height: 100%;
  width: 280px;
  background: #fe8065;
  transition: transform 0.3s ease-in-out;
  transform: translateX(-100%);
}

.sidebar ul {
  overflow-y: auto;
  list-style: none;
  padding: 0;
}

.sidebar .sub-menu.active {
  transform: translateX(0);
}

.sidebar .slide-out > li > a {
  transform: translateX(100%);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="sidebar">
  <ul>
    <li><a href="#">Home</a></li>
    <li><a href="#">About Us</a></li>
    <li class="has-children">
      <a href="#">Services</a>
      <ul class="sub-menu">
        <li class="go-back"><a href="#">Services</a></li>
        <li><a href="#">Consultations</a></li>
        <li><a href="#">Design &amp; Planning</a></li>
        <li><a href="#">Service Item 1</a></li>
        <li><a href="#">Service Item 2</a></li>
        <li><a href="#">Service Item 3</a></li>
      </ul>
    </li>
    <li><a href="#">Photo Gallery</a></li>
    <li><a href="#">Resources</a></li>
    <li><a href="#">Find a Location</a></li>
    <li><a href="#">Contact Us</a></li>
  </ul>
</div>

【问题讨论】:

    标签: javascript css overflow submenu


    【解决方案1】:

    很简单,在服务子菜单打开的时候把.sidebar元素从overflow: auto;改成overflow: hidden,像这样:

    ( function( $ ) {
    
    	var sidebar = $( '.sidebar' );
      var menu = sidebar.find( '> ul, > div > ul' );
    
    	// submenus
      ( function() {
      
      	if ( ! sidebar.length || ! menu.children().length || ! menu.length ) {
        	return;
        }
        
        var hasChildren = menu.find( '.has-children > a' );
        var goBack = menu.find( '.go-back' );
        var toggleSub = function( e ) {
        	e.preventDefault();
          var _this;
          
          if ( ! $( e.target ).closest( '.go-back' ).length ) {
          	_this = $( this );
          } else {
          	_this = $( this ).closest( '.sub-menu' ).prev();
          }
          
          _this.find( '~ .sub-menu' ).toggleClass( 'active' );
          _this.closest( '.sidebar' ).toggleClass( 'overflow-off' );
          _this.closest( 'ul' ).toggleClass( 'slide-out' );
        };
        
        hasChildren.on( 'click', toggleSub );
        goBack.on( 'click', toggleSub );
      
      } ) ();
    
    } ) ( jQuery );
    html, body {
      height: 100%;
      background: #f5f5f5;
      font-family: Arial, Helvetica, Helvetica Neue, sans-serif;
    }
    
    .sidebar {
      position: fixed;
      top: 0;
      left: 0;
      width: 280px;
      height: 100%;
      background: #fe6570;
      box-shadow: 2px 0px 4px 0px rgba(50,50,50,0.5);
      overflow: auto;
    }
    
    .overflow-off {
      overflow: hidden;
    }
    
    .sidebar ul li a {
      display: block;
      padding: 0 1rem;
      color: rgba(255, 255, 255, 0.8);
      line-height: 3.5rem;
      text-transform: capitalize;
      text-decoration: none;
      border-bottom: 1px solid rgba(230, 230, 230, 0.2);
      transition: transform 0.3s ease-in-out;
    }
    
    .sidebar ul .has-children > a {
      position: relative;
    }
    
    .sidebar ul .has-children > a:after,
    .sidebar .go-back > a:before {
      content: '›';
      position: absolute;
      font-size: 1.5rem;
      right: 1rem;
    }
    
    .sidebar .go-back > a:before {
      content: '‹';
      position: relative;
      right: initial;
      left: 0;
      margin-right: 10px;
    }
    
    .sidebar .sub-menu {
      position: fixed;
      z-index: 1;
      top: 0;
      left: 0;
      height: 100%;
      width: 280px;
      background: #fe8065;
      transition: transform 0.3s ease-in-out;
      transform: translateX(-100%);
    }
    
    .sidebar ul {
      overflow-y: auto;
    }
    
    .sidebar .sub-menu.active {
      transform: translateX(0);
    }
    
    .sidebar .slide-out > li > a {
      transform: translateX(100%);
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div class="sidebar">
      <ul>
        <li><a href="#">Home</a></li>
        <li><a href="#">About Us</a></li>
        <li class="has-children">
          <a href="#">Services</a>
          <ul class="sub-menu">
            <li class="go-back"><a href="#">Services</a></li>
            <li><a href="#">Consultations</a></li>
            <li><a href="#">Design &amp; Planning</a></li>
            <li><a href="#">Service Item 1</a></li>
            <li><a href="#">Service Item 2</a></li>
            <li><a href="#">Service Item 3</a></li>
            <li><a href="#">Service Item 4</a></li>
            <li><a href="#">Service Item 5</a></li>
          </ul>
        </li>
        <li><a href="#">Photo Gallery</a></li>
        <li><a href="#">Resources</a></li>
        <li><a href="#">Find a Location</a></li>
        <li><a href="#">Contact Us</a></li>
      </ul>
    </div>

    实现这一点的几种方法,在上面的例子中我已经添加了

    _this.closest( '.sidebar' ).toggleClass( 'overflow-off' );
    

    toggleSub 函数,overflow-off 类是:

    .overflow-off {
      overflow: hidden;
    }
    

    【讨论】:

    • 这很完美,解决了我面临的很多问题。那么进一步的嵌套项目呢?例如:jsfiddle.net/o1sLt5gd/3 .. 到我切换第二级时,溢出关闭类从侧边栏消失,并且还需要在所有以前的 ul 上。新问题?
    • 听起来您需要定位父 .sidebar 和任何父 .sub-menu 元素,例如 _this.closest( '.sidebar, .sub-menu').toggleClass( 'overflow-off' ); 不确定这是否会解决所有问题,但应该让您接近。
    • 啊,是的,_this.closest( '.sidebar, .sub-menu' ).toggleClass( 'overflow-off' ) 成功了!
    • 不确定它是否完全有效,它似乎可能会根据打开时的滚动位置切断当前打开的子菜单的顶部。所以可能需要解决这个问题。
    • 刚刚看到,我可以通过添加来修复它:_this.closest( '.sub-menu' ).scrollTop( 0 );
    猜你喜欢
    • 2019-08-26
    • 2020-01-14
    • 2011-01-26
    • 2016-07-02
    • 1970-01-01
    • 1970-01-01
    • 2015-10-25
    • 2011-11-21
    相关资源
    最近更新 更多