diff --git a/__tests__/src/rules/control-has-associated-label-test.js b/__tests__/src/rules/control-has-associated-label-test.js
index de98d8728..17482d4ea 100644
--- a/__tests__/src/rules/control-has-associated-label-test.js
+++ b/__tests__/src/rules/control-has-associated-label-test.js
@@ -311,3 +311,15 @@ ruleTester.run(`${ruleName}:strict`, rule, {
.map(ruleOptionsMapperFactory(strictOptions))
.map(parserOptionsMapper),
});
+
+ruleTester.run(`${ruleName}:no-config`, rule, {
+ valid: [
+ { code: '' },
+ { code: '' },
+ ]
+ .map(parserOptionsMapper),
+ invalid: [
+ { code: '', errors: [expectedError] },
+ ]
+ .map(parserOptionsMapper),
+});
diff --git a/src/rules/control-has-associated-label.js b/src/rules/control-has-associated-label.js
index cab2611d4..481aa3bb0 100644
--- a/src/rules/control-has-associated-label.js
+++ b/src/rules/control-has-associated-label.js
@@ -15,6 +15,7 @@ import includes from 'array-includes';
import { generateObjSchema, arraySchema } from '../util/schemas';
import type { ESLintContext } from '../../flow/eslint';
import isDOMElement from '../util/isDOMElement';
+import isHiddenFromScreenReader from '../util/isHiddenFromScreenReader';
import isInteractiveElement from '../util/isInteractiveElement';
import isInteractiveRole from '../util/isInteractiveRole';
import mayHaveAccessibleLabel from '../util/mayHaveAccessibleLabel';
@@ -67,10 +68,15 @@ module.exports = {
}
const props = node.openingElement.attributes;
const nodeIsDOMElement = isDOMElement(tag);
+ const nodeIsHiddenFromScreenReader = isHiddenFromScreenReader(tag, props);
const nodeIsInteractiveElement = isInteractiveElement(tag, props);
const nodeIsInteractiveRole = isInteractiveRole(tag, props);
const nodeIsControlComponent = controlComponents.indexOf(tag) > -1;
+ if (nodeIsHiddenFromScreenReader) {
+ return;
+ }
+
let hasAccessibleLabel = true;
if (
nodeIsInteractiveElement