user-personalization — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited user-personalization (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Canonical source:examples/USER_PERSONALIZATION_ACCESSIBILITY_BEST_PRACTICES.mdinmgifford/ACCESSIBILITY.mdThis skill is derived from that file. When in doubt, the example is authoritative.
Apply these rules when implementing user preference controls or reviewing existing personalization features. Only load this skill if the project has personalization features.
Users should be able to customize content presentation to meet their individual needs without compromising information, functionality, or accessibility. Personalization must complement — never replace — proper accessible design.
Note: 1.4.12 Text Spacing (AA) is the primary WCAG criterion that personalization controls address. This skill is the correct home for that criterion.
| Level | Meaning |
|---|---|
| Critical | Overlay used as compliance substitute; interferes with user's AT |
| Serious | OS-level preferences (reduced-motion, colour scheme) not respected |
| Moderate | Personalization widget not keyboard accessible; state not announced |
| Minor | Preferences not persisted; prefers-reduced-data not considered |
Third-party "accessibility overlay" widgets that claim to auto-fix accessibility issues must not be used as a substitute for proper accessible design. Using an overlay as a compliance claim is Critical — they:
browser zoom, OS high contrast)
The only acceptable use of overlay-like technology is custom remediation for legacy vendor-locked systems as a temporary bridge, with a documented plan and timeline for proper implementation.
Respect user OS-level preferences before adding any custom controls. Ignoring `prefers-reduced-motion` is Serious; ignoring prefers-color-scheme is Moderate to Serious depending on contrast impact.
/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
/* Dark mode */
@media (prefers-color-scheme: dark) {
:root {
--color-text: #e8e8e8;
--color-background: #1a1a1a;
}
}
/* High contrast */
@media (prefers-contrast: more) {
:root {
--color-text: #000000;
--color-background: #ffffff;
--border-width: 2px;
}
}
/* Windows High Contrast / forced colors */
@media (forced-colors: active) {
.custom-focus-indicator {
forced-color-adjust: none;
outline: 2px solid CanvasText;
}
}
/* Reduced transparency — Safari only as of 2025; treat as enhancement */
@media (prefers-reduced-transparency: reduce) {
.modal-overlay {
opacity: 1;
background-color: var(--color-background);
}
}Custom personalization controls (font size, spacing, theme) are acceptable when:
<div role="group" aria-label="Text size">
<button type="button" aria-label="Decrease text size"
onclick="adjustFontSize(-1)">A−</button>
<button type="button" aria-label="Reset text size"
onclick="resetFontSize()">A</button>
<button type="button" aria-label="Increase text size"
onclick="adjustFontSize(1)">A+</button>
</div>function adjustFontSize(delta) {
const current = parseFloat(
getComputedStyle(document.documentElement).fontSize
);
const next = `${Math.max(12, Math.min(32, current + delta))}px`;
document.documentElement.style.fontSize = next;
setStoredPref('font-size', next);
announceChange(`Text size set to ${next}`);
}
function resetFontSize() {
document.documentElement.style.fontSize = '';
removeStoredPref('font-size');
announceChange('Text size reset to default');
}const spacingOptions = { normal: '1.5', wide: '1.75', wider: '2' };
function setSpacing(level) {
document.documentElement.style.setProperty(
'--line-height', spacingOptions[level]
);
setStoredPref('spacing', level);
announceChange(`Line spacing set to ${level}`);
}localStorage is unavailable in private browsing, cross-origin iframes, and storage-restricted environments. Always wrap in try/catch.
function getStoredPref(key) {
try { return localStorage.getItem(key); }
catch { return null; }
}
function setStoredPref(key, value) {
try { localStorage.setItem(key, value); }
catch { /* Preference will not persist — widget still works in session */ }
}
function removeStoredPref(key) {
try { localStorage.removeItem(key); }
catch { /* Silent */ }
}
/* Restore preferences on load */
window.addEventListener('DOMContentLoaded', () => {
const fontSize = getStoredPref('font-size');
const spacing = getStoredPref('spacing');
if (fontSize) document.documentElement.style.fontSize = fontSize;
if (spacing) setSpacing(spacing);
});<div aria-live="polite" aria-atomic="true"
class="visually-hidden" id="pref-announcement">
<!-- JS inserts e.g. "Text size increased to large" -->
</div>function announceChange(message) {
const region = document.getElementById('pref-announcement');
region.textContent = '';
// Brief timeout ensures screen readers catch the content change
setTimeout(() => { region.textContent = message; }, 50);
}prefers-reduced-dataAn emerging CSS media query (prefers-reduced-data) allows sites to serve lighter content for users on metered connections. Support is currently limited (no major browser has shipped it as of 2025), but it is worth monitoring as it directly relates to personalization and web sustainability.
/* Future-facing — gate behind @supports or feature detection */
@media (prefers-reduced-data: reduce) {
.decorative-hero-image { display: none; }
video[autoplay] { display: none; }
}WCAG 1.3.6 Identify Purpose (Level AAA) is the criterion that enables personalisation for cognitive accessibility — it requires that UI components, icons, regions, and links expose their purpose in machine-readable form so that user agents or assistive technologies can adapt the presentation (for example, substituting symbols or stripping non-essential content for users with cognitive disabilities). If your project targets AAA or has cognitive accessibility goals, this skill and 1.3.6 should be considered together.
prefers-reduced-motion, prefers-color-scheme, prefers-contrast, forced-colorslocalStorage access wrapped in try/catch in all read/write operationsDOMContentLoadedaria-live="polite"prefers-reduced-motionStandards horizon: WCAG 3.0 is in development; personalization requirements are expected to expand, not contract. Monitor: <https://www.w3.org/TR/wcag-3.0/>
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.