formatOutdent

How formatOutdent inputType decreases indentation of paragraphs and varies across browsers.

Overview

The formatOutdent inputType is triggered when the user decreases indentation of selected paragraphs (typically via Shift + Tab or toolbar button). The browser decreases the left margin or padding of the affected elements.

Basic Behavior

Scenario: Indented paragraph selected

Before (Indented paragraph selected)

HTML:
<p style="margin-left: 40px;">This is an indented paragraph.</p>

After formatOutdent

HTML:
<p>This is an indented paragraph.</p>
Left margin decreased (outdented)

Difference from formatIndent

formatOutdent (Shift + Tab)

  • Decreases indentation (moves left)
  • Cannot go below 0 indent

formatIndent (Tab)

  • Increases indentation (moves right)
  • Can increase indefinitely

Editor-Specific Handling

Different editor frameworks handle outdentation similarly to indentation. Here's how major editors implement formatOutdent:

Slate.js

Outdentation

Slate decreases indent level:

    import { Editor, Transforms, Element } from 'slate';

element.addEventListener('beforeinput', (e) => {
  if (e.inputType === 'formatOutdent') {
    e.preventDefault();
    
    // Get current indent level
    const [match] = Editor.nodes(editor, {
      match: n => Element.isElement(n) && Editor.isBlock(editor, n),
    });
    
    const currentIndent = match?.[0]?.indent || 0;
    
    // Decrease indent (minimum 0)
    Transforms.setNodes(editor, {
      indent: Math.max(0, currentIndent - 1),
    }, {
      match: n => Element.isElement(n) && Editor.isBlock(editor, n),
    });
  }
});
  
  • Decremental: Decreases indent level by 1, minimum 0.
  • Same pattern: Uses same Transforms API as formatIndent.
ProseMirror

Outdentation

ProseMirror decreases indent attribute:

    view.dom.addEventListener('beforeinput', (e) => {
  if (e.inputType === 'formatOutdent') {
    e.preventDefault();
    const { state, dispatch } = view;
    const { $from } = state.selection;
    
    // Get current indent
    const currentIndent = $from.node(-1)?.attrs.indent || 0;
    
    // Decrease indent (minimum 0)
    const tr = state.tr.setNodeMarkup($from.before(-1), null, {
      ...$from.node(-1).attrs,
      indent: Math.max(0, currentIndent - 1),
    });
    
    dispatch(tr);
  }
});
  
  • Minimum check: Ensures indent does not go below 0.
Draft.js

Outdentation

Draft.js handles Shift+Tab:

    import { EditorState, RichUtils } from 'draft-js';

function handleOutdent(editorState) {
  // Draft.js may use block-level styles or custom block types for outdentation
  return RichUtils.onTab({ preventDefault: () => {}, shiftKey: true }, editorState, 4);
}

element.addEventListener('beforeinput', (e) => {
  if (e.inputType === 'formatOutdent') {
    e.preventDefault();
    const newState = handleOutdent(editorState);
    setEditorState(newState);
  }
});
  
  • Shift+Tab: Uses RichUtils.onTab() with shiftKey flag.

Related resources