Vector~Prime
★★★★☆ Station Commander
| Location | Sector 9 |
|---|---|
| Interests | space sims, tracker music |
| Homepage | vectorprime.example.net |
All 63 components in core, on one long page, the way FAQ pages used to be. Each exhibit comes with its era pedigree, a class table, a live specimen, and the source to copy. Everything here works without JavaScript; the laws apply throughout. This page is generated from manifest.json, so it cannot go stale, a class missing from the catalog is a release blocker, not a documentation bug.
Curator's note: where a snippet references demo files
(avatar.gif, my-cat.jpg, the files you are meant
to supply), the live specimen borrows pixel art that ships in
/dist/assets/ so nothing on this page 404s. The source shown is the
canonical snippet, verbatim.
<center>, the most honest tag HTML ever had. Deprecated, never forgotten.
Centers text and block children. Culturally load-bearing.
| Class | Role |
|---|---|
rs-center |
text-align center; block children get auto margins |
Everything here is centered, as nature intended.
<div class="rs-center"> <h2>~ * ~ welcome ~ * ~</h2> <p>Everything here is centered, as nature intended.</p> </div>
Access for all: None specific.
The links-page table: rows of 88×31 buttons and blue underlines, cellpadding 4.
Equal columns for badge walls and link farms. 4 → 2 → 1, 3 → 1, 2 → 1 as the screen shrinks.
| Class | Role |
|---|---|
rs-cols-2 |
two equal columns from vga up |
rs-cols-3 |
three equal columns from svga up |
rs-cols-4 |
four from svga, two from vga, one below |
left column
right column
cool site #1
cool site #2
cool site #3
<div class="rs-cols-2"> <p>left column</p> <p>right column</p> </div> <div class="rs-cols-3"> <p>cool site #1</p> <p>cool site #2</p> <p>cool site #3</p> </div>
Access for all: None specific; column order is source order.
"Best viewed at 800×600", 760px is what actually fit that CRT after scrollbar and chrome.
Width governor: 760px by default, centered, fluid below its max.
| Class | Role |
|---|---|
rs-container |
max-width 760px, centered |
rs-container--wide |
modifier: max-width 1000px |
rs-container--fluid |
modifier: full width |
760 pixels of prime real estate, centered.
The deluxe 1000px lot, for portals with a lot to say.
<div class="rs-container"> <p>760 pixels of prime real estate, centered.</p> </div> <div class="rs-container rs-container--wide"> <p>The deluxe 1000px lot, for portals with a lot to say.</p> </div>
Access for all: None specific.
Netscape 2.0 framesets, nav frame left, content frame right, minus the broken back button.
Frameset cosplay: sticky side pane and main pane, each scrolling on its own, divided by a ridge.
| Class | Role |
|---|---|
rs-frames |
grid wrapper |
rs-frames__side |
sticky side pane (top strip below svga) |
rs-frames__main |
main pane |
rs-frames--right |
modifier: side pane on the right |
The main pane scrolls on its own, like a proper frameset, except bookmarks work and the back button tells the truth.
<div class="rs-frames">
<nav class="rs-frames__side" aria-label="Site">
<a href="#">home</a><br>
<a href="#">my scope</a><br>
<a href="#">guestbook</a>
</nav>
<main class="rs-frames__main">
<p>The main pane scrolls on its own, like a proper frameset, except
bookmarks work and the back button tells the truth.</p>
</main>
</div>
Access for all: Side pane should be a <nav>, main pane a <main>. Real URLs, working back button, the parts framesets got wrong.
Nested table layouts: nav column left, content right, banner on top, rebuilt as grid, no tables harmed.
Page-shape recipes via grid areas: sidebars, holy grail, portal thirds. Single column below svga.
| Class | Role |
|---|---|
rs-layout |
grid wrapper |
rs-layout--sidebar-left |
recipe: 180px nav + main |
rs-layout--sidebar-right |
recipe: main + 180px rail |
rs-layout--holy-grail |
recipe: header / nav main rail / footer |
rs-layout--three-col |
recipe: the portal look, three honest thirds |
rs-layout__header |
area: header |
rs-layout__nav |
area: navigation column |
rs-layout__main |
area: content |
rs-layout__rail |
area: right rail |
rs-layout__footer |
area: footer |
Content first in the source, even though the nav sits on the left.
<div class="rs-layout rs-layout--sidebar-left">
<header class="rs-layout__header">
<h1>My Site</h1>
</header>
<main class="rs-layout__main">
<p>Content first in the source, even though the nav sits on the left.</p>
</main>
<nav class="rs-layout__nav" aria-label="Site">
<a href="#">home</a><br>
<a href="#">about me</a><br>
<a href="#">links</a>
</nav>
<footer class="rs-layout__footer">
<p>Last updated: yesterday, probably.</p>
</footer>
</div>
Access for all: Source order stays header, main, nav, rail, footer, readers first; the grid rearranges visually from svga up. Use real landmark elements for the areas.
The centered content table on a starfield background, the anatomy of every 1997 homepage.
The opaque content sheet that sits on the tiled or colored body.
| Class | Role |
|---|---|
rs-page |
the sheet: content background, padding, bevel border from vga up |
You have reached the content sheet. The body behind it wears the wallpaper.
<div class="rs-page rs-container"> <h1>Welcome to my homepage!</h1> <p>You have reached the content sheet. The body behind it wears the wallpaper.</p> </div>
Access for all: Purely visual wrapper; carries no role. Put your landmarks inside it.
The 1×1 transparent spacer.gif, stretched into invisible struts. It held the old web together.
A vertical spacer block on the spacing scale.
| Class | Role |
|---|---|
rs-spacer |
block spacer, default 8px |
rs-spacer--1 |
2px |
rs-spacer--2 |
4px |
rs-spacer--3 |
8px |
rs-spacer--4 |
16px |
rs-spacer--5 |
32px |
Some breathing room follows.
That was 16 pixels of pure nothing, in memory of spacer.gif.
<p>Some breathing room follows.</p> <div class="rs-spacer rs-spacer--4" aria-hidden="true"></div> <p>That was 16 pixels of pure nothing, in memory of spacer.gif.</p>
Access for all: Decorative: mark it aria-hidden, as the snippet does.
Signatures, textfile logos, and figlet banners, the art you made when the only tool guaranteed to render was the font.
A <pre> block for ASCII art and text banners, marked up as an image so readers announce a label, not every slash.
| Class | Role |
|---|---|
rs-ascii |
the art block: tight-leading monospace on <pre>, scrolls sideways if wide |
rs-ascii--center |
centers the block while the art inside stays left-aligned |
rs-ascii--framed |
a raised bevel frame around the art |
rs-ascii--sig |
the forum signature variant: smaller and quieter, under a hairline |
/\_/\ ( o.o ) > ^ <
<!-- role="img" + aria-label: the reader hears "A small cat", not the slashes --> <pre class="rs-ascii rs-ascii--framed rs-ascii--center" role="img" aria-label="A small cat, in ASCII art"> /\_/\ ( o.o ) > ^ <</pre>
Access for all: Mark it up as <pre role="img"> with an aria-label that says what the art shows; assistive tech announces the label instead of reading every character. Wide art scrolls inside its own box, so it never breaks the page on a phone. For text you want read aloud (code, tables), use rs-dos instead.
Netscape's <blink> tag, born of a 1994 bar joke about Lynx, back, and holding steady at one flash per second.
Inline text that blinks at exactly one hertz.
| Class | Role |
|---|---|
rs-blink |
1Hz steps(1) opacity blink; bold + underline under reduced motion |
NEW! Three fresh wallpapers in the downloads section!
HOT! My guestbook just passed 100 entries. Thank you, visitors!
<p><span class="rs-blink">NEW!</span> Three fresh wallpapers in the downloads section!</p> <p><span class="rs-blink">HOT!</span> My guestbook just passed 100 entries. Thank you, visitors!</p>
Access for all: One flash per second sits well under the three-per-second photosensitivity ceiling. Under prefers-reduced-motion it renders as static bold plus underline, the emphasis survives, the blinking does not.
Terminal cosplay from the textfiles web, black screen, gray Courier, ASCII banners, and cheat tables at the C:\> prompt.
A black terminal block on <pre>, with an optional C:\> title strip.
| Class | Role |
|---|---|
rs-dos |
the terminal block on <pre>: black bg, gray mono, 2px sunken border |
rs-dos__title |
the C:\> strip above the block |
type welcome.txt Greetings, visitor. You have reached the coolest corner of this hard drive. Mind the ASCII dust. 1 file(s) displayed, 0 regrets
<div class="rs-dos__title">C:\HOMEPAGE></div> <pre class="rs-dos"> type welcome.txt Greetings, visitor. You have reached the coolest corner of this hard drive. Mind the ASCII dust. 1 file(s) displayed, 0 regrets </pre>
Access for all: Built on <pre>, so spacing and reading order survive exactly as typed. Give large ASCII art a short text alternative nearby, screen readers read every slash.
The <font size=1..7> ladder at the browsers' own mapping, 10, 13, 16, 18, 24, 32, 48 pixels of pure 1997 hierarchy.
The seven sanctioned text sizes, 10px to 48px, as utility classes.
| Class | Role |
|---|---|
rs-font-1 |
10px (size=1): fine print, counters, footers |
rs-font-2 |
13px (size=2): sans-theme body text |
rs-font-3 |
16px (size=3): serif-theme body text |
rs-font-4 |
18px (size=4): lead paragraphs, h4 |
rs-font-5 |
24px (size=5): section headings |
rs-font-6 |
32px (size=6): welcome banners, h1 |
rs-font-7 |
48px (size=7): splash pages |
size 1: the fine print under the hit counter
size 2: cozy sans body text
size 3: regular body text, business as usual
size 5: now we are heading somewhere
size 7: WELCOME!!
<p class="rs-font-1">size 1: the fine print under the hit counter</p> <p class="rs-font-2">size 2: cozy sans body text</p> <p class="rs-font-3">size 3: regular body text, business as usual</p> <p class="rs-font-5">size 5: now we are heading somewhere</p> <p class="rs-font-7">size 7: WELCOME!!</p>
Access for all: Pixel names, rem values underneath, browser zoom and user font-size overrides keep working. For contrast, steps 1-4 are body text; only 5 and up count as large (4 sneaks in when bold).
The WordArt welcome banner and the logo-mill headline GIF, a gradient poured into very large letters.
Two-stop gradient display text in fire, ice, and toxic flavors.
| Class | Role |
|---|---|
rs-gradient-text |
two-stop gradient text, display sizes only |
rs-gradient-text--fire |
modifier: red to yellow |
rs-gradient-text--ice |
modifier: aqua to blue |
rs-gradient-text--toxic |
modifier: lime to teal |
<h1 class="rs-gradient-text">My Gradient Masterpiece</h1> <h2 class="rs-gradient-text rs-gradient-text--fire">This Week's Hottest Files</h2> <h2 class="rs-gradient-text rs-gradient-text--ice">The Chill-Out Lounge</h2>
Access for all: Real text with a painted fill, keep it at display sizes, so both gradient stops clear large-text contrast against the theme background.
The divider-GIF drawer of 1998, braided ropes, chasing lights, rainbow bars, because every section break deserved jewelry.
A wardrobe of horizontal rules for the semantic <hr>.
| Class | Role |
|---|---|
rs-hr |
base rule; the upgrade for a semantic <hr> |
rs-hr--groove |
modifier: the classic 3D groove |
rs-hr--dotted |
modifier: dotted line |
rs-hr--rainbow |
modifier: 4px banded rainbow bar |
rs-hr--stars |
modifier: tiled pixel-star divider |
Thanks for scrolling this far!
My MIDI collection lives below, all seventeen files, hand-picked.
This section is under construction. Aren't they all?
<p>Thanks for scrolling this far!</p> <hr class="rs-hr rs-hr--rainbow"> <p>My MIDI collection lives below, all seventeen files, hand-picked.</p> <hr class="rs-hr rs-hr--stars"> <p>This section is under construction. Aren't they all?</p>
Access for all: Keep the semantic <hr>, assistive tech announces it as a separator, whatever costume it wears.
"Press CTRL+D to bookmark this site!", the era's favorite parting instruction, finally wearing real keycaps.
A <kbd> dressed as a beveled keycap.
| Class | Role |
|---|---|
rs-kbd |
keycap chrome on <kbd>: sunken bevel, mono, tight padding |
Press Ctrl + D to bookmark this page. You know you want to!
Secret: try Up Up Down Down on the splash screen.
<p>Press <kbd class="rs-kbd">Ctrl</kbd> + <kbd class="rs-kbd">D</kbd> to bookmark this page. You know you want to!</p> <p>Secret: try <kbd class="rs-kbd">Up</kbd> <kbd class="rs-kbd">Up</kbd> <kbd class="rs-kbd">Down</kbd> <kbd class="rs-kbd">Down</kbd> on the splash screen.</p>
Access for all: The element stays a semantic <kbd>, so keyboard input reads as keyboard input; the keycap is only chrome.
GeoCities' jeweled bullets, spinning balls, gems and tiny arrows doing the stock <li> disc's job with style.
A <ul> with themed pixel markers in place of the stock disc.
| Class | Role |
|---|---|
rs-list |
the themed <ul>; nested levels alternate glyphs |
rs-list--stars |
modifier: star bullets |
rs-list--arrows |
modifier: arrow bullets |
rs-list--disks |
modifier: floppy-disk bullets |
rs-list--paws |
modifier: paw-print bullets |
<ul class="rs-list rs-list--stars"> <li>my top five space games</li> <li>cheat codes (tested, working!)</li> <li>the screenshot gallery</li> </ul> <ul class="rs-list rs-list--paws"> <li>photos of my cat</li> <li>more photos of my cat</li> </ul>
Access for all: Markers are decoration on an honest <ul>: item counts and list semantics reach screen readers untouched.
The <marquee> tag Internet Explorer 2.0 shipped in 1995, welcome banners crawling across a million homepages.
Scrolling text at one of three sane speeds; pauses on hover and focus, stands still under reduced motion.
| Class | Role |
|---|---|
rs-marquee |
the scrolling viewport; pauses on hover and focus-within |
rs-marquee__content |
the moving track (the enhancer clones it for a seamless loop) |
<div class="rs-marquee" data-rs-marquee-speed="normal">
<span class="rs-marquee__content">
★·.·´¯`·.·★ welcome to my homepage ★·.·´¯`·.·★ now with 30% more content ★·.·´¯`·.·★
</span>
</div>
Access for all: The text lives once in the DOM and reads in order; the enhancer's duplicate track is aria-hidden. Under prefers-reduced-motion it renders as static, fully-wrapped text and the pause button disappears (nothing to pause).
phpBB 2's [quote] pyramid, "Originally posted by" strips stacked like sediment, the signature ruled off below the post.
The forum quote block: source strip, quoted body, and the signature divider.
| Class | Role |
|---|---|
rs-quote |
the quote block: 1px sunken border; nesting flattens past three |
rs-quote__source |
silver header strip: Originally posted by … |
rs-quote__body |
the quoted text itself |
rs-quote__sig |
signature divider: the -- line, then up to three muted lines |
The marquee stays. It is the soul of the page.
Agreed! But only at 60 pixels per second -- we are not animals.
--
~*~ visit my homepage ~*~
proud member of three webrings and counting
<div class="rs-quote">
<div class="rs-quote__source">Originally posted by Webmaster</div>
<blockquote class="rs-quote__body">
<p>The marquee stays. It is the soul of the page.</p>
</blockquote>
</div>
<p>Agreed! But only at 60 pixels per second -- we are not animals.</p>
<p class="rs-quote__sig">--<br>
~*~ visit my homepage ~*~<br>
proud member of three webrings and counting</p>
Access for all: Put the quoted text in a real <blockquote>; the source strip sits outside it, so attribution never reads as quotation. Signatures stay under three lines, RFC 1855 manners, kept by CSS.
Rainbow headlines built one <font color> tag per letter, a whole evening in Notepad, now a single class.
Per-character rainbow text via a banded gradient, for headlines only.
| Class | Role |
|---|---|
rs-rainbow |
banded per-character rainbow via background-clip; headlines only |
Every letter colors itself now, in 1998 that was one font tag apiece.
<h1 class="rs-rainbow">Welcome to my Rainbow Page!</h1> <p>Every letter colors itself now, in 1998 that was one font tag apiece.</p>
Access for all: It stays plain, selectable text under the paint. Reserve it for 24px-and-up headlines, where the banded colors clear large-text contrast against the theme background.
The window.status typewriter loop that typed welcomes into the browser's status bar, promoted to the page, letter by letter.
Courier text with letterspacing; the reveal modifier types it on.
| Class | Role |
|---|---|
rs-typewriter |
Courier stack + 1px letterspacing |
rs-typewriter--reveal |
modifier: types on with steps(); instant under reduced motion |
All systems nominal. Enjoy your stay, visitor.
<h2 class="rs-typewriter rs-typewriter--reveal">Initializing homepage . . .</h2> <p class="rs-typewriter">All systems nominal. Enjoy your stay, visitor.</p>
Access for all: The reveal is decoration over real text: under prefers-reduced-motion the line simply appears, fully typed. Screen readers always get the whole sentence.
The 80×80 forum avatar, dithered to 256 colors and worn like a uniform on every message board of 2001.
An 80×80 pixelated avatar image with a 1px border; --small drops it to 40×40.
| Class | Role |
|---|---|
rs-avatar |
80×80, 1px border, image-rendering pixelated |
rs-avatar--small |
modifier: 40×40 |
<img class="rs-avatar" src="avatar.gif" alt="Vector~Prime's avatar: a knight in mirrored shades" width="80" height="80"> <img class="rs-avatar rs-avatar--small" src="avatar.gif" alt="Vector~Prime's avatar, 40 pixels of knight" width="40" height="40">
Access for all: It is an <img>: alt text is required and names who the avatar stands for.
"This site won the Golden Floppy, March 1999", awards traded between webmasters like merit badges.
A trophy-shelf block: one award image and the caption telling who gave it and when.
| Class | Role |
|---|---|
rs-award |
trophy-shelf block for one award image |
rs-award__caption |
the who/what/when line |
<figure class="rs-award"> <img src="golden-floppy.gif" alt="Golden Floppy Award trophy" width="120" height="90"> <figcaption class="rs-award__caption">This site won the Golden Floppy, March 1999.</figcaption> </figure>
Access for all: A <figure> with <figcaption>: the alt names the award, the caption tells the story.
The flashing NEW! gif planted beside every link the webmaster touched this month.
Inline flashing tags, NEW!, UPDATED!, HOT!, COOL!, for links you touched this month.
| Class | Role |
|---|---|
rs-badge |
inline tag chip |
rs-badge--new |
modifier: NEW! in red on yellow |
rs-badge--updated |
modifier: UPDATED! |
rs-badge--hot |
modifier: HOT! with flame icon |
rs-badge--cool |
modifier: COOL! in blue |
<ul> <li><a href="#">Downloads</a> <sup><span class="rs-badge rs-badge--new rs-blink">NEW!</span></sup></li> <li><a href="#">Cheats & codes</a> <sup><span class="rs-badge rs-badge--updated">UPDATED!</span></sup></li> <li><a href="#">MIDI jukebox</a> <sup><span class="rs-badge rs-badge--hot">HOT!</span></sup></li> <li><a href="#">Winter skin pack</a> <sup><span class="rs-badge rs-badge--cool">COOL!</span></sup></li> </ul>
Access for all: The badge is real text, read inline where it sits; add rs-blink for the flash and reduced motion renders it static bold.
The 468×60 full banner of 1996: the only ad size that ever mattered.
A 468×60 banner shell that scales proportionally below 500px, the one sanctioned proportional scale.
| Class | Role |
|---|---|
rs-banner |
468×60 shell; scales down proportionally below 500px viewports |
<a class="rs-banner" href="#"> <img src="banner-468x60.gif" alt="Star Quest 3D fan zone, click to warp in" width="468" height="60"> </a>
Access for all: An image link: the alt text names the destination, not the artwork.
Blinkies, skinny animated badges with a shiny border and a phrase like "I love my cat".
The ~150×20 glitter strip that declared your allegiances in a sidebar or signature.
| Class | Role |
|---|---|
rs-blinkie |
the 150×20 strip; pair with rs-blink for the shimmer |
rs-blinkie--hot |
modifier: maroon and amber |
rs-blinkie--cool |
modifier: black and cyan |
rs-blinkie--candy |
modifier: fuchsia and white |
I <3 MY CAT HTML 4 EVER SURF THE WEB ~*~ KAWAII ~*~
<p class="rs-badge-wall"> <span class="rs-blinkie rs-blink">I <3 MY CAT</span> <span class="rs-blinkie rs-blinkie--hot">HTML 4 EVER</span> <span class="rs-blinkie rs-blinkie--cool">SURF THE WEB</span> <span class="rs-blinkie rs-blinkie--candy">~*~ KAWAII ~*~</span> </p>
Access for all: Just a small styled element; if it links somewhere, it's a real link. Add rs-blink for the classic shimmer (which stops under reduced motion).
The 88×31 button, the micro-banner standard every site traded and no committee ever ratified.
The 88×31 button as an element: fixed size forever, built for badge walls.
| Class | Role |
|---|---|
rs-button88 |
fixed 88×31 box, pixel border, one line of text; never scales |
rs-button88--navy |
baked navy-on-white palette |
rs-button88--maroon |
baked maroon-with-gold palette |
rs-button88--teal |
baked teal-on-white palette |
<div class="rs-badge-wall"> <a class="rs-button88" href="#">STAR QUEST 3D</a> <a class="rs-button88" href="#">SECTOR 9 BBS</a> <a class="rs-button88" href="#"><img src="valid-html.gif" alt="Valid HTML 4.01" width="88" height="31"></a> </div>
Access for all: A real link (or image link) whose text or alt names the destination, 88×31 pixels is no excuse for an empty accessible name.
The message-board member card beside every post: avatar, rank stars, and a Location/Interests table.
The member card: avatar, name, rank stars and a fields table.
| Class | Role |
|---|---|
rs-card-profile |
the member card shell |
rs-card-profile__avatar |
slot: the 80×80 avatar |
rs-card-profile__name |
slot: member name |
rs-card-profile__rank |
slot: rank stars line |
rs-card-profile__fields |
slot: the location/interests fields table |
★★★★☆ Station Commander
| Location | Sector 9 |
|---|---|
| Interests | space sims, tracker music |
| Homepage | vectorprime.example.net |
<article class="rs-card-profile">
<img class="rs-card-profile__avatar rs-avatar" src="avatar.gif" alt="Vector~Prime's avatar: a knight in mirrored shades" width="80" height="80">
<h3 class="rs-card-profile__name">Vector~Prime</h3>
<p class="rs-card-profile__rank">
<span class="rs-stars" role="img" aria-label="Rank: 4 of 5 stars">★★★★<span class="rs-stars__empty">☆</span></span>
Station Commander
</p>
<table class="rs-card-profile__fields">
<tr><th scope="row">Location</th><td>Sector 9</td></tr>
<tr><th scope="row">Interests</th><td>space sims, tracker music</td></tr>
<tr><th scope="row">Homepage</th><td><a href="#">vectorprime.example.net</a></td></tr>
</table>
</article>
Access for all: The name is a real heading and the fields are a real table with th scope="row" labels, so readers get proper label-value pairs.
The digging-worker barricade GIF that lived on every homepage, forever unfinished.
The permanently-temporary under-construction sign: a yellow board between caution bars.
| Class | Role |
|---|---|
rs-construction |
the sign: caution-striped bars around a yellow text board |
rs-construction--bar |
modifier: just the striped barrier, no text |
<div class="rs-construction"> This page is under construction!<br> Come back soon (when dad fixes the scanner). </div> <div class="rs-construction rs-construction--bar" aria-hidden="true"></div>
Access for all: Ordinary text in a block; the caution stripes are decorative pseudo-elements. Say what's under construction in the text.
The odometer hit counter at the foot of the page, proudly proving 4,096 visitors since 1998.
The sunken odometer shell for a hit counter; static digits work today, the hit-counter widget populates it later.
| Class | Role |
|---|---|
rs-counter |
sunken bezel, black bg, odometer digits |
rs-counter__label |
the "visitors since …" line |
You are visitor 4,096. 004096 visitors since March 1999
<p class="rs-counter"> <span class="rs-sr-only">You are visitor 4,096.</span> <span aria-hidden="true">004096</span> <span class="rs-counter__label">visitors since March 1999</span> </p>
Access for all: One visually hidden sentence carries the count; the odometer digits are aria-hidden decoration. Never a live region.
A scanned photo in an outset frame with a caption strip below, the "my cat, 72dpi" exhibit on every personal page.
An image in a 2px outset frame with an optional sunken caption strip.
| Class | Role |
|---|---|
rs-figure |
2px outset frame around the image |
rs-figure__caption |
sunken caption strip below |
<figure class="rs-figure"> <img src="my-cat.jpg" alt="A gray cat asleep on a beige keyboard" width="240" height="180"> <figcaption class="rs-figure__caption">Pixel, guarding the F5 key. Scanned at 72dpi like everything else.</figcaption> </figure>
Access for all: Native <figure>/<figcaption>: the caption describes the exhibit, the alt text still describes the image itself.
The yellow "webmaster's note" box wedged into every 1999 update log, apologizing for the guestbook again.
A yellow sticky note with a hard shadow, for asides and webmaster's notes.
| Class | Role |
|---|---|
rs-note |
sticky note: #FFFF99 bg, olive border, hard 2px shadow |
<aside class="rs-note"> <p><b>Webmaster's note:</b> the guestbook is down while I argue with the CGI script. Sign the old one twice to compensate.</p> </aside>
Access for all: Just styled content; mark it up as an <aside> when it truly is one. No role required.
The groove-bordered group box with its label sitting on the line, system settings dialogs taught every homepage this shape.
The general-purpose box: groove border with a title riding the line, fieldset-style.
| Class | Role |
|---|---|
rs-panel |
the box: 2px groove border, content padding |
rs-panel__title |
title riding the border line, legend-style |
rs-panel--raised |
modifier: bevel out |
rs-panel--sunken |
modifier: bevel in |
Webmaster, age 15. I like space sims, MIDI files, and collecting 88×31 buttons.
The sunken variant, for output wells and quiet asides.
<section class="rs-panel"> <h2 class="rs-panel__title">About me</h2> <p>Webmaster, age 15. I like space sims, MIDI files, and collecting 88×31 buttons.</p> </section> <div class="rs-panel rs-panel--sunken"> <p>The sunken variant, for output wells and quiet asides.</p> </div>
Access for all: Use a real heading for the title; when the box groups form controls, build it on <fieldset> with the title as <legend> instead.
The file-copy dialog: a sunken track filling with chunky blue blocks, eight pixels at a time.
A segmented progress bar: sunken track, chunky accent blocks, optional marching indeterminate mode.
| Class | Role |
|---|---|
rs-progress |
sunken track |
rs-progress__bar |
filled portion, segmented blocks |
rs-progress--indeterminate |
modifier: three blocks marching |
Copying SQ3D.ZIP (3 of 8 files)…
Contacting server…
<p>Copying SQ3D.ZIP (3 of 8 files)…</p> <div class="rs-progress" role="progressbar" aria-label="Copying files" aria-valuemin="0" aria-valuemax="100" aria-valuenow="60"> <div class="rs-progress__bar" style="width: 60%"></div> </div> <p>Contacting server…</p> <div class="rs-progress rs-progress--indeterminate" role="progressbar" aria-label="Contacting server"></div>
Access for all: role="progressbar" with aria-valuemin/max/now and an aria-label, as in the snippet; indeterminate mode omits aria-valuenow.
Black-on-black spoiler text on episode-guide pages, highlight to reveal how the season ends.
A details-based spoiler: content hidden until deliberately opened.
| Class | Role |
|---|---|
rs-spoiler |
details-based disclosure styled as the classic black bar |
The station was the ship all along. The captain knew since episode two.
<details class="rs-spoiler"> <summary>Spoiler: season finale</summary> <p>The station was the ship all along. The captain knew since episode two.</p> </details>
Access for all: Native <details>/<summary>: expanded/collapsed state is announced for free, and the hidden content stays out of the accessibility tree until opened.
The ★★★☆☆ verdict on every shareware download page, back when five stars meant something.
A display-only star rating: filled and empty pixel stars sized to the font.
| Class | Role |
|---|---|
rs-stars |
the star row, sized to the surrounding font |
rs-stars__empty |
the unfilled stars |
Space Miner 2000, ★★★★☆ "Better than the demo promised."
<p> Space Miner 2000, <span class="rs-stars" role="img" aria-label="Rated 4 of 5 stars">★★★★<span class="rs-stars__empty">☆</span></span> "Better than the demo promised." </p>
Access for all: The glyph row is a single role="img" with an aria-label like "Rated 4 of 5 stars", readers get the number, not five star characters.
The high-score table: silver header row, bordered cells, cellpadding=2 cellspacing=0, forever.
Dressing for honest data tables: bordered cells, silver header row, stripe and mono-numeral modifiers.
| Class | Role |
|---|---|
rs-table |
base dressing: 1px cell borders, silver header row |
rs-table--striped |
modifier: alternating row backgrounds |
rs-table--bordered |
modifier: 2px sunken outer border |
rs-table--data |
modifier: mono numerals for data-heavy tables |
rs-num |
cell class: right-aligns number cells |
| Pilot | Score | Sector |
|---|---|---|
| Vector~Prime | 1,048,576 | 9 |
| midnight_rider | 981,300 | 8 |
| KHAOS99 | 742,050 | 7 |
<table class="rs-table rs-table--striped rs-table--data">
<caption>Star Quest 3D, high scores, week 11</caption>
<thead>
<tr>
<th scope="col">Pilot</th>
<th scope="col" class="rs-num">Score</th>
<th scope="col" class="rs-num">Sector</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Vector~Prime</th>
<td class="rs-num">1,048,576</td>
<td class="rs-num">9</td>
</tr>
<tr>
<th scope="row">midnight_rider</th>
<td class="rs-num">981,300</td>
<td class="rs-num">8</td>
</tr>
<tr>
<th scope="row">KHAOS99</th>
<td class="rs-num">742,050</td>
<td class="rs-num">7</td>
</tr>
</tbody>
</table>
Access for all: Data tables only: <caption>, <thead>, and th scope="col"/"row" as in the snippet. The borders are CSS; the semantics stay honest.
The little yellow tip that popped up beside the cursor when you hovered a toolbar button in 1997.
A small yellow tip box on hover and focus, fed by a data-rs-tip attribute.
| Class | Role |
|---|---|
rs-tooltip |
trigger class; the tip text lives in data-rs-tip |
The download is a 1.44 MB ZIP that fits on one floppy, naturally.
<p> The download is a <a href="#" class="rs-tooltip" data-rs-tip="Zipped with maximum compression. Unzips to 4.2 MB.">1.44 MB ZIP</a> that fits on one floppy, naturally. </p>
Access for all: Shows on hover and keyboard focus alike, so the trigger must be focusable. Never essential content, the tip lives in a CSS pseudo-element.
Gray window chrome, gradient titlebar, _ □ ✕ in the corner, the 1998 desktop, quoted verbatim.
Window chrome: titlebar, control buttons, body and status bar; dragging arrives with the windows widget.
| Class | Role |
|---|---|
rs-window |
window chrome shell |
rs-window__titlebar |
titlebar with the two-stop fade |
rs-window__title |
title text; carries the id aria-labelledby points at |
rs-window__controls |
control button group |
rs-window__body |
window content area |
rs-window__statusbar |
sunken status cells |
rs-window--inactive |
modifier: grayed titlebar |
Thank you for downloading Star Quest 3D. Unzip everything into one folder before running SETUP.
<section class="rs-window" role="dialog" aria-labelledby="win-readme-title">
<div class="rs-window__titlebar">
<span class="rs-window__title" id="win-readme-title">README.TXT</span>
<span class="rs-window__controls">
<button aria-label="Minimize">_</button>
<button aria-label="Maximize">□</button>
<button aria-label="Close">✕</button>
</span>
</div>
<div class="rs-window__body">
<p>Thank you for downloading Star Quest 3D. Unzip everything into one folder before running SETUP.</p>
</div>
<div class="rs-window__statusbar"><span>Ready</span></div>
</section>
Access for all: A <section role="dialog"> (non-modal, no aria-modal) labelled via aria-labelledby to the titlebar text; controls are real buttons with aria-labels. Never traps focus, it is furniture, not a modal.
The silver Windows 95 push button, raised at rest, sunken while you hold it, the most-pressed rectangle of the decade.
The beveled system button; pressing it nudges the label one pixel down-right.
| Class | Role |
|---|---|
rs-btn |
the raised bevel button; :active sinks it and nudges the label 1px |
rs-btn--primary |
modifier: bold, accent-faced, the default action |
rs-btn--link |
modifier: dressed as a link, still a button |
rs-btn--small |
modifier: font step 1 |
rs-btn--large |
modifier: font step 4 |
rs-btn--icon |
modifier: 16×16 icon beside the text |
<button type="button" class="rs-btn">OK</button> <button type="button" class="rs-btn rs-btn--primary">Sign my guestbook!</button> <button type="button" class="rs-btn rs-btn--small">maybe later</button>
Access for all: Always a real <button>, focus, Space and Enter come free, and the --link disguise is still a button underneath. Disabled buttons keep the engraved gray text, which WCAG exempts as inactive UI.
Windows 95's 13-by-13 checkbox, the exact square you ticked to join a mailing list forever.
The 13×13 sunken checkbox with a proper check glyph.
| Class | Role |
|---|---|
rs-checkbox |
restyled native checkbox: 13×13 sunken box, black check glyph |
<p> <input class="rs-checkbox" type="checkbox" id="opt-news" checked> <label for="opt-news">Notify me when this page is updated!</label> </p> <p> <input class="rs-checkbox" type="checkbox" id="opt-midi"> <label for="opt-midi">I want the MIDI playlist too</label> </p>
Access for all: Under the pixel paint sits the native input, keyboard toggling and screen-reader states are untouched, and the dotted focus ring lands on the label. Always wire the <label for>.
The Windows group box: a groove border with its label riding the line, standard issue in every 90s options dialog.
Native fieldset and legend wearing the groove border.
| Class | Role |
|---|---|
rs-fieldset |
native fieldset + legend with the groove border |
<fieldset class="rs-fieldset">
<legend>Mailing list</legend>
<p>
<label for="ml-email">Your email:</label>
<input class="rs-input" id="ml-email" type="text">
</p>
<p>
<input class="rs-checkbox" type="checkbox" id="ml-weekly" checked>
<label for="ml-weekly">Send me the weekly update</label>
</p>
</fieldset>
Access for all: The native <fieldset> and <legend> pair announces the group name with every control inside it, that grouping is the point, so never fake the legend with a heading.
Every 1999 signup form was a two-column table, bold labels right-aligned against their fields. The table left; the look stayed.
The label:field two-column form grid, minus the table.
| Class | Role |
|---|---|
rs-form-table |
the grid: bold right-aligned labels, fields beside; stacks below vga |
rs-form-error |
the error message line under a field |
<form class="rs-form-table"> <label for="ft-name">Name:</label> <input class="rs-input" id="ft-name" type="text"> <label for="ft-email">Email:</label> <input class="rs-input" id="ft-email" type="text" aria-invalid="true" aria-describedby="ft-email-err"> <p class="rs-form-error" id="ft-email-err">That does not look like an email address, friend.</p> <label for="ft-home">Homepage:</label> <input class="rs-input" id="ft-home" type="text" value="http://"> </form>
Access for all: It is a grid, not a <table>, so screen readers meet label-then-field in source order. Keep <label for> on every control and tie each rs-form-error line to its field with aria-describedby.
The white sunken fields of the guestbook form, name, email, homepage, waiting on every page worth visiting.
The sunken single-line text input.
| Class | Role |
|---|---|
rs-input |
sunken text input; invalid state gets the 1px red border |
<p> <label for="gb-name">Your name:</label> <input class="rs-input" id="gb-name" type="text"> </p> <p> <label for="gb-home">Your homepage:</label> <input class="rs-input" id="gb-home" type="text" value="http://"> </p>
Access for all: Every field gets a <label for>, never a placeholder standing in for one. Invalid means a red border plus an rs-form-error line tied on with aria-describedby, so the message is more than a color.
The site poll's round buttons, Windows 95 radios, whose 12-pixel "circle" was always secretly an octagon.
The 12×12 sunken pixel-circle radio; a dot appears when checked.
| Class | Role |
|---|---|
rs-radio |
restyled native radio: 12×12 sunken pixel-circle, dot when checked |
<fieldset class="rs-fieldset">
<legend>Site poll: best screen resolution?</legend>
<p>
<input class="rs-radio" type="radio" name="res" id="res-640">
<label for="res-640">640x480 (classic)</label>
</p>
<p>
<input class="rs-radio" type="radio" name="res" id="res-800" checked>
<label for="res-800">800x600 (the people's choice)</label>
</p>
<p>
<input class="rs-radio" type="radio" name="res" id="res-1024">
<label for="res-1024">1024x768 (showoff)</label>
</p>
</fieldset>
Access for all: Still a native radio: arrow keys walk the group and states announce themselves. Group the choices in a fieldset with a legend, and give every option its <label for>.
The guestbook's "How did you find my page?" dropdown, a real Windows combo box, right down to the arrow.
A native <select> in bevel chrome with a pixel down-arrow.
| Class | Role |
|---|---|
rs-select |
native select in bevel chrome with the pixel down-arrow |
<p>
<label for="found-via">How did you find my page?</label>
<select class="rs-select" id="found-via">
<option>a webring</option>
<option>a search engine</option>
<option>a friend's links page</option>
<option>total accident (welcome!)</option>
</select>
</p>
Access for all: It stays a native <select>: keyboard, screen readers and phone pickers all work untouched. We only paint the box the arrow lives on.
The tall box under "Your message:", where a million guestbook greetings went, one heartfelt line at a time.
The sunken multi-line field, for messages of substance.
| Class | Role |
|---|---|
rs-textarea |
sunken multi-line field; invalid state matches rs-input |
<p> <label for="gb-msg">Your message:</label><br> <textarea class="rs-textarea" id="gb-msg" rows="4" cols="40">Cool page! Greetings from a fellow webmaster!</textarea> </p>
Access for all: Label it with <label for> and size it with rows, the sunken bevel is paint, not policy. Invalid state matches rs-input: red border plus a linked rs-form-error line.
"You are here:", the directory-portal trail printed above every category page, mall-map style.
The "You are here:" trail as an ordered list of links.
| Class | Role |
|---|---|
rs-breadcrumbs |
the trail; bold prefix and > separators come from the CSS |
<nav class="rs-breadcrumbs" aria-label="You are here">
<ol>
<li><a href="#">Home</a></li>
<li><a href="#">Games</a></li>
<li aria-current="page">Star Quest 3D</li>
</ol>
</nav>
Access for all: <nav aria-label="You are here"> around an <ol>; the current page gets aria-current="page". Separators are CSS, invisible to readers.
The page basement of 1999: a "Last updated" line, an 88×31 badge wall, and a mailto envelope that spun.
The page footer kit: last-updated line, 88×31 badge wall, and a mailto.
| Class | Role |
|---|---|
rs-footer |
the footer kit wrapper |
rs-footer__updated |
the "Last updated:" line; pairs with the last-updated widget |
rs-footer__badges |
88×31 badge wall row |
rs-footer__email |
the mailto line |
<footer class="rs-footer">
<p class="rs-footer__updated">Last updated: March 14, 1999, fixed the guestbook, broke the counter.</p>
<div class="rs-footer__badges">
<a class="rs-button88" href="#">MADE WITH RETROSTRAP</a>
<a class="rs-button88" href="#">BEST VIEWED WITH EYES</a>
</div>
<p class="rs-footer__email">
Webmaster: <a href="mailto:webmaster@example.net">webmaster@example.net</a>
</p>
<p>© 1997-1999. All rights reserved, whatever that means.</p>
</footer>
Access for all: A real <footer> landmark; badge links need proper accessible names, and the mailto shows the address as its own link text.
The "DHTML dropdown menu" cut-and-pasted from a free-scripts site onto every portal of 2000.
A dropdown menu bar: nested list submenus open on hover and focus; the enhancer adds keyboard and tap.
| Class | Role |
|---|---|
rs-menu |
menu bar nav; nested ul submenus open on hover/focus-within |
<nav class="rs-menu" aria-label="Main menu">
<ul>
<li><a href="#">Home</a></li>
<li>
<button aria-expanded="false" aria-controls="menu-files">Files</button>
<ul id="menu-files">
<li><a href="#">Downloads</a></li>
<li><a href="#">Skins</a></li>
<li><a href="#">MIDI archive</a></li>
</ul>
</li>
<li><a href="#">Guestbook</a></li>
</ul>
</nav>
Access for all: Disclosure navigation, not role="menu": submenu triggers are <button aria-expanded aria-controls>, submenus are plain lists of links. The enhancer adds the full keyboard map.
The row of bevel-edged button links under the site logo, current page pressed in like a held key.
A horizontal bar of bevel-chip links; the current page renders sunken.
| Class | Role |
|---|---|
rs-navbar |
horizontal row of bevel-chip links; wraps to two rows below svga, never a hamburger |
<nav class="rs-navbar" aria-label="Site"> <a href="#" aria-current="page">Home</a> <a href="#">News</a> <a href="#">Downloads</a> <a href="#">Links</a> <a href="#">Guestbook</a> </nav>
Access for all: A <nav> landmark with an aria-label; the current page carries aria-current="page", that is what renders it sunken.
"Pages: [1] 2 3 … Next>", the forum thread pager, current page bracketed because you cannot click where you stand.
A page-number row: current page bracketed, Prev/Next in angle brackets.
| Class | Role |
|---|---|
rs-pagination |
the page link row; the current page is bracketed via aria-current |
<nav class="rs-pagination" aria-label="Pages"> <span aria-current="page">1</span> <a href="#">2</a> <a href="#">3</a> <a href="#">4</a> <span>…</span> <a href="#">12</a> <a href="#">Next></a> </nav>
Access for all: <nav aria-label="Pages"> of real links; the current page is plain text with aria-current="page", bracketed by CSS, never a link to itself.
The left-hand nav column of every frameset site: star bullets, bold section caps, links purple from visiting.
The left nav list: pixel bullets, section headers, and visited links proudly purple.
| Class | Role |
|---|---|
rs-sidenav |
the nav list; visited-link purple lives here |
rs-sidenav__section |
bold caps section header |
<nav class="rs-sidenav" aria-label="Site">
<h3 class="rs-sidenav__section">Main</h3>
<ul>
<li><a href="#">home</a></li>
<li><a href="#">news archive</a></li>
<li><a href="#">about me</a></li>
</ul>
<h3 class="rs-sidenav__section">Goodies</h3>
<ul>
<li><a href="#">midi jukebox</a></li>
<li><a href="#">cool links</a></li>
<li><a href="#">webrings</a></li>
</ul>
</nav>
Access for all: A <nav> landmark with an aria-label wrapping real lists; the bullets are decoration, and links keep their visited state on purpose.
"Skip intro", the most-clicked link of the splash-screen era, repurposed to jump keyboards straight to the content.
A skip-to-content link, visually hidden until focused, first in the tab order.
| Class | Role |
|---|---|
rs-skip |
visually hidden until focused, then a bevel chip at the top left |
No boxed specimen needed, this very page has one. Press Tab from the top of the page and the skip link steps out of hiding, exactly once, exactly where a keyboard needs it.
<a class="rs-skip" href="#main">Skip intro →</a> <main id="main"> <p>The skip link is the first thing the keyboard reaches, and invisible until it does.</p> </main>
Access for all: The first focusable element in <body>, pointing at #main; on focus it appears as a proper 3D button. Every page ships one.
Manila folder tabs with the active lip merged into its page, the property-sheet look, brought to the web.
Folder tabs over stacked panels; without the enhancer they are honest in-page links.
| Class | Role |
|---|---|
rs-tabs |
the tabs wrapper |
rs-tabs__tab |
one folder lip |
rs-tabs__panel |
one content panel |
rs-tabs__tab--active |
modifier: active lip merged into its panel |
<div class="rs-tabs">
<a class="rs-tabs__tab rs-tabs__tab--active" href="#tab-news">News</a>
<a class="rs-tabs__tab" href="#tab-files">Files</a>
<a class="rs-tabs__tab" href="#tab-links">Links</a>
<section class="rs-tabs__panel" id="tab-news">
<h3>News</h3>
<p>Version 0.9 of the map pack is out. The lava level no longer eats saves.</p>
</section>
<section class="rs-tabs__panel" id="tab-files">
<h3>Files</h3>
<p>Everything zipped, everything under a floppy.</p>
</section>
<section class="rs-tabs__panel" id="tab-links">
<h3>Links</h3>
<p>Sites I actually visit, all six of them.</p>
</section>
</div>
Access for all: Unenhanced it is honest in-page links to headed, stacked sections, the snippet shows that shape. The enhancer adds role=tablist/tab/tabpanel, aria-selected and roving tabindex.
The "^ Top" link sprinkled through every long FAQ, back when pages were tall and scroll wheels were optional.
The "^ Top" back-to-top link; instant jump, no smooth scroll.
| Class | Role |
|---|---|
rs-top |
the back-to-top link idiom; jumps instantly |
<h3 id="faq-part-9">Part 9: joystick trouble</h3> <p>…several screens of answers later…</p> <p><a class="rs-top" href="#top">^ Top</a></p>
Access for all: A plain in-page link; href="#top" falls back to the document top natively. The jump is instant, smooth scrolling is not used.
The webring bar bolted under the footer: Prev, Random, Next, and faith that surfers would keep the loop alive.
The centered prev/random/next bar with a ring name line; static links until the webring widget fills them.
| Class | Role |
|---|---|
rs-webring-bar |
centered prev/random/next bar |
rs-webring-bar__name |
the ring name line |
<nav class="rs-webring-bar" aria-label="Webring"> <p class="rs-webring-bar__name">This site is part of the Midnight Starfield webring.</p> <a href="#"><< Prev</a> <a href="#">Random</a> <a href="#">Ring Home</a> <a href="#">Next >></a> </nav>
Access for all: <nav aria-label="Webring"> of plain links, fully functional as static HTML before the webring widget ever loads.
The plain message bar, "Your entry has been added", sitting in the page like news, no animation.
An inline message bar in info, warn and error flavors; no animation, it is just there.
| Class | Role |
|---|---|
rs-alert |
inline message bar: icon slot plus text |
rs-alert--info |
modifier: silver |
rs-alert--warn |
modifier: #FFFFCC |
rs-alert--error |
modifier: #FFCCCC with red border; carries role="alert" |
Your entry has been added to the guestbook.
The jukebox is down for maintenance until Sunday.
Upload failed: the file is bigger than a floppy.
<p class="rs-alert rs-alert--info">Your entry has been added to the guestbook.</p> <p class="rs-alert rs-alert--warn">The jukebox is down for maintenance until Sunday.</p> <p class="rs-alert rs-alert--error" role="alert">Upload failed: the file is bigger than a floppy.</p>
Access for all: Static variants are just text where they stand; only --error carries role="alert", so errors injected after load get announced.
The system alert: titlebar, 32×32 icon, OK and Cancel, the box the operating system sent when it needed you.
The native dialog in system-alert costume: titlebar, icon, message and button row over a dithered backdrop.
| Class | Role |
|---|---|
rs-dialog |
native <dialog> in alert-box costume; 8×8 dither backdrop |
rs-dialog__titlebar |
titlebar; carries the id aria-labelledby points at |
rs-dialog__body |
icon slot plus message |
rs-dialog__buttons |
button row, a method="dialog" form |
rs-dialog--info |
modifier: info icon |
rs-dialog--warn |
modifier: warning icon |
rs-dialog--error |
modifier: error icon |
<dialog class="rs-dialog rs-dialog--warn" open aria-labelledby="dlg-del-title">
<div class="rs-dialog__titlebar" id="dlg-del-title">Confirm delete</div>
<div class="rs-dialog__body">
<p>Delete SPACETHEME.MID? You will have to hum it yourself.</p>
</div>
<form method="dialog" class="rs-dialog__buttons">
<button autofocus>OK</button>
<button value="cancel">Cancel</button>
</form>
</dialog>
Access for all: Native <dialog> opened with showModal(): focus containment, Escape and the top layer come from the platform. aria-labelledby points at the titlebar text; the button row is a method="dialog" form.
The bare "HTTP 404, File Not Found" server page, redecorated by webmasters into an apology with a way home.
The 404 furniture: a DOS box with the status line and a link back home.
| Class | Role |
|---|---|
rs-error-page |
the 404 furniture wrapper |
rs-error-page__code |
the status line, heading weight |
A page, not a widget, so the live specimen is our own 404 page. Go get lost for a minute; we'll wait.
<main class="rs-error-page"> <pre class="rs-dos"><span class="rs-error-page__code">HTTP 404, File Not Found</span> The file you asked for moved, got renamed, or never existed in the first place.</pre> <p><a href="/"><< Back to the homepage</a></p> </main>
Access for all: A page, not a widget: real <main>, the status line first in reading order, and a working link home. The sad floppy is decoration.
The hourglass, promoted from cursor to page furniture: "Loading, please wait…" while the modem sang.
An hourglass with "Loading, please wait…"; the --bar variant adds an indeterminate progress bar.
| Class | Role |
|---|---|
rs-loading |
hourglass sprite plus waiting text |
rs-loading--bar |
modifier: wraps an indeterminate rs-progress |
Loading, please wait…
Loading, please wait…
<p class="rs-loading">Loading, please wait…</p> <div class="rs-loading rs-loading--bar"> <p>Loading, please wait…</p> <div class="rs-progress rs-progress--indeterminate" role="progressbar" aria-label="Loading"></div> </div>
Access for all: The text carries the meaning; the hourglass is aria-hidden decoration and holds still under reduced motion.
onMouseOver image swaps: the first bit of interactivity most homepages ever shipped.
The onmouseover swap, hide one thing, reveal another on hover or focus, in pure CSS.
| Class | Role |
|---|---|
rs-rollover |
the wrapper; give it its own accessible name |
rs-rollover__off |
shown at rest |
rs-rollover__on |
revealed on hover or focus |
<a class="rs-rollover" href="#top"> <span class="rs-rollover__off">★ back to top ★</span> <span class="rs-rollover__on">▲ back to top ▲</span> </a>
Access for all: The two halves are paint only; the wrapping link or button carries the accessible name. It swaps on focus as well as hover, so keyboard users see it too.
The click-to-enter splash page: a huge title, an [ ENTER ] link, and a webmaster certain you would wait.
A click-to-enter intro sheet, hidden until its enhancer decides to show it; the page never depends on it.
| Class | Role |
|---|---|
rs-splash |
full-viewport click-to-enter sheet; hidden until the enhancer reveals it |
rs-splash__enter |
the [ ENTER ] button |
No live specimen for this one: the splash covers the entire screen by design and would sit on top of the whole museum. Paste the source into a blank page and enjoy the ta-da, it is always skippable, and it remembers being skipped.
<dialog class="rs-splash" aria-label="Welcome" hidden> <h1 class="rs-font-7">STAR QUEST 3D</h1> <p>a fan zone since 1998</p> <button class="rs-btn rs-btn--large rs-splash__enter" autofocus>[ ENTER ]</button> </dialog> <main> <p>The actual page. It reads fine whether or not the splash ever appears.</p> </main>
Access for all: A native <dialog aria-label="Welcome"> with an autofocused Enter button; the page behind stays in the DOM and is never hidden from assistive tech.
The browser status bar every 1998 homepage scribbled welcomes into, rebuilt in-page, where it can't spoof a link.
A sunken status strip whose direct children become cells. With JS, a hovered or focused link's real destination previews in a cell laid over the bar.
| Class | Role |
|---|---|
rs-statusbar |
sunken strip; direct children become groove-divided cells |
<div class="rs-statusbar"> <span>Document: Done</span> <span>4 visitors online</span> <span>Best viewed at 800x600</span> </div>
Access for all: Static text, no live region, a status bar that chattered would be worse than one that blinked. If a ticker docks here, the ticker brings its own screen-reader manners.
The Back, Forward, Stop and Reload strip of every 1998 browser window, grooves between the button families.
A raised strip of buttons with groove separators that wraps instead of hiding.
| Class | Role |
|---|---|
rs-toolbar |
the raised strip; wraps, never collapses into an overflow menu |
rs-toolbar__sep |
groove separator between button groups |
<div class="rs-toolbar"> <button type="button" class="rs-btn">Back</button> <button type="button" class="rs-btn">Forward</button> <span class="rs-toolbar__sep" aria-hidden="true"></span> <button type="button" class="rs-btn">Reload</button> <button type="button" class="rs-btn">Home</button> <span class="rs-toolbar__sep" aria-hidden="true"></span> <button type="button" class="rs-btn">Music: off</button> </div>
Access for all: Buttons stay real buttons in the tab order; mark each separator aria-hidden, it is furniture. Overflow wraps to a second row, so nothing ever hides behind a menu.