猿问

Chrome 中内联元素的插入符位置和选择高度

我正在考虑使用SlateProseMirror构建一个编辑器,并在使用内联元素时在插入符号位置和选择区域周围看到 Chrome 的一些奇怪行为。问题 1 如下图所示。当文本光标位置位于“f”后面时,插入符号显示在图像顶部。问题 2 在第二张图片中 - 选择文本会显示一个与内联元素一样高的突出显示区域。有什么方法可以控制这种行为,而是让插入符号显示在文本位置,并仅突出显示文本周围的空间(即使内联图像使行高更大)

我想模仿 Firefox 的行为:

https://img1.sycdn.imooc.com/65ae59a30001d9a406520805.jpg

示例图像是使用此处的 ProseMirror 演示生成的:https ://prosemirror.net/examples/basic/

使用JSBin的最小示例(感谢@Kaiido):

<div contenteditable>Test text<img src="https://upload.wikimedia.org/wikipedia/en/9/9b/Yoda_Empire_Strikes_Back.png">Testing</div>

不确定这在其他操作系统上的表现如何,但我使用的是 macOS Catalina。


30秒到达战场
浏览 110回答 3
3回答

qq_笑_17

您可以使用 Flexbox 解决选择问题。我最初尝试使用,align-items: flex-end但我得到了一些奇怪的箭头键行为。align-items: baseline目前看来有效。图像问题很奇怪。我注意到 Chrome 对 SVG 元素的处理方式与 IMG 元素不同。截至目前,最新版本的 Chrome 在跳过 IMG 之前会“等待”,但允许用户像任何其他字符一样跳过 SVG(左箭头跳过最接近 svg 的字符)。这可能是由底层默认样式引起的,但我不知道。我正要发布我的发现,但我意识到 Firefox 的工作方式不一样。当使用 SVG 和/或 Flexbox 时,Firefox 有一些非常奇怪的箭头键行为。光标会移至图像上方,但仅当按向右箭头键时才会出现。然而,Firefox 可以很好地处理普通的 IMG 元素。长话短说,您将必须根据浏览器渲染不同的图像元素。// chrome contenteditable ads spaces between spans.// firefox does not, so you have to add them manually.if (navigator.userAgent.indexOf("Firefox") > 0) {&nbsp; Array.from(document.querySelectorAll('#editable span')).forEach(el => {&nbsp; &nbsp; el.innerHTML += " "&nbsp; })}.flexit {&nbsp; display: flex;&nbsp; align-items: baseline;&nbsp; flex-wrap: wrap;}span {&nbsp;display: inline-block;&nbsp;white-space: pre;}.img-wrapper, .img-wrapper + span {display: inline;}<!DOCTYPE html><html><head>&nbsp; <meta charset="utf-8">&nbsp; <meta name="viewport" content="width=device-width">&nbsp; <title>JS Bin</title></head><body>&nbsp; <h1>chrome</h1>&nbsp; <div contenteditable="true" class="flexit">&nbsp; &nbsp; <span>test</span><svg width="200" height="200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; <image href="https://mdn.mozillademos.org/files/6457/mdn_logo_only_color.png" height="200" width="200"/>&nbsp; &nbsp; </svg><span>Here</span><span>is</span><span>a</span><span>longer</span><span>sentence.</span><span>Notice</span><span>I</span><span>wrapped</span><span>each</span><span>word</span><span>in</span><span>a</span><span>span.</span><span>This</span><span>makes</span><span>the</span><span>text</span><span>appear</span><span>like</span><span>it</span><span>is</span><span>inline.</span>&nbsp; </div>&nbsp; <h1>firefox</h1>&nbsp; <div contenteditable="true" id="editable">&nbsp; &nbsp; <span>test</span><span class="img-wrapper"><img src="https://mdn.mozillademos.org/files/6457/mdn_logo_only_color.png" height="200" width="200" /></span><span>test</span><span>Here</span><span>is</span><span>a</span><span>longer</span><span>sentence.</span><span>Notice</span><span>I</span><span>wrapped</span><span>each</span><span>word</span><span>in</span><span>a</span><span>span.</span><span>This</span><span>makes</span><span>the</span><span>text</span><span>appear</span><span>like</span><span>it</span><span>is</span><span>inline.</span>&nbsp; </div></body></html>PS 很多编辑器我都使用默认的全角图像。编辑:我刚刚意识到我的 Firefox 解决方案似乎也适用于最新的 Chrome。我认为这是可行的,因为我将文本节点包装在 SPAN 元素中。SVG 元素在 Chrome 中的工作方式仍然不同,但在 SPAN 中换行文本似乎解决了大部分问题。

慕工程0101907

