简体   繁体   English

如何在 CSS 中仅在一个方向上启用滚动?

[英]How do I enable scrolling only in one direction in CSS?

I have a list with some resizing elements.我有一个包含一些调整大小元素的列表。 When the elements are resized, they should overflow the container in the x direction.当元素被调整大小时,它们应该在 x 方向溢出容器。 There should never be scrolling in the x direction.永远不应该在 x 方向滚动。 Scrolling should be enabled in the y direction.应该在 y 方向启用滚动。

I have tried setting:我试过设置:

overflow-x: visible;
overflow-y: scroll;

But this seems to enable scrolling in both directions.但这似乎可以在两个方向上滚动。

How do I prevent this?我如何防止这种情况?

https://jsfiddle.net/64tw8rqe/ https://jsfiddle.net/64tw8rqe/


The answers to CSS overflow-x: visible; CSS 溢出-x的答案:可见; and overflow-y: hidden; 和溢出-y:隐藏; causing scrollbar issue explain the underlying problem but not a work-around in the case of scroll . 导致滚动条问题解释了潜在的问题,但不是在scroll的情况下的解决方法。


This behaviour is in accordance with the spec .此行为符合规范 I am looking for work-arounds.我正在寻找变通办法。

The problem is that overflow-x: visible; overflow-y: scroll 问题是overflow-x: visible; overflow-y: scroll overflow-x: visible; overflow-y: scroll is an impossible combination in CSS. overflow-x: visible; overflow-y: scroll是CSS中不可能的组合。 Whenever visible is paired with scroll , it is converted to auto . 只要visiblescroll配对,它就会转换为auto In other words, these are equivalent: 换句话说,这些是等价的:

overflow-x: visible;
overflow-y: scroll;

overflow-x: auto;
overflow-y: scroll;

It was a poor descision for the spec, but there are work-arounds. 对于规范来说,这是一个糟糕的决策,但有一些解决方法。

By making the expanding elements position: absolute , their size will not change the container, and they will not be clipped by overflow: hidden . 通过使扩展元素position: absolute ,它们的大小不会改变容器,并且它们不会被overflow: hidden To get them positioned correctly, an extra div with position: relative is wrapped around the whole container. 为了正确定位它们,将一个带有position: relative的额外div包裹在整个容器周围。

HTML: HTML:

<div class='container1'>
  <div class='container2'>
    <ul class='messages'>
      <li><pre>Hello</pre></li>
      <li>
        <pre>This is a 
      really really really 
      really really long message.</pre>
      </li>
      <li><pre>World</pre></li>
    </ul>
  </div>
</div>

CSS: CSS:

* {
  margin: 0;
  padding: 0;
}

.container1 {
  position: relative; 
  width: 200px;
}

.container2 {
  background: #f0f;
  width: 100%;
  height: 100%;
  overflow: scroll;
}

.messages {
  overflow: visible;
  list-style: none;
}

.messages li {
  background: #ff0;
  width: 100%;
  height: 24px;
  margin-top: 12px;
}

.messages li pre {
  position: absolute;
  display: inline-block;
  box-sizing: border-box;
  width: 100%;
  max-height: 24px;
  padding: 4px;
  background: #0ff;
  border-radius: 4px;
  line-height: 16px;
  overflow: hidden;
  text-overflow: ellipsis;
  width: auto;
  min-width: 100%;
  max-width: 100%;
  transition: max-width 200ms ease-out, height 200ms ease-out;
}

.messages li pre:hover {
  z-index: 1;
  background: #00f;
  max-width: 80vw;
  max-height: 80vh;
  transition: max-width 200ms ease-in, max-height 200ms ease-in;
}

Fiddle: 小提琴:

https://jsfiddle.net/cyL6tc2k/2/ https://jsfiddle.net/cyL6tc2k/2/

