I've been looking all over and failed to find a solution to this on my own. I'm trying to make a basic contenteditable code editor, and for the line numbers I have chosen to use a paragraph for each line with a counter set in a CSS pseudo element.
.editor {
display: inline-block;
border: 1px black solid;
font-family: "Consolas", "Monaco", "Courier New", monospace;
counter-reset: line;
width: 90%;
height: 350px;
overflow: scroll;
padding-left: 0;
margin-left: 0;
z-index: 1;
}
.editor p {
display: block;
counter-increment: line;
background-color: #FFF;
text-align: left;
margin: 0px;
z-index: 2;
outline: none;
}
.editor p:before {
display: inline-block;
width: 2em;
height: 100%;
border-right: 1px black solid;
padding-right: 1em;
margin-right: 1em;
content: counter(line);
color: #FFF;
background-color: #006;
text-align: right;
/*-webkit-user-select: none;
user-select: none;*/
}
<div class="editor" contenteditable="true" spellcheck="false">
<p>Some paragraph</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas aliquet nunc non pulvinar luctus. Cras finibus turpis at arcu mollis, nec fermentum mi pretium. Aliquam suscipit lacus sapien, eu fringilla enim malesuada quis. Sed ut tincidunt erat.
In posuere vulputate venenatis. Mauris quis porta magna. Phasellus pharetra in nisl et luctus. Etiam in ultrices risus. Morbi vel dapibus ex. Suspendisse gravida libero non malesuada congue. Pellentesque ut nunc diam.</p>
<p> </p>
<p> </p>
<p> </p>
</div>
The problem is that if the paragraph is a bit longer the rest of the text will go beneath my counter pseudoelement. I want to strech the :before counter to be the same height as the paragraph.
I have tried using position:relative
on the paragraph and position:absolute; height:100%
on the p:before pseudoelement like explained here: How can the pseudo element detect the height of the non-pseudo element?
This does not work in my case because I don't want the p:before element to go over and cover the paragraph, I just want the same behaviour as now, just want the p:before
element to strech at the same height as the main p
.
I also wouldn't want to have the line strech more than the width of the wrapper container. I've been trying many methods but failed to come to a solution.
Instead of height
, rather use position: relative;
for p
, and position: absolute;
for :before
.
Here are the newly added CSS properties:
.editor p {
position: relative;
padding-left: 3.5em;
.editor p:before {
position: absolute;
top: 0;
bottom: 0;
left: 0;
}
Edit
It should be a second question :D
Pressing Enter in IE will not create a br
, whereas in modern browsers it creates a br
using :after
. Here is to guarantee so that p
tag does not remain empty:
.editor {
display: inline-block;
border: 1px black solid;
font-family: "Consolas", "Monaco", "Courier New", monospace;
counter-reset: line;
width: 90%;
height: 350px;
overflow: scroll;
padding-left: 0;
margin-left: 0;
z-index: 1;
}
.editor p {
display: block;
counter-increment: line;
background-color: #FFF;
text-align: left;
margin: 0px;
z-index: 2;
outline: none;
position: relative;
padding-left: 3.5em;
}
.editor p:before {
display: inline-block;
width: 2em;
height: 100%;
border-right: 1px black solid;
padding-right: 1em;
margin-right: 1em;
content: counter(line);
color: #FFF;
background-color: #006;
text-align: right;
position: absolute;
top: 0;
bottom: 0;
left: 0;
/*-webkit-user-select: none;
user-select: none;*/
}
.editor p:after {
content: " "
}
<div class="editor" contenteditable="true" spellcheck="false">
<p>Some paragraph</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas aliquet nunc non pulvinar luctus. Cras finibus turpis at arcu mollis, nec fermentum mi pretium. Aliquam suscipit lacus sapien, eu fringilla enim malesuada quis. Sed ut tincidunt erat.
In posuere vulputate venenatis. Mauris quis porta magna. Phasellus pharetra in nisl et luctus. Etiam in ultrices risus. Morbi vel dapibus ex. Suspendisse gravida libero non malesuada congue. Pellentesque ut nunc diam.</p>
<p>one</p>
<p>two</p>
<p>three</p>
</div>