【问题标题】:How to maintain layered absolute div alignment and sizing while scrolling and resizing?如何在滚动和调整大小时保持分层的绝对 div 对齐和调整大小?
【发布时间】:2019-03-14 18:18:39
【问题描述】:

我需要像这样制作所见即所得的编辑器:

  1. 一个透明的textarea,带有透明字体是编辑组件。
  2. 它位于一个 div 之上,该 div 从 textarea 中获取其值并进行渲染。
  3. 编辑交互发生在 textarea 中,但视图来自底层 div。

这样,我们可以渲染语法高亮文本,同时保持文本区域的编辑功能。

我的问题是我缺乏 CSS 方面的专业知识。因此,无论我尝试了多少种变体,总是会出现自动换行、滚动或对齐不同步的问题。

下面提供的是一种变体。编辑器组件有透明的灰色文本,而底层的 div 是橙色文本,所以我们可以看到它们何时排成一行。

挑战在于让它们始终排成一行,无论内容、滚动或大小如何。

function update(){
  document.getElementById("richtext").innerHTML = 
  document.getElementById("editor").value;
}
.scrollable {
  width: 300px;
  height: 100px;
  overflow: scroll;
  border : 1px solid grey;
}

.content {
  font-family: monospace;
  font-size: 18px;
  position: absolute;
  top: 0;
  left: 0;
  border: none;
  overflow: hidden;
  min-width: 100%;
  min-height: 100%;
  outline: none;
  resize: none;
  margin: none;
  padding: 0;
  box-shadow: none;
  box-sizing: border-box;
  white-space: pre;
  display: block;
  overflow: none;
}

#richtext {
  z-index: -10;
  color: orange;
}

#view {
  height: 100%;
  position: relative;
  display: inline-block;
}

#editor {
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;  
  background-color: transparent;
  color: #00000055;
  caret-color: black;
}
<div class="scrollable">
  <div id="view" class="content">
  <textarea id="editor" class="content" onInput="update();" class="content"></textarea>
  <div id="richtext" class="content"></div>
</div>
</div>

【问题讨论】:

  • 您所描述的内容尚不清楚(从技术角度来看)。请创建一个runnable minimal reproducible example。还可以考虑将您的研究结果添加到问题中。否则看起来好像你没有进行过。
  • 我会努力让这个更清楚。没有 SO 要求显示已完成的工作。事实上,我的工作是在 elm-ui,在 elm 中完成的。我的问题的解决方案首先要了解 CSS 解决方案的机制,但我现有的代码对这里的任何人都没有帮助,因为这不是 elm/elm-ui 特定的问题。如果你好奇,这里是代码gist.github.com/z5h/…
  • 无论使用何种工具、后端技术或前端框架,这都归结为浏览器如何解释您的 CSS 输出,您似乎需要帮助。不要提供源代码,提供一个工作示例(基于重现它所需的最小输出量(已处理 = 浏览器中的内容)代码)。没有人说有 SO 要求来展示您的研究或现有代码,但这会大大增加您获得有用答案的机会,而这反过来似乎是您的要求/期望。
  • @z5h 好像您回答了自己的问题。将 2 个 div 放入包装器中,并为包装器提供 heightoverflow: auto
  • 好的,我已经添加了我所拥有的。它不起作用。任何帮助表示赞赏。

标签: html css


【解决方案1】:

您需要textarea 和底层 div 吗?我最近试图找到一个好的富文本编辑器,并注意到许多现代编辑器使用的只是一个带有contenteditable="true" 作为 HTML5 属性的 div。这是现实世界中的一些good examples


如果你真的需要坚持使用这两个元素,我会通过重置所有属性将它们都撕成裸机:

textarea,
.preview {
  all: initial;
}

然后建立文本样式,使其在两者上完全相同。 font-familyfont-sizefont-weightline-height 等。我还要确保有良好的 CSS 重置或正常化。

问题在于浏览器在 textarea 中处理文本渲染的方式与在其他地方不同,因此目标是通过有点强硬来强制它们相同。

