これにより、一緒にスクロールして整列したままにすることができます。
CSS
これがエディターに使用した CSS 全体です。
html,
body {
height: 100vh;
width: 100vw;
padding: 0;
margin: 0;
}
#editor {
height: 100%;
width: 100%;
box-sizing: border-box;
display: grid;
grid-template: 1fr / 1fr;
place-items: top;
overflow: auto;
padding: 2rem;
background-color: #1a1723;
}
#editor .code,
#editor .preview {
all: unset;
}
#editor .code,
#editor .preview {
height: auto;
grid-column: 1 / 1;
grid-row: 1 / 1;
font-family: Monaco, monospace;
font-size: 16px;
resize: none;
line-height: 24px;
white-space: pre-wrap;
overflow: hidden;
}
#editor .preview {
pointer-events: none;
color: #ccc;
}
#editor .code {
color: rgba(255, 255, 255, 0);
caret-color: magenta;
}
要素を重ねる
ここでの重要な部分の 1 つは、表示グリッドを使用してテキストエリアとプレビューをオーバーレイすることです
#editor {
...
display: grid;
grid-template: 1fr / 1fr;
place-items: top;
overflow: auto;
...
}
コンテナ内の 2 つの要素をオーバーラップさせるために fr ユニットを使用しています。 fr について詳しくは、こちらの CSSTricks をご覧ください。
テキストエリアとプレビューを同じように固定する
同じルールをプレビューとテキストエリアに適用していることに気づくかもしれません。これにより、正確にオーバーラップすることが保証されます。
#editor .code,
#editor .preview {
height: auto;
grid-column: 1 / 1;
grid-row: 1 / 1;
font-family: Monaco, monospace;
font-size: 16px;
resize: none;
line-height: 24px;
white-space: pre-wrap;
overflow: hidden;
}
テキストエリアを透明にする
テキストの色に rgba を使用すると、テキストを完全に透明にすることができるので、プレビューを選択して編集しているように見えます。
#editor .code {
color: rgba(255, 255, 255, 0);
caret-color: magenta;
}
ちょっとした Javascript
これをすべて結び付けるには、少量の Javascript が必要です。必要なものを見てみましょう。
const $preview = document.querySelector("#editor .preview");
const $code = document.querySelector("#editor .code");
function mirror() {
// make textarea grow to height of content so we can scroll together
$code.style.height = $code.scrollHeight;
// update the preview underlay with the syntax highlight
$preview.innerHTML = Prism.highlight(
$code.value,
Prism.languages.javascript,
"javascript",
);
}
// insert two spaces on tab
$code.addEventListener("keydown", (ev) => {
if (ev.code === "Tab") {
ev.preventDefault();
$code.setRangeText(" ", $code.selectionStart, $code.selectionStart, "end");
mirror();
}
});
$code.addEventListener("input", mirror);
mirror();
これには Prism を使用しますが、お好きなものを使用してください。
ここでは、mirror() 関数がいくつかのことを行っています。
<div id="editor">
<div class="preview"></div>
<textarea class="code" spellcheck="false"></textarea>
</div>
これにより、入力中に
html,
body {
height: 100vh;
width: 100vw;
padding: 0;
margin: 0;
}
#editor {
height: 100%;
width: 100%;
box-sizing: border-box;
display: grid;
grid-template: 1fr / 1fr;
place-items: top;
overflow: auto;
padding: 2rem;
background-color: #1a1723;
}
#editor .code,
#editor .preview {
all: unset;
}
#editor .code,
#editor .preview {
height: auto;
grid-column: 1 / 1;
grid-row: 1 / 1;
font-family: Monaco, monospace;
font-size: 16px;
resize: none;
line-height: 24px;
white-space: pre-wrap;
overflow: hidden;
}
#editor .preview {
pointer-events: none;
color: #ccc;
}
#editor .code {
color: rgba(255, 255, 255, 0);
caret-color: magenta;
}
次に、Prism を使用して
タブのインデントのサポート
コードを編集するときは常にインデントできる必要があります。このコードにより、誰かがタブを押したときにスペースを追加し、mirror() を再度呼び出してプレビューを更新できます。
#editor {
...
display: grid;
grid-template: 1fr / 1fr;
place-items: top;
overflow: auto;
...
}
最後に、
それだけです!明らかに、何千行ものコードを編集している場合、構文強調表示されたコードをすべて更新するとパフォーマンスの問題が発生する可能性があります。このアイデアを改善する 1 つの方法は、「仮想」スクローラーを作成し、コンテナー ビューに表示されるコードのみを強調表示することです。これが VsCode のエディタのやり方です。
これを試してみたい場合は、
を見つけてください。
コードと GitHub 上の動作例