首先,不要像 JQuery 示例中所示操作 ProseMirror DOM。事实上,您很可能会遇到 DOM 或内容问题。ProseMirror 使用自己的 DOM 节点和标记架构。如果您想操作 ProseMirror DOM 或添加插件,请查看标记、插件和节点 API。我附上了一个简单的文本对齐标记代码示例。旁注,Grammarly 和其他人没有 ProseMirror 插件的原因是 DOM 方法/模型。我应该补充一点,ProseMirror 非常好,但说实话,它更像是一个高级开发人员解决方案。除此之外,好消息是你有一个纯粹的 CSS 问题。ProseMirror 会删除所有类并重置 DOM / CSS,因此如果您导入文档或剪切并粘贴所有/大多数类,您的类将会消失。解决这个问题的最简单方法是将编辑器包装在 div 中,并为该 div 分配一个类,然后向该类添加样式和子样式。包装它的原因是像 img、p、h 等 css 选择器仅适用于编辑器类内部的标签。如果没有它,你最终会出现明显的 CSS 冲突。CSS不要将 Flexbox 用于内联图像,因为 Flexbox 不是网格系统。事实上,如果我记得你不能内联弹性容器的直接子级。p 标签和 img 上的内联不会自动换行,您最终会遇到上面列出的问题。如果您想真正包装并删除光标问题,那么您需要使用浮点数,例如float: left;(推荐方法)添加小或大的填充和边框以帮助折叠边缘,还有助于分离图像和文本您遇到的光标问题是因为当您在图像块内时,它垂直与顶部对齐,您可以使用vertical-align: baseline;但不使用浮动来修复该问题,您仍然会有一个与图像高度而不是文本高度匹配的光标。另外,如果不使用浮动,光标将被拉长,因为行高实际上与图像的高度相同。蓝色只是选择器,您也可以使用 CSS 进行更改。<html>&nbsp; &nbsp; <div class="editor">&nbsp; &nbsp; &nbsp; &nbsp; <!--&nbsp; &nbsp; &nbsp; &nbsp; <editor></editor>-->&nbsp; &nbsp; </div></html><style>&nbsp; &nbsp; .editor {&nbsp; &nbsp; &nbsp; &nbsp; position: relative;&nbsp; &nbsp; &nbsp; &nbsp; display: block;&nbsp; &nbsp; &nbsp; &nbsp; padding: 10px;&nbsp; &nbsp; }&nbsp; &nbsp; .editor p {&nbsp; &nbsp; &nbsp; &nbsp; font-weight: 400;&nbsp; &nbsp; &nbsp; &nbsp; font-size: 1rem;&nbsp; &nbsp; &nbsp; &nbsp; font-family: Roboto, Arial, serif;&nbsp; &nbsp; &nbsp; &nbsp; color: #777777;&nbsp; &nbsp; &nbsp; &nbsp; display: inline;&nbsp; &nbsp; &nbsp; &nbsp; vertical-align: baseline;&nbsp; &nbsp; }&nbsp; &nbsp; .editor img {&nbsp; &nbsp; &nbsp; &nbsp; width: 50px;&nbsp; &nbsp; &nbsp; &nbsp; float: left;&nbsp; &nbsp; &nbsp; &nbsp; padding: 20px;&nbsp; &nbsp; }</style>节点扩展示例可添加为工具栏的文本对齐节点扩展示例。更长的帖子,但即使你确实为图像创建了一个节点/插件,你也必须处理它渲染的方式,即 base64 与 url 等。顺便说一句,这对于他们这样做的原因非常有意义,但只需添加寻求 SEO 等的开发人员的复杂性export default class Paragraph extends Node {&nbsp; &nbsp; get name() {&nbsp; &nbsp; &nbsp; &nbsp; return 'paragraph';&nbsp; &nbsp; }&nbsp; &nbsp; get defaultOptions() {&nbsp; &nbsp; &nbsp; &nbsp; return {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; textAlign: ['left', 'center', 'right'],&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; inputRules({ type }) {&nbsp; &nbsp; &nbsp; &nbsp; return [&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; markInputRule(/(?:\*\*|__)([^*_]+)(?:\*\*|__)$/, type),&nbsp; &nbsp; &nbsp; &nbsp; ]&nbsp; &nbsp; }&nbsp; &nbsp; get schema() {&nbsp; &nbsp; &nbsp; &nbsp; return {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; attrs: {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; textAlign: {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; default: 'left'&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; },&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; content: 'inline*',&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; group: 'block',&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; draggable: false,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; inclusive: false,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; defining : true,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; parseDOM: [&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tag: 'p',&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; style: 'text-align',&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; getAttrs: value => value&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ],&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; toDOM: (node) => [ 'p', {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; style: 'text-align:' + node.attrs.textAlign,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; class: `type--base type--std text-` + node.attrs.textAlign&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }, 0 ]&nbsp; &nbsp; &nbsp; &nbsp; };&nbsp; &nbsp; }&nbsp; &nbsp; commands ({ type }) {&nbsp; &nbsp; &nbsp; &nbsp; return (attrs) => updateMark(type, attrs)&nbsp; &nbsp; }}

慕哥9229398

我尝试用 HTML 和 css 进行一些修改。<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width"><title>JS Bin</title></head><body><div contenteditable><p class="new1" contenteditable>Hello</p><div contenteditable>&nbsp;<img src="https://upload.wikimedia.org/wikipedia/en/9/9b/Yoda_Empire_Strikes_Back.png"></div>&nbsp;<p class="new2">Testing</p></div></body></html>//CSS.new2{font-size:30px;margin-top:-35px;margin-left:252px;padding-left:79px;}img{margin-left:75px;padding-left:5px;padding-right:5px;margin-top:-300px;}.new1{text-overflow:hidden;padding-top:260px;margin-bottom:-20px;font-size:30px;padding-right:10px;}这是jsfiddle&nbsp;https://jsfiddle.net/wtekxavm/1/
随时随地看视频慕课网APP

相关分类

Html5
我要回答