【讨论】:

  • 我正在使用 Elm,并且 contenteditable 存在许多已知问题。我故意避开它。
  • 这完全可以理解。我也给了你一些 CSS 的东西来尝试。问题是浏览器在 textarea 中处理文本渲染的方式与在其他地方不同,因此目标是通过有点笨拙来强制它们相同
【解决方案2】:

将类 .content min-height:100%; 更改为 min-height:100vh; 并将 white-space: pre; 更改为 white-space: pre-wrap;

这是更新的小提琴:

function update() {
  document.getElementById("richtext").innerHTML =
    document.getElementById("editor").value;
}
.scrollable {
  width: 300px;
  height: 100px;
  overflow: scroll;
  border: 1px solid grey;
}

.content {
  font-family: monospace;
  font-size: 18px;
  position: absolute;
  top: 0;
  left: 0;
  border: none;
  overflow: hidden;
  min-width: 100%;
  min-height: 100vh;
  outline: none;
  resize: none;
  margin: none;
  padding: 0;
  box-shadow: none;
  box-sizing: border-box;
  white-space: pre-wrap;
  display: block;
  overflow: none;
}

#richtext {
  z-index: -10;
  color: orange;
}

#view {
  height: 100%;
  position: relative;
  display: inline-block;
}

#editor {
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: transparent;
  color: #00000055;
  caret-color: black;
}
<div class="scrollable">
  <div id="view" class="content">
    <textarea id="editor" class="content" onInput="update();" class="content"></textarea>
    <div id="richtext" class="content"></div>
  </div>
</div>

【讨论】:

  • 随着内容变长,它会失去同步。
【解决方案3】:

您使用了绝对位置。因此 div 和 textarea 是相互放置的。删除 div 和 textarea 的位置、最小宽度和最大宽度。并为 div#view 使用 display:flex-inline; 您可以更改空白的值以获得更好的结果。

【讨论】:

    【解决方案4】:

    对齐不同步,因为最终您将超过文本区域的定义高度,并且其内部滚动开始。

    为避免这种情况,请更新 textarea 的高度,使其自动扩展。

    function update(){
      richtext.innerHTML = editor.value;
    
      editor.style.width = 'auto';
      editor.style.width = editor.scrollWidth+'px';
    
      editor.style.height = 'auto';
      editor.style.height = editor.scrollHeight+'px';
    }
    

    var richtext = document.getElementById("richtext")
    var editor = document.getElementById("editor")
    
    function update(){
      richtext.innerHTML = editor.value;
      
      editor.style.width = 'auto';
      editor.style.width = editor.scrollWidth+'px';
      
      editor.style.height = 'auto';
      editor.style.height = editor.scrollHeight+'px';
    }
    .scrollable {
      width: 300px;
      height: 100px;
      overflow: scroll;
      border : 1px solid grey;
    }
    
    .content {
      font-family: monospace;
      font-size: 18px;
      position: absolute;
      top: 0;
      left: 0;
      border: none;
      overflow: hidden;
      min-width: 100%;
      min-height: 100%;
      outline: none;
      resize: none;
      margin: none;
      padding: 0;
      box-shadow: none;
      box-sizing: border-box;
      white-space: pre;
      display: block;
      overflow: none;
    }
    
    #richtext {
      z-index: -10;
      color: orange;
    }
    
    #view {
      height: 100%;
      position: relative;
      display: inline-block;
    }
    
    #editor {
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;  
      background-color: transparent;
      color: #00000055;
      caret-color: black;
    }
    <div class="scrollable">
      <div id="view" class="content">
      <textarea id="editor" class="content" onInput="update();" class="content"></textarea>
      <div id="richtext" class="content"></div>
    </div>
    </div>

    编辑:显然,宽度也是如此。

    【讨论】:

      猜你喜欢
      • 2013-12-02
      • 1970-01-01
      • 2015-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-29
      • 2012-01-28
      相关资源
      最近更新 更多