当鼠标悬停在一个 Div 上时,如何使滚动条仅可见?

112

我正在尝试找出如何创建一个滚动的 div,只有在鼠标悬停时才显示其滚动条。

谷歌图片搜索是一个例子,在下面的图片中,你可以看到左侧边栏似乎不能滚动,直到你将鼠标悬停在它上面。

这个功能可以用 CSS 实现吗?还是需要 JavaScript?如果可能,能否提供一个快速示例来完成这样的任务?

示例

16个回答

203

div {
  height: 100px;
  width: 50%;
  margin: 0 auto;
  overflow: hidden;
}

div:hover {
  overflow-y: scroll;
}
<div>
  <p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It
    has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop
    publishing software like Aldus PageMaker including versions of Lorem Ipsum.
  </p>
</div>

这种方案可行吗?


3
它会显示滚动条,但有时在鼠标移出后,滚动条下面的 div 元素不会更新宽度。它们将保持缩小状态,留有空白以适应滚动条(在 Firefox 和 Chrome 上测试)。 - Bakhshi
1
@Bakhshi 我也遇到了同样的问题,我已经按照这篇文章中所解释的实现了,现在它正常工作了。https://dev59.com/qnA75IYBdhLWcg3wFEyb - Jeffpowrs
1
它在大多数Mac浏览器中不起作用,因为它们开始在滚动本身开始后显示滚动条,而不是在悬停时。 - antiplayer
2
当你悬停并添加滚动条时,内容会向左跳动。内容应该保持在原位。 - StealthTrails
7
抱歉搬起石头砸自己的脚...但是#div:hover { overflow-y: auto; }是一个更加用户友好的解决方案。只有在需要时才显示滚动条。 - barnacle.m
显示剩余5条评论

84

使用overflow属性来改变布局有许多问题,比如内部块的宽度不一致和触发重排。

有一种更简单的方法可以达到相同的效果,并且不会触发任何重排:使用visibility属性和嵌套块:

.scrollbox {
  width: 10em;
  height: 10em;
  overflow: auto;
  visibility: hidden;
}

.scrollbox-content,
.scrollbox:hover,
.scrollbox:focus {
  visibility: visible;
}

.scrollbox_delayed {
  transition: visibility 0.2s;
}

.scrollbox_delayed:hover {
  transition: visibility 0s 0.2s;
}
<h2>Hover it</h2>
<div class="scrollbox" tabindex="0">
  <div class="scrollbox-content">Hover me! Lorem ipsum dolor sit amet, consectetur adipisicing elit. Facere velit, repellat voluptas ipsa impedit fugiat voluptatibus. Facilis deleniti, nihil voluptate perspiciatis iure adipisci magni, nisi suscipit aliquam, quam, et excepturi! Lorem
    ipsum dolor sit amet, consectetur adipisicing elit. Facere velit, repellat voluptas ipsa impedit fugiat voluptatibus. Facilis deleniti, nihil voluptate perspiciatis iure adipisci magni, nisi suscipit aliquam, quam, et excepturi!</div>
</div>

<h2>With delay</h2>
<div class="scrollbox scrollbox_delayed" tabindex="0">
  <div class="scrollbox-content">Hover me! Lorem ipsum dolor sit amet, consectetur adipisicing elit. Facere velit, repellat voluptas ipsa impedit fugiat voluptatibus. Facilis deleniti, nihil voluptate perspiciatis iure adipisci magni, nisi suscipit aliquam, quam, et excepturi! Lorem
    ipsum dolor sit amet, consectetur adipisicing elit. Facere velit, repellat voluptas ipsa impedit fugiat voluptatibus. Facilis deleniti, nihil voluptate perspiciatis iure adipisci magni, nisi suscipit aliquam, quam, et excepturi!</div>
</div>

这种方法的另一个特点是,visibility 可以进行动画处理,因此我们可以为其添加过渡效果(请参见上面笔中的第二个示例)。 添加过渡效果对于用户体验更好:当悬停在元素上并且沿着移动到另一个元素时,滚动条不会立即出现,并且在用鼠标光标定位滚动条时,它也不会立即隐藏,从而很难错过滚动条。


所以只是为了澄清:这涉及到为滚动条设置专用的div吗?这是正确的做法吗? - Trace DeCoy
2
我看到了很多关于这个问题的提问,而这个答案实际上非常棒。它是跨浏览器兼容的,总体来说易用且令人惊叹。 - Rithwik
1
这个解决方案真的帮了我很多忙。我花了几个小时试图让一个 div 滚动条只在悬停时显示,但尝试修复悬停时页面重新定位在跨浏览器上并不容易。这个解决方案立即解决了这个问题。谢谢! - helloimbarbara
4
在触摸设备上,该解决方案可能存在问题。由于“visibility: hidden”,用户必须在滚动框中轻击一次才能进行滚动。我的解决方案是将其修改为以下方式:“@media (hover: hover) { .scrollbox { visibility: hidden; }}”。 - Benjamin Freitag

