1) Fix generic link text in the hero carousel
Buttons like “Read more here” are not descriptive for screen readers and hurt SEO.
Change (per slide):
<!-- BEFORE -->
<a class="carousel-link usa-button" href="/articles/...">Read more here</a>
<!-- AFTER -->
<a class="carousel-link usa-button" href="/articles/...">
Read more: Unleashing American Energy in Alaska
</a>
(Repeat for each slide with the actual headline.)
2) Respect reduced-motion in carousels & decorative animations
Provide a no-motion experience and keep animation from stealing focus.
@media (prefers-reduced-motion: reduce) {
.splide__track, .splide__list, .splide__slide,
.splide__progress__bar { animation: none !important; transition: none !important; }
}
Also ensure your “Play/Pause” button reflects state:
// After initializing Splide
toggleBtn.addEventListener('click', () => {
toggleBtn.setAttribute('aria-pressed', splide.Components.Autoplay.isPaused());
});
3) Make the hero background an actual LCP image
Your LCP is likely the large CSS background image. Browsers can’t prioritize it well.
Markup approach (keeps visual design, improves LCP):
<!-- Inside .carousel-hero -->
<img
src="/sites/default/files/2025-06/17S1_Alaska_SEC.png"
alt=""
fetchpriority="high"
decoding="async"
width="1350" height="759"
class="visually-hidden lcp-helper"
/>
…then keep your existing background CSS. The hidden <img> gives the browser a concrete LCP candidate it can preload/prioritize.
(If you’d rather not add the helper image, add an HTTP/2 server push/preload header for the hero. But the inline <img> is simpler and usually wins.)
4) Ensure all decorative images are truly decorative
Several cards/collections include thumbnails that repeat the title next to them.
If an image is purely decorative:
<img src="/.../supercomputing-homepage-hero_0.jpg" alt="" aria-hidden="true" ...>
Keep meaningful alt where an image conveys content not present in nearby text (your social icons already include hidden text—nice).
5) Mega menu & search toggles: keep ARIA state accurate
You’re using USWDS accordions. Check that the toggles update aria-expanded on open/close, especially the mobile search buttons (megamenu-search-btn[-mobile]). If any are toggled purely by class, add a line to sync ARIA:
const btn = document.getElementById('megamenu-search-btn');
const panel = document.getElementById('search-nav');
btn.addEventListener('click', () => {
const expanded = btn.getAttribute('aria-expanded') === 'true';
btn.setAttribute('aria-expanded', String(!expanded));
panel.hidden = expanded;
});
6) External links & new windows
Your extlink module handles most of this. For manual external links (e.g., social icons), ensure:
<a href="https://www.linkedin.com/company/u-s--department-of-energy"
target="_blank" rel="noopener noreferrer">
...
</a>
You already add screen-reader text (“Link to …”). Good.
7) Clean up analytics/containers in production
You’re loading multiple GA properties and two GTM noscript iframes (one includes gtm_auth and gtm_preview env tokens):
<noscript>
<iframe src="https://www.googletagmanager.com/ns.html?id=GTM-PCSS9JS>m_auth=...>m_preview=...">
</iframe>
</noscript>
- Recommendation: In production builds, remove preview/authed containers and consolidate analytics into a single GTM container whenever possible (it reduces payload and avoids exposing preview tokens).
- If you must keep multiple GA streams, keep them all in one GTM container and remove duplicate
gtag.jsloads.
8) Preconnect small perf wins
Since you load multiple analytics domains and GovDelivery:
<link rel="preconnect" href="https://www.googletagmanager.com" crossorigin>
<link rel="preconnect" href="https://public.govdelivery.com" crossorigin>
(You’re serving Font Awesome locally, so no need for fonts.gstatic.com.)
9) Font Awesome bundle size
You currently ship many FA JS bundles:
all.js
sharp-solid.js
sharp-regular.js
sharp-light.js
sharp-thin.js
sharp-duotone-*.js
fontawesome.js
- Recommendation: create a single custom FA build including only the families/glyphs in use (or switch to a static SVG sprite). This typically cuts tens/hundreds of KB.
10) Social “Follow Us” icons – focus clarity
You already include visually hidden labels; ensure the icons themselves are not focusable when wrapped in links (they’re not, fine). If you ever add standalone icons, give them aria-hidden="true".
11) OG/Twitter cleanup
og:typeshould bewebsite(not “Homepage”).- You already have
og:image:alt— 👍 - Consider adding an
OrganizationJSON-LD (logo + url) for richer entity signals:
<script type="application/ld+json">
{
"@context":"https://schema.org",
"@type":"Organization",
"name":"U.S. Department of Energy",
"url":"https://www.energy.gov/",
"logo":"https://www.energy.gov/sites/default/files/2025-03/DOE%20Full%20Seal%20on%20Blue%20background%20-%201312%20x%20825_1.png",
"sameAs":[
"https://www.facebook.com/energy",
"https://twitter.com/energy",
"https://www.youtube.com/user/USdepartmentofenergy",
"https://www.instagram.com/energy",
"https://www.linkedin.com/company/u-s--department-of-energy"
]
}
</script>
12) “Trending” links: spacing + hit area
Those are short and close together. Increase inline padding or block spacing to make them easier to tap on mobile (target ~44px touch height).
.sub-hero__links .field__item a { padding: .25rem .5rem; display:inline-block; }
@media (max-width: 640px) {
.sub-hero__links .field__item { display:block; margin-bottom:.25rem; }
}
13) Newsletter form is solid—add inline error messaging
You already have a <label> and required. Add ARIA invalid and describe on error:
const email = document.getElementById('edit-email');
email.addEventListener('invalid', () => {
email.setAttribute('aria-invalid', 'true');
// Optionally set aria-describedby to an inline error <div id="email-error">
});
14) Security header hygiene (server-side)
Not in the HTML, but worth setting at the edge:
Content-Security-Policythat includes Dynatrace/GTM/GovDelivery origins explicitly.Strict-Transport-Security: max-age=31536000; includeSubDomains; preloadPermissions-Policy(at least disable camera/mic/geolocation by default).Cross-Origin-Opener-Policy: same-origin
15) Minor head cleanup
- You have
meta name="Generator"twice (Drupal 10 and 8)—keep one, or remove both. - Prefer one canonical analytics path (see §7).
Quick wins checklist
- Replace all “Read more here” with descriptive link text.
- Add
prefers-reduced-motionstyles for Splide. - Add hidden
<img fetchpriority="high">inside hero to improve LCP. - Make repetitive images
alt="" aria-hidden="true". - Remove preview GTM iframe / consolidate analytics.
- Preconnect to GTM + GovDelivery.
- Collapse Font Awesome bundles to a single custom build.
- Change
og:typetowebsiteand add Organization JSON-LD. - Ensure all menu/search toggles keep
aria-expandedaccurate.
If you’d like, I can turn these into tiny Twig overrides (carousel slide template, menu toggle behavior, and a head partial) so you can drop them into your theme without touching content.