Here’s a focused QA pass for this USAGov homepage markup. I’ve prioritized issues that affect validity, accessibility, and performance, and included safe, drop-in fixes.


🔴 Must-fix (validity / a11y)

  1. Invalid/empty alt attributes and conflicting aria-hidden

There are several <img>s with alt but no value (invalid), or with real alt text and aria-hidden="true" (conflict). Decorative images: alt="" aria-hidden="true". Informative images: provide meaningful alt and remove aria-hidden.

<!-- BAD -->
<img class="usa-banner__icon" src="/themes/custom/usagov/assets/img/icon-dot-gov.svg" alt aria-hidden="true">

<!-- GOOD (decorative) -->
<img class="usa-banner__icon" src="/themes/custom/usagov/assets/img/icon-dot-gov.svg" alt="" aria-hidden="true">

<!-- BAD (conflict) -->
<img aria-hidden="true" class="usa-banner__header-flag" src="/themes/custom/usagov/images/favicon-57.png" alt="U.S. flag">

<!-- GOOD (either make it informative)… -->
<img class="usa-banner__header-flag" src="/themes/custom/usagov/images/favicon-57.png" alt="U.S. flag">
<!-- …or make it decorative) -->
<!-- <img class="usa-banner__header-flag" src="…" alt="" aria-hidden="true"> -->

Also fix other spots with alt but no value:

<img src="/themes/custom/usagov/images/topics/ICONS_Reimagined_Benefits.svg" alt="" height="56">
<img src="/themes/custom/usagov/images/Reimagined_Jump_to_Arrow.svg" alt="">
  1. Anchor styled as a button has role="button"

<a> should not carry role="button" unless it truly behaves as one (via JS). Here it’s a normal link, so remove the role.

<a href="/es/" class="usa-button language-link" hreflang="es">Español</a>
  1. Inline event handlers doing nothing useful

onfocus="this.placeholder" doesn’t change state and can confuse AT. Remove it (and prefer no placeholder on search if a label is present).

<input … type="search" name="query" placeholder="Search all government" autocomplete="off">

🟡 Accessibility & UX polish

  1. Add meaningful programmatic labels (buttons/icons)
  • Mobile/desktop “Close” buttons: keep visible text (you have it) and ensure the icon is decorative:
<button class="usa-nav__close" aria-label="Close menu">
  <img src="/themes/custom/usagov/assets/img/usa-icons/close.svg" alt="" aria-hidden="true">
</button>
  • The banner disclosure caret SVGs are decorative; add aria-hidden="true" (you already hide many via CSS):
<svg class="usa-banner_expand_arrow …" aria-hidden="true">…</svg>
  1. Better search labels

You have SR-only labels (“Search”)—great. Optionally make them more specific:

<label class="usa-sr-only" for="search-field-small">Search all U.S. government</label>
  1. Improve JSON-LD consistency

Your canonical is https://www.usa.gov/, but both JSON-LD blocks use https://usa.gov/ (no www). Align to canonical:

{
  "@context": "https://schema.org",
  "@type": "WebSite",
  "name": "USA.gov",
  "url": "https://www.usa.gov/"
}

…and:

{
  "@context": "https://schema.org",
  "@type": "Organization",
  "url": "https://www.usa.gov/",
  "logo": "https://www.usa.gov/themes/custom/usagov/images/Logo_USAGov.png"
}
  1. Social image alt text (assistive/social tooling)

Add descriptive alt for Open Graph/Twitter images.

<meta property="og:image:alt" content="USAGov logo">
<meta name="twitter:image:alt" content="USAGov logo">
  1. Give the Spanish switch a language hint

The “Español” link targets Spanish content—add lang to improve AT pronunciation.

<a href="/es/" class="usa-button language-link" hreflang="es" lang="es">Español</a>

⚡ Performance / stability

  1. Preconnect for site search (you already do script injection)

Slightly reduces latency for the search service:

<link rel="preconnect" href="https://search.usa.gov" crossorigin>
  1. Explicit HTTPS for third-party script

The Crazy Egg script uses a protocol-relative URL—make it explicit:

<script src="https://script.crazyegg.com/pages/scripts/0007/9651.js" async></script>
  1. Native lazy-loading for non-critical images

You already use a lazyload class; also add native loading="lazy" to inline <img> where below the fold (e.g., topic icons, footer art).

<img … alt="" loading="lazy">
  1. Prevent CLS for icon “tiles”

The topic “cards” use .homepage-icon as a background. Ensure those boxes have fixed dimensions/aspect-ratio in CSS (so layout doesn’t shift while background loads):

.homepage-icon {
  width: 56px; /* or whatever final size is */
  height: 56px;
  flex: 0 0 56px;
}

🧭 Semantics / consistency

  1. USWDS banner icon images

Where you have alt + aria-hidden="true" or alt without a value, normalize as “decorative”:

<img class="usa-banner__icon usa-media-block__img" src="…/icon-https.svg" alt="" aria-hidden="true">
  1. Improve <noscript> GTM iframe accessibility (optional)

You already added title="GTM" and sandbox. Consider aria-hidden="true" to keep it out of the virtual buffer:

<noscript>
  <iframe title="Analytics loader" aria-hidden="true" sandbox
          src="https://www.googletagmanager.com/ns.html?id=GTM-W8LW6DB"
          height="0" width="0" style="display:none;visibility:hidden"></iframe>
</noscript>

Quick copy-pastable fixes (bundle)

  • Images: replace all alt without value → alt=""; remove aria-hidden when alt is meaningful.
  • Español link: drop role="button", add lang="es".
  • Search inputs: remove onfocus="this.placeholder"; keep SR-only labels; optionally clarify label text.
  • JSON-LD: switch https://usa.gov/https://www.usa.gov/.
  • Open Graph/Twitter: add og:image:alt and twitter:image:alt.
  • Preconnect: add https://search.usa.gov.
  • CrazyEgg: use https:// URL.
  • Lazy: add loading="lazy" to non-critical <img>.
  • Icon containers: set fixed size (or aspect-ratio) to avoid CLS.

If you want, I can generate a minimal patch that only touches the affected lines (no structural changes).