Row-Level Edit Mode Versus Cell-Level Editing

Permalink to "Row-Level Edit Mode Versus Cell-Level Editing"

Editable grids typically offer one of two models. In cell-level editing, users edit one cell at a time: Enter or F2 opens an editor in the cell, Enter commits, Escape cancels. In row-level editing, an “Edit” action turns the whole row into form fields, with Save and Cancel buttons; changes commit together. Both can be accessible, but they suit different data and have different focus, validation and announcement needs. Mixing them inconsistently across a product confuses everyone.

This guide belongs to inline editing & form controls.

Spec reference

Permalink to "Spec reference"
  • SC 3.3.1, 3.3.3 (A, AA) — errors identified and suggestions given, per field.
  • SC 4.1.2 (A) — editors and buttons named; row edit state exposed.
  • SC 2.4.3 (A) — focus enters and leaves edit mode predictably.
  • SC 3.3.4 (AA) — for consequential data, review before submission (row Save provides a natural point).
  • SC 4.1.3 (AA) — save results announced.
Cell-level versus row-level editing Comparison: cell-level editing suits quick independent changes with immediate commits; row-level editing suits records with dependent fields, validated and saved together. Cell-level versus row-level editing✗ Cell-level editingOne value at a timeEnter commits immediatelyEscape cancels one cellValidation per cellFast for spreadsheets✓ Row-level editingSeveral fields at onceSave commits the rowCancel discards all changesValidation per field plus summaryClear for records with rules

When to use — and when not to

Permalink to "When to use — and when not to"

Use cell-level editing for independent values — quantities, prices, statuses — and spreadsheet-like workflows. Use row-level editing when fields depend on each other (start and end dates, currency and amount), when changes should be reviewed together, or when edits trigger expensive server validation.

Do not mix both models in one grid without a clear visual and textual indication. The misapplication: a grid where some columns edit in place and others open a row form, with no indication which is which.

Choosing the editing model Flow: are fields independent? Cell-level editing. Do fields depend on each other or need review? Row-level editing. Are edits complex or long-form? Edit in a dialog or detail pane instead. Choosing the editing modelIndependent values?quantity, status, pricecell-levelDependent fields?dates, currency and amountrow-levelNeed review before save?financial or legal datarow-level with SaveComplex or long text?descriptions, attachmentsdialog or detail pane

Annotated code example

Permalink to "Annotated code example"
<!-- Row in edit mode: fields labelled by their column headers -->
<tr data-editing="true" aria-describedby="row-42-errors">
  <th scope="row">INV-1042</th>
  <td><label class="visually-hidden" for="due-42">Due date</label>
      <input id="due-42" type="date" value="2026-10-15" aria-describedby="due-42-err"></td>
  <td><label class="visually-hidden" for="amt-42">Amount (EUR)</label>
      <input id="amt-42" inputmode="decimal" value="1240.00"></td>
  <td>
    <button type="button" id="save-42">Save INV-1042</button>
    <button type="button" id="cancel-42">Cancel editing INV-1042</button>
  </td>
</tr>
<p id="row-42-errors" class="error-summary" hidden></p>
function enterRowEdit(row) {
  renderRowEditors(row);
  row.querySelector('input, select, textarea').focus();               // first field (SC 2.4.3)
  status.textContent = `Editing ${row.dataset.id}. Save or Cancel when done.`;
}
async function saveRow(row) {
  const errors = validateRow(row);                                     // per field (SC 3.3.1)
  if (errors.length) { showFieldErrors(errors); focusFirstError(errors); return; }
  await api.save(row.dataset.id, valuesOf(row));
  exitRowEdit(row);
  row.querySelector('th').focus();                                     // back to the row header
  status.textContent = `${row.dataset.id} saved.`;                     // SC 4.1.3
}

Keyboard & AT behaviour

