4

I have an editable div with :before and :after css pseudo-elements.

The :before sets a prompt in the div
The :after acts like a placeholder

When the user clicks in an empty div, the cursor is placed before the "prompt" content.
Once the user starts typing the :after content disappears and the cursor is in the right spot.

Is there a way to have the cursor positioned after the content when an empty div is selected? What is interesting is if there is any text in the div and you select the div the cursor goes to the end (as I want).

Any thoughts/help would be most appreciated.

div[data-prompt][contenteditable=true]:before {
  content: attr(data-prompt);
  font-family: 'Open Sans', sans-serif;
  color: black;
}

div[data-placeholder]:empty:after {
  content: attr(data-placeholder);
  color: black;
}
<div contenteditable='true' id="tbl01_r2c2" data-type="2" data-prompt="I will " data-placeholder="..."></div>

Cursor position when empty div is selected

enter image description here

Also note that the "prompt" will not always be the same length.

PeterB
  • 43
  • 5

1 Answers1

5

You can consider text-indent and some translation to control the cursor position. Apply this only when the div is :empty

div[data-prompt][contenteditable=true]:before {
  content: attr(data-prompt);
  font-family: 'Open Sans', sans-serif;
  color: black;
}

div[data-placeholder]:empty:after {
  content: attr(data-placeholder);
  color: black;
  /* added */
  display: inline-block;
  transform: translateX(-28px);
  text-indent: 0;
  /**/
}

/* added */
div[data-placeholder]:empty {
  text-indent: 38px;
}
div[data-prompt][contenteditable=true]:empty:before {
  display: inline-block;
  transform: translateX(-37px);
  text-indent: 0;
}
/**/

div[data-prompt][contenteditable=true] {
  border: 1px solid;
}
<div contenteditable='true' id="tbl01_r2c2" data-type="2" data-prompt="I will " data-placeholder="..."></div>

For a more generic way you can rely on CSS variables:

div[data-prompt][contenteditable=true]:before {
  content: attr(data-prompt);
  font-family: 'Open Sans', sans-serif;
  color: black;
}

div[data-placeholder]:empty:after {
  content: attr(data-placeholder);
  color: black;
  /* added */
  display: inline-block;
  transform: translateX(calc(10px - var(--d)));
  text-indent: 0;
  /**/
}

/* added */
div[data-placeholder]:empty {
  text-indent: var(--d);
}
div[data-prompt][contenteditable=true]:empty:before {
  display: inline-block;
  transform: translateX(calc(1px - var(--d)));
  text-indent: 0;
}
/**/

div[data-prompt][contenteditable=true] {
  border: 1px solid;
}
<div style="--d:37px;" contenteditable='true' id="tbl01_r2c2" data-type="2" data-prompt="I will " data-placeholder="..."></div>


<div style="--d:64px;" contenteditable='true' id="tbl01_r2c2" data-type="2" data-prompt="I will not " data-placeholder="..."></div>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
  • Thanks for your solution. Can you think of a way to make it a bit more dynamic? By that I mean to allow for different prompt lengths. – PeterB Mar 27 '20 at 09:03