Положение каретки в contenteditable с большой высотой строки в Chrome - PullRequest
12 голосов
/ 01 июля 2019

Chrome в macOS и Chromium в Linux не размещают курсор в щелчке внутри редактируемой области для увеличения высоты строки.

В этом примере мы устанавливаем значение для line-height для <span> элементов. Оставить его и наследовать от родительского элемента невозможно из-за других требований приложения, в основном из-за использования Quill.js текстового редактора. Может быть несколько <span> на строку с разными размерами шрифта, но без вложенных элементов.

p {
  display: inline-block;
  margin: 0;
  background: lightgrey;
}
span {
  line-height: 2.5;
  font-size: 50px;
  background: lightblue;
}
span.small {
  font-size: 25px;
}
<p contenteditable><span>some </span><span class="small">text</span><br/><span>some text</span></p>

В Firefox, если вы щелкнете по серой области (отмечая элемент <p>), каретка всегда будет располагаться рядом с ближайшим символом. Если щелкнуть между строками, каретка также позиционируется разумно.

В Chrome каретка располагается у ближайшего символа, только если вы щелкнете внутри синей области (отмечая элемент). В серой области каретка заканчивается в начале следующей строки или в конце последней строки, если щелкнуть ниже последнего интервала.

Как можно воспроизвести поведение Firefox с помощью Chrome?

Примечание: предоставление пролетам display: inline-block в соответствии с рекомендациями здесь не решает проблему.

1 Ответ

5 голосов
/ 09 июля 2019

Как вы уже знаете, это связано с Chrome и тем, как он работает с высотой строки.

Хотя я написал обходной путь, который, похоже, хорошо работает в Linux (Chrome, Firefox), а также в Windows (Chrome, Firefox, Edge).

При vertical-align: text-bottom все строки, кажется, работают, как и предполагалось, кроме первой. Таким образом, идея состоит в том, чтобы добавить разрыв строки (и затем обнулить его с помощью font-size: 0)

p::before {
  content: "\A";
  white-space: pre;
  display: inline;
}

p::first-line {
  font-size: 0px;
}

Это очень хорошо работает в Chrome (как в Linux, так и в Windows), , но в Firefox. Мне не удалось отменить дополнительный разрыв строки. Итак, поскольку изначально все работало хорошо, я использовал правило firefox-only , чтобы скрыть дополнительный разрыв строки.

Итак, у нас есть обходной путь для Chrome и Firefox (как для Windows, так и для Linux) , но Edge столкнулся с некоторыми трудностями с vertical-align, поэтому (еще раз) я использовал только мс Правило unset vertical-align.

Результат (работает на Chrome Windows / Linux, Firefox Windows / Linux, Edge Windows)

p {
  display: inline-block;
  margin: 0;
  background: lightgrey;
  
}
span {
  line-height: 2.5;
  font-size: 30px;
  background: lightblue;
  vertical-align: text-bottom;
}

p::before {
  content: "\A";
  white-space: pre;
  display: inline;
}

p::first-line {
  font-size: 0px;
}

/*  Firefox only */
@-moz-document url-prefix() {
  p::before {
    display: none;
  }
}

/* Edge only */
@supports (-ms-ime-align:auto) {
  span {
    vertical-align: unset;
  }
}
<p contenteditable><span>some text</span><br/><span>some text</span></p>

UPDATE

В обновленном тестовом примере, когда у вас есть несколько размеров шрифта на строку, вам нужно будет пропустить vertical-align: bottom|text-bottom и пойти на компромисс с выделением дополнительного места для строки ниже (только в Chrome - Linux).

Обратите внимание, что вам все равно понадобится вышеупомянутый "хак" для первой строки, чтобы иметь согласованное поведение между всеми строками.

Посмотрите на этот codepen для обновленного теста.

...