13

对于webkit浏览器,一种技巧是创建一个不可见的滚动条,然后在鼠标悬停时显示出来。这种方法不会影响滚动区域的宽度,因为滚动条所需的空间已经存在。

类似于以下内容:

body {
  height: 500px;
  &::-webkit-scrollbar {
    background-color: transparent;
    width: 10px;
  }
  &::-webkit-scrollbar-thumb {
    background-color: transparent;
  }
}

body:hover {
  &::-webkit-scrollbar-thumb {
    background-color: black;
  }
}

.full-width {
  width: 100%;
  background: blue;
  padding: 30px;
  color: white;
}
some content here

<div class="full-width">does not change</div>


这在自定义元素的影子根中对我不起作用,如下所示::host:hover::-webkit-scrollbar-thumb {background: blue}。什么也没发生。它在这个答案中与body一起工作,但是与:host完全不起作用。 - trusktr
哦,因为应该是:host(:hover),而不是:host:hover。这不太直观。 - trusktr

6

给该 div 元素设置固定的高度和 scroll:hidden; 样式,当鼠标悬停在该元素上时将样式更改为 scroll:auto;。

#test_scroll{ height:300px; overflow:hidden;}
#test_scroll:hover{overflow-y:auto;}

这是一个示例。 http://jsfiddle.net/Lywpk/

5

.scroll {
  height: 140px;
  width: 140px;
  overflow-y: auto;
}

.scroll:active::-webkit-scrollbar-thumb,
.scroll:focus::-webkit-scrollbar-thumb,
.scroll:hover::-webkit-scrollbar-thumb {
    visibility: visible;
}
.scroll::-webkit-scrollbar-thumb {
    background-color: darkgrey;
    visibility: hidden;
}

.scroll::-webkit-scrollbar {
    width: 4px;
    height: 4px;
}
<div class="scroll">
  <p>
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Reiciendis aliquid recusandae nisi dolore numquam consectetur voluptatibus officia. Velit quod corporis quae quos. Facere, obcaecati? Tenetur obcaecati minima fugit a iste!
  </p>
</div>


4
.div::-webkit-scrollbar-thumb {
    background: transparent;
}

.div:hover::-webkit-scrollbar-thumb {
    background: red;
}

这并没有回答问题,它只是改变了滚动条的颜色。而且,它只适用于移动Webkit设备,并且仍处于草案阶段。 - pygeek

3

由于尚未提及,这里提供一种针对Firefox的CSS解决方案,不会影响div的大小:

div {
    overflow-y: scroll;
    /* Sets Color to Transparent for both the track and the thumb */
    scrollbar-color: transparent transparent;
    /* Optional, provides a smooth transition */
    transition: scrollbar-color .25s ease-in-out;
}

div:hover {
    /* Sets the color back to the default value. You can choose a different color */
    scrollbar-color: initial;
}

您可以使用::webkit-scrollbar属性(已在此处回答)以确保兼容性。


2
我使用了这种方法。

.content {
  padding: 17px 0 17px 17px;
  width: 300px;
  height: 200px;
  overflow-y: scroll;
  mask-image: linear-gradient(to top, transparent, black),
    linear-gradient(to left, transparent 17px, black 17px);
  mask-size: 100% 20000px;
  mask-position: left bottom;
  -webkit-mask-image: linear-gradient(to top, transparent, black),
    linear-gradient(to left, transparent 17px, black 17px);
  -webkit-mask-size: 100% 20000px;
  -webkit-mask-position: left bottom;
  transition: mask-position 0.3s, -webkit-mask-position 0.3s;
}

.content:hover {
  -webkit-mask-position: left top;
}

@keyframes background {
  from {
    background: pink;
  }
  to {
    background: #c0d6ff;
  }
}

.wrapper {
  float: left;
  animation: background 5s infinite alternate;
}
<div class="wrapper">
  <div class="content">
    Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
  </div>
</div>


2

@Calvin Froedge的答案很简短,但也有一个问题,@kizu提到了这个问题。 由于div的宽度不一致,当鼠标悬停时会闪烁。为解决此问题,在悬停时在右侧添加负边距。

#div { 
     overflow:hidden;
     height:whatever px; 
}
#div:hover { 
     overflow-y:scroll; 
     margin-right: -15px; // adjust according to scrollbar width  
}

2
我认为类似以下这样的东西:
$("#leftDiv").mouseover(function(){$(this).css("overflow","scroll");});
$("#leftDiv").mouseout(function(){$(this).css("overflow","hidden");});

3
从性能角度来看,这比使用Calvin的:hover解决方案要昂贵得多。 - Shyam Habarakada

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接