You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何判断contenteditable光标是否在{ }内及实现CSS编辑器自动缩进

Hey there! I’ve built similar code editor features before, so let’s break this down into two key parts: checking if the cursor is inside curly braces, and adding automatic tab indentation when hitting Enter. Here’s how to make it work reliably.

1. 判断光标是否处于 { } 范围内

The core challenge here is handling nested braces (like in nested CSS rules or media queries) and making sure we’re checking the correct pair. We’ll use the browser’s Selection and Range APIs to get the cursor position, then scan the text to find the matching brace pair.

Here’s a robust function to do this:

function isCursorInsideBraces(editableElement) {
  const selection = window.getSelection();
  if (selection.rangeCount === 0) return false;
  
  const range = selection.getRangeAt(0);
  const fullText = editableElement.textContent;
  const cursorPos = range.startOffset;

  // Step 1: Find the nearest unclosed opening brace before the cursor
  let openBraceIndex = -1;
  let closeBraceCounter = 0;
  for (let i = cursorPos - 1; i >= 0; i--) {
    if (fullText[i] === '}') {
      closeBraceCounter++;
    } else if (fullText[i] === '{') {
      if (closeBraceCounter === 0) {
        openBraceIndex = i;
        break;
      } else {
        closeBraceCounter--;
      }
    }
  }

  if (openBraceIndex === -1) return false;

  // Step 2: Find the matching closing brace after the cursor
  let closeBraceIndex = -1;
  let openBraceCounter = 0;
  for (let i = cursorPos; i < fullText.length; i++) {
    if (fullText[i] === '{') {
      openBraceCounter++;
    } else if (fullText[i] === '}') {
      if (openBraceCounter === 0) {
        closeBraceIndex = i;
        break;
      } else {
        openBraceCounter--;
      }
    }
  }

  // Return true if we found a matching pair and cursor is between them
  return closeBraceIndex !== -1 && cursorPos > openBraceIndex && cursorPos < closeBraceIndex;
}

This function counts nested braces to avoid false positives—so it won’t think you’re inside an outer brace pair when you’re actually in a nested one.

2. 实现换行自动添加Tab缩进

Once we can detect the cursor’s position, we’ll listen for the Enter key press, block the default behavior, and insert a newline plus tab (or spaces, if you prefer) instead.

Add this event listener to your contenteditable element:

const cssEditor = document.querySelector('[contenteditable="true"]');

cssEditor.addEventListener('keydown', (e) => {
  if (e.key === 'Enter') {
    // Check if we're inside curly braces first
    if (isCursorInsideBraces(cssEditor)) {
      e.preventDefault(); // Stop the default newline behavior
      
      const selection = window.getSelection();
      const range = selection.getRangeAt(0);

      // Define your indentation (use '  ' for 2 spaces if needed)
      const indent = '\t';
      const newLineWithIndent = '\n' + indent;

      // Insert the custom newline + indent
      range.deleteContents();
      const textNode = document.createTextNode(newLineWithIndent);
      range.insertNode(textNode);

      // Move the cursor to the end of the inserted text
      range.setStartAfter(textNode);
      range.setEndAfter(textNode);
      selection.removeAllRanges();
      selection.addRange(range);
    }
  }
});

This will insert a tab immediately after the newline, and place the cursor right after the indent—perfect for writing CSS rules.

3. 处理边界情况

A few edge cases to test and tweak if needed:

  • Empty braces: If your cursor is between { and }, hitting Enter should still insert the indent (the code above handles this fine).
  • Cursor at brace edges: If the cursor is right after { or right before }, the isCursorInsideBraces function will still return true (which is correct).
  • Custom indentation: Swap '\t' for ' ' (four spaces) if your team uses space-based indentation.

内容的提问来源于stack exchange,提问作者Seann

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:11:09