Что нового
  • Что бы вступить в ряды "Принятый кодер" Вам нужно:
    Написать 10 полезных сообщений или тем и Получить 10 симпатий.
    Для того кто не хочет терять время,может пожертвовать средства для поддержки сервеса, и вступить в ряды VIP на месяц, дополнительная информация в лс.

  • Пользаватели которые будут спамить, уходят в бан без предупреждения. Спам сообщения определяется администрацией и модератором.

  • Гость, Что бы Вы хотели увидеть на нашем Форуме? Изложить свои идеи и пожелания по улучшению форума Вы можете поделиться с нами здесь. ----> Перейдите сюда
  • Все пользователи не прошедшие проверку электронной почты будут заблокированы. Все вопросы с разблокировкой обращайтесь по адресу электронной почте : info@guardianelinks.com . Не пришло сообщение о проверке или о сбросе также сообщите нам.

A Simple, mostly CSS code editor

Lomanu4

Команда форума
Администратор
Регистрация
1 Мар 2015
Сообщения
1,825
Баллы
155
In this article, I'm going to talk about how to make a very simple, browser based code editor using mostly CSS. I originally built this when I needed to let users edit JSON in a CMS that I was building.

If you just want to jump to the code and the working example, here you go. The code can be found

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

and the working example

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

Contenteditable sucks...


So if you were ever pondered building your own code editor, you have probably looked at

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

. While contenteditable is great for many situations, there is one huge problem in regards to updating the content while you type. It is nearly impossible to place the cursor back to where it was after you syntax highlight the code in the editor as it changes.

In my case, I wanted something very minimal without reaching for some huge, heavy handed library for this. I set out to see if I could build a very simple editor using mostly CSS, just using Javascript to create the syntax highlighted output, and update the preview.

I wanted to type in a normal <textarea> but and just update a separate preview of the syntax highlighted code.

How the illusion works



Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



The HTML code


<div id="editor">
<div class="preview"></div>
<textarea class="code" spellcheck="false"></textarea>
</div>
  • A regular <textarea> with transparent text
  • A <div> populated with your syntax highlighted code.
  • A container wrapping your <textarea> and your preview <div> so that they can scroll together and remain lined up.
The CSS


Here is the entire CSS that I used for the editor.


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;
}
Overlapping the elements


One of the key parts here is using display grid to overlay the textarea and the preview


#editor {
...
display: grid;
grid-template: 1fr / 1fr;
place-items: top;
overflow: auto;
...
}

I am using the fr unit to overlap the two elements inside the container. You can read more about fr at CSSTricks

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

.

Stying the textarea and preview identically


You may notice that I apply the same rules to the preview and the textarea. This ensures that they overlap precisely.


#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;
}
Make the textarea transparent


Using rgba for the text color allows me to have the text entirely transparent, so it seems like you are selecting and editing the preview.


#editor .code {
color: rgba(255, 255, 255, 0);
caret-color: magenta;
}
A small bit of Javascript


We do need a small amount of Javascript to tie this all together. Let's take a look at what we need.


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();
We will be using

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

for this, but you could use anything you like.
The mirror() function is doing a couple of things here.


$code.style.height = $code.scrollHeight;

This ensures that as you type, the height of the <textarea> grows, so that the container will scroll instead of the <textarea> itself. You have probably seen this used to make "auto-growing" textareas before.


$preview.innerHTML = Prism.highlight(
$code.value,
Prism.languages.javascript,
"javascript",
);

Then we are using Prism to take the code from the <textarea> syntax highlight it and place the result in the preview <div>

Supporting tab indentation


Anytime you are editing code, you need to be able to indent, and this bit of code allows us to add in spaces when someone hits tab, and then call mirror() again to update the preview.


$code.addEventListener("keydown", (ev) => {
if (ev.code === "Tab") {
ev.preventDefault();
$code.setRangeText(" ", $code.selectionStart, $code.selectionStart, "end");
mirror();
}
});

Finally, we add an eventListener for input on the <textarea> and update the preview with mirror() on each change. Then we call mirror() initially, in case there is already code in the <textarea> at page load.

That's it! Obviously, if you were be editing thousands and thousands of lines of code, you might hit performance issues updating all that syntax highlighted code. One way to improve on this idea would be to create a "virtual" scroller, and only highlight the code that is visible in the containers view. This is how VsCode does their editor.

If you would like to play around with this, you can find the

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

and a

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

on GitHub


Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

 
Вверх