Add @media queries for a11y and also add small settings nav so users can

toggle a11y features between on / off / system.
This commit is contained in:
badblocks 2026-07-18 14:46:55 -07:00
parent 5fdc947bcd
commit c959f0d848
Signed by: badblocks
SSH key fingerprint: SHA256:hEcM6BP4hKm9F7WsomNuXSBpPn2BSDnFzPSl3y1NerQ
3 changed files with 191 additions and 105 deletions

View file

@ -46,7 +46,6 @@ body {
var(--color-accent-transparent), var(--color-accent-transparent),
black 120% black 120%
); );
color: var(--color-fg); color: var(--color-fg);
column-gap: var(--gutter-large); column-gap: var(--gutter-large);
display: grid; display: grid;
@ -62,6 +61,77 @@ body {
text-shadow: 0 0 5px var(--color-glow); text-shadow: 0 0 5px var(--color-glow);
top: 0; top: 0;
} }
body::after {
content: " ";
display: block;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
background: rgba(18, 16, 16, 0.1);
background-attachment: fixed;
opacity: 0;
z-index: 2;
pointer-events: none;
animation: flicker 15s infinite;
}
body::before {
content: " ";
display: block;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
background:
linear-gradient(rgba(18, 16, 16, 0) 50%, rgba(0, 0, 0, 0.25) 50%),
linear-gradient(
90deg,
rgba(255, 0, 0, 0.06),
rgba(0, 255, 0, 0.02),
rgba(0, 0, 255, 0.06)
);
z-index: 2;
background-size:
100% 2px,
3px 100%;
background-attachment: fixed;
pointer-events: none;
}
:root[data-reduce-motion="on"] body,
:root[data-reduce-motion="on"] body::after {
animation: none;
}
@media (prefers-reduced-motion: reduce) {
:root:not([data-reduce-motion="off"]) body,
:root:not([data-reduce-motion="off"]) body::after {
animation: none;
}
}
:root[data-more-contrast="on"] body {
background-image: none;
text-shadow: none;
animation: none;
}
:root[data-more-contrast="on"] body::before,
:root[data-more-contrast="on"] body::after {
content: none;
}
@media (prefers-contrast: more) {
:root:not([data-more-contrast="off"]) body {
background-image: none;
text-shadow: none;
animation: none;
}
:root:not([data-more-contrast="off"]) body::before,
:root:not([data-more-contrast="off"]) body::after {
content: none;
display: none;
background: none;
animation: none;
}
}
@keyframes flicker { @keyframes flicker {
0% { 0% {
opacity: 0.27861; opacity: 0.27861;
@ -255,44 +325,6 @@ body {
0 0 3px; 0 0 3px;
} }
} }
body::after {
content: " ";
display: block;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
background: rgba(18, 16, 16, 0.1);
background-attachment: fixed;
opacity: 0;
z-index: 2;
pointer-events: none;
animation: flicker 15s infinite;
}
body::before {
content: " ";
display: block;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
background:
linear-gradient(rgba(18, 16, 16, 0) 50%, rgba(0, 0, 0, 0.25) 50%),
linear-gradient(
90deg,
rgba(255, 0, 0, 0.06),
rgba(0, 255, 0, 0.02),
rgba(0, 0, 255, 0.06)
);
z-index: 2;
background-size:
100% 2px,
3px 100%;
background-attachment: fixed;
pointer-events: none;
}
header, header,
main, main,
footer { footer {
@ -311,6 +343,48 @@ nav {
padding-inline: var(--gutter-small); padding-inline: var(--gutter-small);
width: 100%; width: 100%;
} }
.display-prefs-nav {
position: absolute;
top: 0;
right: 0;
z-index: 3;
}
.display-prefs-nav summary {
align-items: center;
cursor: pointer;
display: flex;
justify-content: flex-end;
list-style: none;
padding-block: var(--stack-small);
padding-inline: 1ch;
}
.display-prefs-nav summary::-webkit-details-marker {
display: none;
}
.display-prefs-nav summary:hover {
padding-inline: 0;
}
.display-prefs-nav summary:hover::before {
color: var(--color-glow);
content: "[";
}
.display-prefs-nav summary:hover::after {
color: var(--color-glow);
content: "]";
}
.display-prefs-nav summary > span {
translate: 0 -0.225em;
}
.display-prefs-panel {
background-color: var(--color-bg);
border: 2px solid var(--color-accent);
min-inline-size: 10em;
padding-block: var(--stack-small);
padding-inline: var(--gutter-small);
position: absolute;
right: 0;
inline-size: max-content;
}
nav ul { nav ul {
column-gap: var(--gutter-large); column-gap: var(--gutter-large);
display: flex; display: flex;

View file

@ -3,6 +3,13 @@
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script is:inline>
for (const pref of ["reduce-motion", "more-contrast"]) {
const v = localStorage.getItem(pref);
if (v === "on" || v === "off")
document.documentElement.setAttribute("data-" + pref, v);
}
</script>
<link <link
rel="preload" rel="preload"
href="/unscii-16.woff" href="/unscii-16.woff"
@ -20,6 +27,7 @@
<meta name="generator" content={Astro.generator} /> <meta name="generator" content={Astro.generator} />
<meta name="darkreader-lock" /> <meta name="darkreader-lock" />
<link rel="sitemap" href="/sitemap-index.xml" /> <link rel="sitemap" href="/sitemap-index.xml" />
<script is:inline src="/htmz.js"></script> <script is:inline src="/htmz.js"></script>
<script <script
is:inline is:inline
@ -39,6 +47,48 @@
<li><a href="https://git.badblocks.dev" target="_blank">Git</a></li> <li><a href="https://git.badblocks.dev" target="_blank">Git</a></li>
</ul> </ul>
</nav> </nav>
<details class="display-prefs-nav">
<summary aria-label="Display preferences" title="Display preferences"
><span>⚙</span></summary
>
<div class="display-prefs-panel">
<label>
Low Motion
<select data-pref="reduce-motion">
<option value="">System</option>
<option value="on">On</option>
<option value="off">Off</option>
</select>
</label>
<label>
High Contrast
<select data-pref="more-contrast">
<option value="">System</option>
<option value="on">On</option>
<option value="off">Off</option>
</select>
</label>
</div>
</details>
<script is:inline>
document.querySelectorAll("[data-pref]").forEach((sel) => {
const key = sel.dataset.pref;
sel.value = localStorage.getItem(key) ?? "";
sel.addEventListener("change", () => {
if (sel.value) {
localStorage.setItem(key, sel.value);
document.documentElement.setAttribute("data-" + key, sel.value);
} else {
localStorage.removeItem(key);
document.documentElement.removeAttribute("data-" + key);
}
});
});
document.addEventListener("click", (e) => {
const d = document.querySelector(".display-prefs-nav");
if (!d.contains(e.target)) d.removeAttribute("open");
});
</script>
</header> </header>
<main id="main"> <main id="main">
<slot name="main" /> <slot name="main" />

View file

@ -120,7 +120,16 @@ import Layout from "@layouts/BaseLayout.astro";
animation: scroll calc(var(--scroll-multiplier) * var(--layer-5-speed)) animation: scroll calc(var(--scroll-multiplier) * var(--layer-5-speed))
linear infinite; linear infinite;
} }
:root[data-reduce-motion="on"]
:is(.layer-0, .layer-1, .layer-2, .layer-3, .layer-4, .layer-5) {
animation: none;
}
@media (prefers-reduced-motion: reduce) {
:root:not([data-reduce-motion="off"])
:is(.layer-0, .layer-1, .layer-2, .layer-3, .layer-4, .layer-5) {
animation: none;
}
}
@keyframes scroll { @keyframes scroll {
0% { 0% {
transform: translateX(0); transform: translateX(0);
@ -129,66 +138,6 @@ import Layout from "@layouts/BaseLayout.astro";
transform: translateX(-50%); transform: translateX(-50%);
} }
} }
/*.desktop {
width: 100%;
}
.desktop-monitor {
margin: 10px auto 0px auto;
width: 330px;
height: 230px;
border: 4px solid #34495e;
border-radius: 15px;
}
.desktop-audio {
border: 2px solid #34495e;
width: 10px;
height: 8px;
border-radius: 10px;
margin: 6px auto 0px auto;
}
.desktop-screen {
margin: 5px auto 0px auto;
border: 3px solid #34495e;
border-radius: 5px;
width: 305px;
height: 195px;
background-color: black;
object-fit: contain;
position: relative;
}
.desktop-screen-text {
position: absolute;
top: 0;
right: 0.25em;
}
.desktop-keyboard {
width: 360px;
height: 20px;
border: 4px solid #34495e;
border-radius: 2px;
margin: -4px auto 2px auto;
}
.desktop-keyboard-detail {
border: 1px solid #34495e;
width: 50px;
height: 8px;
border-radius: 10px;
margin: 0px auto 0px auto;
}
.desktop-keyboard-top {
width: 360px;
height: 8px;
background-color: #34495e;
border-radius: 2px;
margin: -2px auto 4px auto;
clip-path: polygon(10% 0, 90% 0, 100% 100%, 0 100%);
}*/
.desktop { .desktop {
width: 100%; width: 100%;
container-type: inline-size; container-type: inline-size;
@ -244,9 +193,10 @@ import Layout from "@layouts/BaseLayout.astro";
border: 1px solid #34495e; border: 1px solid #34495e;
border-radius: 999px; border-radius: 999px;
} }
.desktop-caption { .desktop-screen-caption {
width: 100%; position: absolute;
text-align: center; top: 1.25em;
right: 0.25em;
font-size: clamp(0.75rem, 4.5cqi, 1rem); font-size: clamp(0.75rem, 4.5cqi, 1rem);
} }
.sided { .sided {
@ -272,7 +222,10 @@ import Layout from "@layouts/BaseLayout.astro";
], ],
index: 0, index: 0,
get theme() { return this.themes[this.index].value }, get theme() { return this.themes[this.index].value },
next() { this.index = (this.index + 1) % this.themes.length }, next() {
this.index = (this.index + 1) % this.themes.length;
document.querySelector('.desktop-screen-caption').classList.add('hidden');
},
}" }"
> >
<div class="sided"> <div class="sided">
@ -297,15 +250,24 @@ import Layout from "@layouts/BaseLayout.astro";
</div> </div>
<div class="desktop-screen-text" x-text="themes[index].label"> <div class="desktop-screen-text" x-text="themes[index].label">
</div> </div>
<div class="desktop-screen-caption">(Click me!)</div>
</div> </div>
</div> </div>
<div class="desktop-keyboard-top"></div> <div class="desktop-keyboard-top"></div>
<div class="desktop-keyboard"> <div class="desktop-keyboard">
<div class="desktop-keyboard-detail"></div> <div class="desktop-keyboard-detail"></div>
</div> </div>
<div class="desktop-caption">(Click me!)</div>
</div> </div>
</div> </div>
<script is:inline>
document
.querySelector(".display-prefs-nav")
.addEventListener("click", (e) => {
document
.querySelector(".desktop-screen-caption")
.classList.add("hidden");
});
</script>
</article> </article>
</Fragment> </Fragment>
</Layout> </Layout>