web-dev-qa-db-ja.com

Chromeのインライン要素のキャレットの位置と選択の高さ

Slate または ProseMirror を使用してエディターを作成しているときに、Chromeを使用してキャレットの位置と選択領域を囲むと、奇妙な動作が発生する場合があります。インライン要素を使用しています。問題1は下の最初の図に示されています。テキストカーソルの位置が「f」の後ろにある場合、キャレットは画像の上部に表示されます。問題2は2番目の画像にあります-テキストを選択すると表示されますインライン化された要素と同じ高さの強調表示された領域。この動作を制御して、代わりにテキストの位置にキャレットを表示し、テキストの周囲のスペースのみを強調表示する方法はあります(インライン画像が行を作成している場合でも)高さが大きい) caret position too highselection area too big

ここで、Firefoxからの動作を模倣したいと思います: enter image description hereenter image description here

ここで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を使用しています。

8
mowwwalker

まず、JQueryの例に示すように、ProseMirror DOMを操作しないでください。実際、DOMまたはコンテンツの問題に遭遇する可能性が最も高くなります。 ProseMirrorは独自のDOMノードとマークアップスキーマを使用します。 ProseMirror DOMを操作したり、プラグインを追加したりする場合は、マークアップ、プラグイン、およびNode Apisをご覧ください。マークアップコードをテキストで配置する簡単な例を添付しました。補足事項、文法の理由他の人がProseMirrorプラグインを持っていないのは、DOMのアプローチ/モデルが原因です。ProseMirrorは非常に優れていますが、正直に言うと、高度な開発者向けソリューションです。

それはさておき、CSSだけの問題は朗報です。 ProseMirrorはすべてのクラスを取り除き、DOM/CSSをリセットするため、ドキュメントをインポートしたり、すべてをカットアンドペーストしたりすると、ほとんどのクラスが失われます。

これを解決する最も簡単な方法は、エディターをdivでラップし、クラスをdivに割り当てて、そのクラスにスタイルと子スタイルを追加することです。ラップする理由は、img、p、hなどのCSSセレクターがエディタークラス内のタグにのみ適用されるためです。それがなければ、明らかなCSSの衝突が発生します。

[〜#〜] css [〜#〜]

  1. flexboxはインラインシステムではflexboxはグリッドシステムではないため、使用しないでください。実際、私が思い出すと、フレックスコンテナの直接の子をインライン化することはできません。
  2. pタグとimgのインラインはテキストを折り返さず、上記の問題が発生します。
  3. カーソルの問題を本当にラップして削除したい場合は、フロートを使用する必要があります。 float: left;(推奨されるアプローチ)
  4. 小さなまたは大きなパディングとボーダーボックスを追加して、エッジを折りたたむのに役立ち、画像とテキストの分離にも役立ちます
  5. 発生しているカーソルの問題は、画像ブロック内で上に垂直に配置されている場合、vertical-align: baseline;で修正できますが、フロートなしでは、テキストではなく画像の高さに一致するカーソルが残っているためです。 。また、フロートを使用しない場合、行の高さが画像と実質的に同じであるため、カーソルは長くなります。青色はセレクターにすぎず、CSSを使用しても変更できます。
<html>
    <div class="editor">
        <!--        <editor></editor>-->
    </div>
</html>

<style>
    .editor {
        position: relative;
        display: block;
        padding: 10px;
    }

    .editor p {
        font-weight: 400;
        font-size: 1rem;
        font-family: Roboto, Arial, serif;
        color: #777777;
        display: inline;
        vertical-align: baseline;
    }

    .editor img {
        width: 50px;
        float: left;
        padding: 20px;
    }

</style>

ノード拡張の例

Nodeの例です。ツールバーとして追加できるテキスト配置の拡張機能です。投稿はかなり長くなりますが、Node /画像のプラグインを作成した場合でもレンダリングの方法、つまりbase64とurlなどを処理する必要があります。これはなぜそうしたのかについては完全に理にかなっていますが、SEOなどを求める開発者に複雑さを追加するだけです。

export default class Paragraph extends Node {
    get name() {
        return 'paragraph';
    }

    get defaultOptions() {
        return {
            textAlign: ['left', 'center', 'right'],
        }
    }

    inputRules({ type }) {
        return [
            markInputRule(/(?:\*\*|__)([^*_]+)(?:\*\*|__)$/, type),
        ]
    }

    get schema() {
        return {
            attrs: {
                textAlign: {
                    default: 'left'
                }
            },
            content: 'inline*',
            group: 'block',
            draggable: false,
            inclusive: false,
            defining : true,
            parseDOM: [
                {
                    tag: 'p',
                    style: 'text-align',
                    getAttrs: value => value
                }
            ],

            toDOM: (node) => [ 'p', {
                style: 'text-align:' + node.attrs.textAlign,
                class: `type--base type--std text-` + node.attrs.textAlign
            }, 0 ]

        };
    }

    commands ({ type }) {
        return (attrs) => updateMark(type, attrs)
    }
}

0
Nolan