A <label> element should have text content and be associated with a control.

Why is this an issue?

When a label element lacks text content or an associated control, it can lead to several issues:

  1. Poor Accessibility: Screen readers rely on correctly associated labels to describe the function of the form control. If the label is not properly associated with a control, it can make the form difficult or impossible for visually impaired users to understand or interact with.
  2. Confusing User Interface: Labels provide users with clear instructions about what information is required in a form control. Without a properly associated label, users might not understand what input is expected, leading to confusion and potential misuse of the form.
  3. Code Maintainability: Properly structured and labeled code is easier to read, understand, and maintain. When labels are not correctly associated, it can make the code more difficult to navigate and debug, especially for new developers or those unfamiliar with the codebase.

Control elements include:

Exceptions

Labels containing custom JSX components do not raise issues. Static analysis cannot determine whether a custom component eventually renders a control, so SonarJS treats it as an allowed exception.

How to fix it

Make sure the <label> has text that describes the control.

An implicit association wraps the control element inside the <label>. An explicit association keeps the label and control separate, and links them with the label’s for attribute and the control’s id. Both approaches are compliant. If you lack a control element, add one.

In JavaScript, this rule applies to JSX markup, so the examples below use JSX. In JSX, use htmlFor instead of for.

Code examples

Noncompliant code example

export function FavoriteFields() {
  return (
    <>
      {/* Non-compliant: label without text */}
      <label htmlFor="favorite-sport"></label>
      <input id="favorite-sport" type="text" />

      {/* Non-compliant: missing "htmlFor" attribute on label */}
      <label>Favorite food</label>
      <input id="favorite-food" type="text" />
    </>
  );
}

Compliant solution

export function FavoriteFields() {
  return (
    <>
      {/* Label with text */}
      <label htmlFor="favorite-sport">Favorite sport</label>
      <input id="favorite-sport" type="text" />

      {/* Explicit association */}
      <label htmlFor="favorite-food">Favorite food</label>
      <input id="favorite-food" type="text" />

      {/* Implicit association */}
      <label>
        Favorite place
        <input id="favorite-place" type="text" />
      </label>
    </>
  );
}

Resources

Documentation