使绝对定位的元素打破可滚动文本。

5

我有一个呈现文本的文本框。这个文本框有一个最大高度,并且它的溢出被设置为auto,使其可滚动。现在我想引入一个复选框,它呈现在这个文本框的右下角。为了实现这一点,我将复选框绝对定位在右下角。这已经按预期工作:

checkbox showing at the bottom right

现在我有一个问题:是否可能使文本在复选框周围换行,以防止文本被复选框遮挡?

同时,必须确保在滚动文本时复选框不会移动,并且它应该(至少在视觉上)保持在文本框内。

我已经尝试使用弹性布局和网格布局方法,但要么失败了,因为在滚动期间复选框移动了,要么是复选框使用了文本框外的额外空间,这是我不想发生的。

还有一个相关问题得到了解决,但在那个问题中,文本不可滚动,因此可以在可滚动的文本框中添加一个不可见的间隔符来打破文本。这个解决方案在这里不起作用,因为我们不知道在哪里添加间隔符,因为根据滚动位置,它必须放在不同的位置。

我的当前版本,在这个fiddle中可以找到文本在复选框下方运行(这是不想要的):

.text {
  white-space: pre-wrap;
  max-height: 8em;
  overflow-y: auto;
}

.read {
  display: inline;
  padding: 8px;
  position: absolute;
  bottom: -2px;
  right: 36px;
  background: white;
  border: 1px solid black;
}

.wrapper {
  position: relative;
}
<div class="wrapper">
  <div class="text">
    Hello World Hello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello World Hello World Hello World Hello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello World Hello World Hello WorldHello WorldHello WorldHello WorldHello World Hello World Hello
    World Hello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello World Hello World Hello World Hello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello World Hello World HelloWorldHello WorldHello WorldHello WorldHello World Hello World Hello
    World Hello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello World Hello World Hello World Hello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello World Hello World HelloWorldHello WorldHello WorldHello WorldHello World Hello World Hello
    World Hello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello World Hello World Hello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello World Hello World Hello World HelloWorldHello WorldHello WorldHello WorldHello World Hello World Hello
    World
  </div>
  <div class="read" id="read">
    <input type="checkbox">
    <label for="read">Read</label>
  </div>
</div>

2个回答

6

这是我能做到的最接近要求的方式。它涉及在复选框上使用float: right,并在包装器上使用scroll事件处理程序来调整复选框位置。

在此解决方案中,复选框需要置于顶部,以便文本实际上可以围绕它换行,并且位于其上方的空白空间不在视图中。

尝试玩弄它,但不确定不断变化的文本对用户友好程度如何。

document.querySelector('.wrapper').addEventListener('scroll', (e) => {
    e.target.querySelector('.read').style.marginTop = `${e.target.scrollTop + 10}px`;
});
.read {
  float: right;
  margin: 10px 20px 10px;
  padding: 8px;
  background: white;
  border: 1px solid black;
}

.wrapper {
  max-height: 8em;
  overflow-y: auto;
}
<div class="wrapper">
  <div class="read" id="read">
    <input type="checkbox">
    <label for="read">Read</label>
  </div>
    Hello World Hello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello World Hello World Hello World Hello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello World Hello World Hello WorldHello WorldHello WorldHello WorldHello World Hello World Hello
    World Hello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello World Hello World Hello World Hello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello World Hello World HelloWorldHello WorldHello WorldHello WorldHello World Hello World Hello
    World Hello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello World Hello World Hello World Hello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello World Hello World HelloWorldHello WorldHello WorldHello WorldHello World Hello World Hello
    World Hello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello World Hello World Hello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello World Hello World Hello World HelloWorldHello WorldHello WorldHello WorldHello World Hello World Hello
    World
</div>


1
谢谢您提供这个好的解决方案。我会再等一等,看看是否有人能够提出一个在底部也能工作的解决方案。 - Philipp
1
我同意@Anton Podolsky的观点,从用户体验的角度来看,这将是一个非常糟糕的想法。想象一下有人试图阅读文本,每次滚动时他们都会失去位置,不得不四处寻找他们的位置。在我看来,你应该改变UI。也许在文本上放置一个大的padding-right,使所有字母远离复选框,但仍然可以滚动。或者只需将复选框放在文本区域下方。或者当你悬停时,复选框可以显示。基本上任何事情,但请不要让用户阅读移动的文本:D - Nikola.grancharov
2
@Nikola.grancharov 老实说,当我提出这个问题时,我甚至没有考虑过这个问题。最终,我决定采用一种解决方案,即在文本中添加填充,以便它不会进入复选框。但是,这个答案仍然解决了最初的问题,而我甚至没有想到这是可能的。 - Philipp

