Problem/Motivation

The lms:course_card SDC produces two distinct links per card. On the /courses catalog (and any other view using this component), each card renders:

  • An invisible, absolutely positioned overlay <a> covering the entire card and linking to the course group page (/group/{id}), with an aria-label of "View course: [title]".
  • A <span class="visually-hidden"> inside that overlay link that duplicates the aria-label text verbatim. Since aria-label takes precedence in the accessible-name computation, this span is never reached by assistive tech.
  • An <h2> course title that is not inside any link.
  • A separate Start/Revisit link in the card footer linking to /course/{id}/start.

This produces several accessibility problems:

  • Redundant tab stops. Keyboard users encounter two tab stops per card: one for the overlay link, one for the Start/Revisit link. On a 12-card catalog that's 24 tab stops instead of 12.
  • Context-free action link. The Start/Revisit link's accessible name is just "Start", "Revisit", or similar, with no course name included. Screen reader users scanning a link list can't tell which course each action link belongs to. This is a WCAG 2.4.4 failure.
  • Unlinked title heading. The <h2> course title is not a link. A screen reader user navigating by heading lands on "Course 1" with no way to activate it from that position; to reach the card link they have to reverse-navigate to find the preceding overlay link.
  • Dead markup. The <span class="visually-hidden"> inside the overlay anchor is unreachable by assistive tech and serves no purpose.

Steps to reproduce

  1. Install the LMS module with at least one course, and go to /courses.
  2. Open DevTools and inspect a .lms-course-card element. You'll see the overlay <a class="lms-course-card__link"> containing a visually-hidden span that duplicates the link's own aria-label.
  3. Tab through the page. Each course card takes two tab stops.
  4. Open a screen reader's link list (e.g. VoiceOver rotor, NVDA element list). The "Start" and "Revisit" links don't name the course they belong to.
  5. Navigate by headings. You'll land on each <h2> course title, but there's no link to activate from that position.

Proposed resolution

Remove the redundant visually-hidden span. Restructure the card so the course title serves as the primary navigation link, the Start/Revisit action is a separately labeled link that includes the course name in its accessible name, and the full-card clickable affordance is preserved for mouse users.

Remaining tasks

  • Create an issue fork and open a merge request against 1.1.x.
  • Maintainer review.

User interface changes

Visual appearance of the card is unchanged. Keyboard and screen reader behavior changes: tab stops per card are reduced from two to one for the primary action, and Start/Revisit links gain course-name context.

API changes

None anticipated. Implementation details to be confirmed in the merge request.

Data model changes

None.

Issue fork lms-3586911

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

mindewen created an issue. See original summary.

mindewen’s picture

Issue summary: View changes
Status: Active » Needs review

graber made their first commit to this issue’s fork.

  • graber committed b6dc98f3 on 1.1.x authored by mindewen
    #3586911: Fix overlay-link card pattern in course_card SDC
    
graber’s picture

Status: Needs review » Fixed

Thank you, fixed come csslint issues and merged.

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.