如何在滚动和调整大小时保持分层的div绝对对齐和大小?

时间:2019-03-14 18:18:39

标签: html css

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

  1. 具有透明字体的透明文本区域是编辑组件。
  2. 它位于div之上,该div从文本区域获取其值并进行渲染。
  3. 编辑交互发生在文本区域,但视图来自基础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>

4 个答案:

答案 0 :(得分:4)

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


如果您确实需要坚持使用这两个元素,那么我将通过重置所有属性将它们分解为裸机:

textarea,
.preview {
  all: initial;
}

然后建立文本样式,因此两者完全相同。 font-familyfont-sizefont-weightline-height等。我还要确保对CSS进行了很好的重置或归一化。

问题在于,浏览器在文本区域中对待文本呈现的方式与在其他地方不同,因此目标是通过使用一些笨拙的方式来迫使它们相同。

答案 1 :(得分:1)

将类 .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>

答案 2 :(得分:1)

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

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

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>

编辑:宽度也一样。

答案 3 :(得分:1)

您已经使用了绝对位置。因此,div和textarea彼此放置。删除div和textarea的位置,最小宽度和最大宽度。并将display:flex-inline用于div#view; 您可以更改空白值以获得更好的效果。