Permalink to "Keyboard & AT behaviour"
Model Key Expected Announcement
Cell Enter / F2 Edit cell “edit, 1,240.00”
Cell Enter Commit Cell value
Cell Escape Cancel Original value
Row Enter on Edit Fields appear; focus first field “Editing INV-1042…”
Row Tab Next field, then Save, Cancel Field labels
Row Save with errors Focus first error Error text
Row Save Exit; focus row header “INV-1042 saved.”
Row Escape or Cancel Discard; focus row header “Changes discarded.”
Editing models and their accessibility trade-offs Matrix of concerns — speed, error handling, dependent fields, keyboard model complexity, undo — against cell-level and row-level editing. Editing models and their accessibility trade-offsCell-levelRow-levelSpeed for single changesFastSlowerError handlingPer cellPer field plus summaryDependent fieldsAwkwardNaturalKeyboard modelGrid modesStandard form Tab orderUndoPer cellCancel before save
Neither is better everywhere; choose per grid and be consistent.

Integration context

Permalink to "Integration context"

Cell-level details are in entering and exiting cell edit mode and inline form validation inside editable table cells. Undo for both models is covered in undo and cancel affordances for inline cell edits. Spreadsheet-style entry, the extreme of cell-level editing, is in Enter and Tab data entry in spreadsheet grids.

Gotchas

Permalink to "Gotchas"

Unsaved changes. Navigating away from a row in edit mode should prompt or auto-save; never discard silently.

Grid keyboard model in row edit. In a role="grid", row edit mode must suspend arrow-key navigation so arrows work inside inputs.

Labels. Inputs inside cells need labels — visually hidden labels or aria-labelledby to the column header and row header.

Worked example

Permalink to "Worked example"

An HR grid mixed cell-level editing for status and row-level editing for contract dates without indication, and contract date errors appeared only as red borders. Screen reader users could not tell which model applied or why saves failed. The team switched the whole grid to row-level editing (fields depend on each other), labelled inputs with column names, named Save and Cancel with the employee, summarised errors with links to fields, and announced saves. Cell-level editing remained in a separate quick-status grid where it fit better.

Common mistakes

Permalink to "Common mistakes"
  • Mixed models without indication.
  • Unlabelled inputs in edit rows.
  • Errors shown only by colour.
  • Focus left on removed Save buttons.

Testing checklist

Permalink to "Testing checklist"

Design system notes

Permalink to "Design system notes"

Offer editMode: 'cell' | 'row' at grid level with built-in focus handling, labels from column definitions and messages. Discourage mixing within one grid.

Step-by-step implementation

Permalink to "Step-by-step implementation"
  1. Pick one model per grid. Row-level edit mode suits forms with validation across fields; cell-level editing suits spreadsheet-like data entry. Mixing both in one grid confuses users about when a change is saved.
  2. Row-level: enter and exit explicitly. An “Edit” button turns the row’s cells into labelled inputs and shows Save and Cancel. Focus moves to the first input; Save returns focus to the Edit button and announces “Row saved”.
  3. Cell-level: Enter or F2 to edit. In a grid, Enter or F2 opens the editor in place; Enter commits and moves down, Escape cancels, Tab commits and moves right.
  4. Label every editor. Inputs inside cells need names that include row and column context, such as “Amount for INV-1042”, because the visible column header is not automatically the input’s label.
  5. Surface validation where the user is. Errors appear next to the field with aria-describedby and aria-invalid; in row mode, Save is blocked and focus moves to the first invalid field.

Edge cases

Permalink to "Edge cases"
  • Navigating away mid-edit. Decide whether leaving a row commits or discards; then tell users, and never discard silently.
  • Concurrent edits. If another user saved the row, show the conflict and offer to keep yours or theirs.
  • Read-only cells. In row mode, read-only cells stay as text with aria-readonly on the cell, not as disabled inputs that clutter the tab order.

FAQ

Permalink to "FAQ"
Which model is more accessible?

Both can be. Row-level uses familiar form behaviour; cell-level is faster for spreadsheets. Choose by data.

Should Enter save a row in row edit mode?

Enter in a single-line input can submit the row if documented; many teams require the Save button to avoid accidental saves.

How should errors be presented in row mode?

Inline per field and a short summary linked to fields, with focus to the first error.

Can row edit open in a dialog instead?

For long forms, yes; then dialog focus rules apply.

How do I indicate a row is in edit mode?

Visually (border, background plus text) and in the row’s description or a status message.

What about bulk editing several rows?

Use a bulk edit dialog with fields that apply to selected rows, and summarise results.

Permalink to "Related"

← Back to Inline Editing & Form Controls in Data Tables