axe-core icon indicating copy to clipboard operation
axe-core copied to clipboard

Incorrect reporting of target size violation from incorrect offset calculation

Open RyanBerliner opened this issue 2 years ago • 3 comments

Product

axe-core

Product Version

4.8.3

Latest Version

  • [X] I have tested the issue with the latest version of the product

Issue Description

Expectation

I would expect no target size violations to occur in the example.

Actual

The link labelled "Incorrectly flagged as target size violation" is in violation of target size, claiming it has 0 offset from both of the the other links.

IMG_2406

How to Reproduce

Unfortunately I was not able to reproduce this in jsfiddle (or the like), so the following html will need to be saved and opened as a file in your browser. All instructions to reproduce are in the comment in the code snippet.

<!DOCTYPE html>
<html lang="en-US">
	<head>
		<title>Target Size</title>
	</head>
​
	<body>
		<div style="max-width:290px">
			<p>
				<a href="#">lorem ipsum dolor</a>
				<a href="#">amet</a>
				<span>et dolore magna aliqua</span>
			</p>
			<a href="#" style="display: inline-block;">Incorrectly flagged as target size violation</a>
		</div>
	</body>
​
	<!--
​
	In your browser, do the following (could not replicate in jsfiddle or the like)
​
	1. Open this HTML file
	2. Open the devtools console on that page - the rest of the instruction will take place there.
	3. Paste in axe source to make the global `axe` available on the page
​
	   For example: https://www.unpkg.com/[email protected]/axe.min.js
​
	4. Configure axe to ONLY report on target size violations
​
		axe.configure({
			rules: [{id: 'target-size', enabled: true}],
			disableOtherRules: true
		})
​
	5. Run axe and print out the violations
​
		axe.run().then(r => console.log(r.violations));
​
	At this point you will observe that the last link is flagged as being in violation
	of target size. Specifically, it states that it has 0 offset from the other 2 links
	on the page, despite clearly being far away from them.
​
	This can be replicated in Chrome, Firefox, Safari
​
	-->
</html>

Additional context

The test case above is very carefully constructed. Here is what I found to be important about it specifically (and what is not)

  • the div must be sized such that the paragraph wraps to multiple lines
  • re: the first paragraph
    • The 2 links in here must be close enough to each other that they should be flagged as violating offset limitations if the were inline-block (its my understanding inline elements are not caught by axe present day for target-size violations?)
    • The text after the links must be wrapped in a span
    • This span must break in the middle as part of the wrapping forced by the div
  • The final link outside the paragraph must be display: inline-block;

RyanBerliner avatar Jan 05 '24 20:01 RyanBerliner

Thanks for the issue. I can replicate the bug.

Notes for myself: It seems that the issue is that the span tag is being counted as an overlapping node in get-target-rects and makes the function return an empty array when it tries to split-rects with the first anchor element in the paragraph and the span. Since the span fully overlaps the anchor there is no space in which they don't overlap so split-rects function returns empty.

// the <a href="#">lorem ipsum dolor</a> nodeRect
nodeRect =  {
    "x": 8,
    "y": 16,
    "width": 118.2109375,
    "height": 18.5,
    "top": 16,
    "right": 126.2109375,
    "bottom": 34.5,
    "left": 8
}
// the <span> element nodeRect
obscuringRects = [{
    "x": 8,
    "y": 16,
    "width": 260.375,
    "height": 37,
    "top": 16,
    "right": 268.375,
    "bottom": 53,
    "left": 8
}]

straker avatar Jan 08 '24 19:01 straker

See related https://github.com/dequelabs/axe-core/issues/4194 (same root cause manifesting as one part of a different issue)

dbjorge avatar Jan 08 '24 19:01 dbjorge

Please let me know if you'd appreciate me dedicating some time to work on a PR here, happy to help where I can.

RyanBerliner avatar Jan 09 '24 01:01 RyanBerliner