0
对我来说,这是不可能做到的,因为文本应该随着滚动条始终移动,我认为这可以通过js脚本完成,但当div是绝对时是不可能的。
另一个(创意)解决方法可能是在鼠标未悬停在复选框上时隐藏它:
* 我将复选框设置为红色,以使其在不活动时更加突出。

const read = document.querySelector('.read');
    
    read.addEventListener('mouseover', function() {
      read.style.transition = "opacity 0.5s";
      read.style.opacity = 1;
    });
    
    read.addEventListener('mouseout', function() {
      read.style.transition = "opacity 0.5s";
      read.style.opacity = 0.15;
    });
    
    read.style.opacity = 0.1;
    read.style.transition = "opacity 0.5s";
.text {
      max-height: 8em;
      overflow-y: auto;
    }
    
    .read {
      display: inline;
      padding: 8px;
      position: absolute;
      bottom: 5px;
      right: 40px;
      background: red;
    color:#fff;
      border: 1px solid red;
    }
    
    .wrapper {
      position: relative;
    }
<div class="wrapper">
    <div class="text"><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer eu efficitur nunc. Suspendisse commodo condimentum felis et volutpat. Phasellus ultricies justo dolor, at porttitor ligula ornare vel. In eu nulla ut justo feugiat tincidunt. Vestibulum dignissim interdum purus, pellentesque placerat magna malesuada nec. Morbi malesuada orci non purus volutpat, ut accumsan nunc accumsan. Suspendisse posuere imperdiet diam blandit interdum. Mauris at ipsum purus. Quisque a augue nec enim mattis sagittis vel quis dui. Morbi condimentum nibh tellus, nec fermentum massa pretium suscipit. Duis dapibus ultrices dolor. Vivamus condimentum nulla nec fermentum vulputate. Cras aliquet diam in nulla euismod fringilla. Ut ultricies venenatis maximus.
    Sed luctus egestas elit ut venenatis. Sed at viverra mi. Etiam nec magna vel odio dignissim consequat. Pellentesque tempor, eros a semper accumsan, ipsum odio fringilla risus, in lacinia lorem felis quis nulla. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Vivamus tristique diam non justo dapibus elementum. Suspendisse sit amet libero a odio venenatis finibus. Curabitur ac purus sed nunc efficitur finibus. Duis vel purus sit amet nisl sollicitudin lobortis.
    Donec varius dui non maximus bibendum. Donec laoreet, elit ac eleifend dictum, velit arcu viverra sem, vehicula euismod massa justo ut massa. Pellentesque sit amet dui viverra, mattis quam at, aliquam orci. Sed nunc nunc, varius eu mollis et, eleifend a eros. Aliquam erat volutpat. Fusce bibendum elit eget nunc mollis faucibus. Nam tempus euismod nisl, eget tincidunt tellus pulvinar vel. Nullam sed odio in turpis vehicula volutpat. Vestibulum a gravida arcu. Maecenas sit amet mattis diam.
    Curabitur risus est, blandit sed tempor in, molestie ut odio. Curabitur laoreet faucibus tristique. Maecenas efficitur ligula purus, ac sollicitudin turpis molestie ut. Proin vitae diam eget mi consequat posuere. In suscipit sed velit non egestas. Donec dictum dolor at libero posuere convallis. Integer orci enim, feugiat a tempor id, placerat vitae quam. Curabitur quis vestibulum purus, facilisis bibendum felis. Etiam ipsum arcu, pretium ac turpis vel, bibendum faucibus libero. Nam quis sagittis nisl. Suspendisse ultricies neque sit amet dolor faucibus, at maximus mi posuere. Aliquam vitae ornare sem, in interdum nibh. Praesent non laoreet magna. Curabitur sollicitudin faucibus sem in tincidunt.
    Aenean lacinia consequat condimentum. Vestibulum condimentum nibh ac vulputate semper. Aliquam in mauris at tortor eleifend luctus. Phasellus euismod ut nibh nec tristique. In eu urna eros. Mauris malesuada id augue accumsan auctor. Mauris congue lacus eu congue sagittis. Praesent ac sapien nulla. Pellentesque eu velit ut ipsum pharetra fermentum. Fusce condimentum sagittis ultrices. Pellentesque imperdiet enim sed ornare tempor. Fusce ultrices feugiat vestibulum. Integer massa massa, blandit ac luctus at, faucibus nec augue. Sed malesuada commodo dolor eu dictum.</p></div>
    
    <div class="read" id="read">
        <input type="checkbox">
        <label for="read">Read</label>
    </div>
</div>

最简单的替代方案可能是留下一个空白区域。(我知道,这不是最好的方法)。只需像这样更改CSS:

.text {max-height: 10em;overflow-y: auto;padding-right: 120px;}

由于复选框是用户的主要操作,因此它不应该是透明的。我已经考虑过类似的解决方案,即在用户单击复选框时隐藏它以显示完整文本。然而,这两种方法都不能真正有效地解决潜在问题。 - Philipp

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