Credit to the trick found here: http://front-back.com/how-to-make-absolute-positioned-elements-overlap-their-overflow-hidden-parent 相信这里发现的技巧: http//front-back.com/how-to-make-absolute-positioned-elements-overlap-their-overflow-hidden-parent

When you have vertical overflow, a scrollbar is added to the horizontal flow (to the right). 当您有垂直溢出时,滚动条将添加到水平流(右侧)。 Elements will not overlay that scrollbar so browsers change your overflow settings to scroll horizontally instead. 元素不会覆盖该滚动条,因此浏览器会将溢出设置更改为水平滚动。

What you will need to do is add another container around all of the content and set it to have a greater width that all of the overflowed content inside but a height of the inner element and vertical scroll: 您需要做的是在所有内容周围添加另一个容器,并将其设置为具有更大的宽度,使得内部元素和垂直滚动的高度内的所有溢出内容:

HTML HTML

<div class='container3'><!-- Add a parent container -->
  <div class='container'>
    ...
  </div>
</div>

CSS CSS

/* A parent container */
.container3 {
  /* The maximum height of your inner content before scrolling is enabled */
  height: 200px;

  /* Enable the vertical scroll if we have enough content */
  overflow-y: auto;
}

FIDDLE 小提琴

https://jsfiddle.net/cL8hr7ot/ https://jsfiddle.net/cL8hr7ot/

This is due to your usage of "pre", which has some default values on some browsers : 这是因为您使用了“pre”,它在某些浏览器上有一些默认值:

    pre {
       display: block;
       font-family: monospace;
       white-space: pre;
       margin: 1em 0;
    }

You have two options : change all the "pre" by "p" (paragraph) or rewrite the white-space property of pre, by adding this : 您有两个选择:将所有“pre”更改为“p”(段落)或重写pre的white-space属性,方法是添加:

    pre { white-space: normal; }

Not sure if there is a better answer elsewhere but I did come up a very brittle/hacky solution to this problem.不确定其他地方是否有更好的答案,但我确实为这个问题提出了一个非常脆弱/笨拙的解决方案。 It uses some magic numbers in my example but I think it could be the starting point of a somewhat better answer in the future.它在我的例子中使用了一些神奇的数字,但我认为这可能是未来更好答案的起点。

This solution boils down to using position: absolute;这个解决方案归结为使用position: absolute; without any values for top , right , bottom , or left on the item you want to be overflow: visible and setting it's parent to overflow: scroll;在要overflow: visible的项目上没有toprightbottomleft任何值overflow: visible并将其父项设置为overflow: scroll; . .

The default behaviour of an absolutely positioned element without any absolute values is in between the static and absolute positioned world I want it to be in, sort of.没有任何绝对值的绝对定位元素的默认行为介于我希望它所处的静态和绝对定位世界之间。

CODEPEN代码笔

Codepen代码笔

HTML HTML

<div class="wrapper">
  <div class="inner-wrapper">
    <div class="item">Item 1</div>
    <div class="item">Item 2</div>
    <div class="item">Item 3</div>
    <div class="item">Item 4</div>
    <div class="item" id="dropdown">
      Hover me
      <div class="menu">Menu</div>
    </div>
  </div>
</div>

CSS CSS

.wrapper {
  background: blue;
  height: 64px;
  width: 250px;
  padding: 2px;
}

.inner-wrapper {
  overflow-x: scroll;
  display: flex;
  height: 100%;
}

.item {
  background: white;
  margin-right: 2px;
  width: 60px;
  height: 100%;
  flex-shrink: 0;
}

#dropdown .menu {
  background: pink;
  height: 0px;
  position: absolute;
  display: none;
}

#dropdown:hover .menu {
  height: 100px;
  z-index: 1;
  display: block;
  margin-left: -58px;
}

I posted a small video clip of the problem I was trying to solve for on Twitter我在Twitter 上发布了一个关于我试图解决的问题的小视频剪辑

尝试更改overflow-y:hidden

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

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