What this is
In a federated university with hundreds of independently run sites, no one could mandate consistency - only earn voluntary adoption. This spec documents the piece of that system with the clearest trade-off: Illini Orange, the university's most recognizable brand color, fails accessibility contrast as ordinary text. Everything here - the token rules, the Button variants, the focus-state options - exists to resolve that tension without asking any team to choose between "on-brand" and "accessible."
Scope of this document. Two layers of one system: the color/contrast rules every component inherits from, and the Button component built on top of them.
Melissa designed buttons, header, hero, quote, statistics, and image-feature components. The shared component library gave WordPress and Drupal teams a foundation they could use and build on top of. This write-up goes deep on Button rather than wide across the system.
The component library began in Adobe XD and later moved to Figma. Its shared foundation supported both WordPress and Drupal teams, regardless of CMS.
What's original, from 2020-2023: the token names and hex values, the contrast rules, the Illini Orange resolution, and the six Button variants and their default appearance. Melissa built the design foundation and led the core design work; the front-end developer named the tokens and built production components. Button's own hover, focus, and disabled mechanics don't have surviving evidence pinning down the original specifics, so they're shown matching the verified current production system instead of a guess (see Explorations).
What's cross-checked against the current system, as of July 2026: the real class names (ilw-button, ilw-theme-*), the anchor/button component split, and the production markup shown in Components. The live system's newer orange-theme contrast fix, covered in Explorations, came after this foundation and is shown as a comparison, not as work done during the original role.
Color
The system names its colors instead of picking a hex value per screen. Five families, each with tints for text, hover, and disabled states.
The contrast rule
Normal text - 4.5:1 minimum
Applies to regular text below 24px, or bold text below 19px. This is body copy, captions, and most link text.
Large text & UI components - 3:1 minimum
Applies to regular text at 24px+, bold text at 19px+, and to graphical/UI elements like button fills and input borders.
The Illini Orange problem - the signature trade-off
Illini Orange is the university's most recognizable brand asset. It also fails WCAG contrast as ordinary text on white. Computed against the real token value:
il-orange #FF5F05 on white #FFFFFF
Fails the 4.5:1 normal-text minimum. Never set body copy, captions, or small links in orange on white.
Passes the 3:1 large-text minimum at 24px+ regular or 19px+ bold. Safe for headings only.
Passes the 3:1 UI-component minimum. This is why orange lives on filled controls and large accents, not on text.
The live system defines white-on-orange as a shared control-accent token, so it governs any filled-orange control, not just Button.
The resolution: il-blue and il-industrial carry text and link duty; il-orange is reserved for fills, large headings, and hover/focus accents. Never use it for body text, captions, or small links, regardless of how on-brand it feels.
The second failure - il-altgeld on il-blue
Orange isn't the only pairing that fails. Il-altgeld, the darker hover/focus red-orange, fails outright against the dark-blue theme. No size rescues it the way large text rescues orange.
il-altgeld #C84113 on il-blue #13294B
Fails the 4.5:1 normal-text minimum.
Also fails the 3:1 large-text/UI minimum. There's no size that saves this pairing.
This is a different category of failure than orange-on-white. Orange is restricted: safe at large or bold sizes, unsafe as body text. Altgeld-on-blue is excluded: it doesn't clear either threshold at any size, which is why the original theme spec marked it "only if needed" instead of giving it a sanctioned use case the way orange got one.
All pairings - quick reference
Every pairing referenced in this document, in one table. Failing or restricted pairings first, so the exceptions are the first thing a reader checks against.
| Pairing | Ratio | Normal text (4.5:1) | Large text / UI (3:1) |
|---|---|---|---|
| Fails or restricted use | |||
| il-altgeld #C84113 on il-blue #13294B | 2.9:1 | Fail | Fail |
| il-orange #FF5F05 on white #FFFFFF - restricted to large headings | 3.05:1 | Fail | Pass |
| white #FFFFFF on il-orange #FF5F05 - restricted to bold labels on filled-orange controls (not button-only) | 3.05:1 | Fail | Pass |
| Passes at all text sizes | |||
| il-blue #13294B on white #FFFFFF - headings, body | 14.5:1 | Pass | Pass |
| white #FFFFFF on il-blue #13294B - dark-theme body | 14.5:1 | Pass | Pass |
| il-industrial #1D58A7 on white #FFFFFF - links | 7.0:1 | Pass | Pass |
| il-altgeld #C84113 on white #FFFFFF - hover/focus links | 5.0:1 | Pass | Pass |
| il-orange #FF5F05 on il-blue #13294B - dark-theme hover link | 4.8:1 | Pass | Pass |
| il-blue #13294B on il-orange #FF5F05 - current live system's orange-theme body text | 4.76:1 | Pass | Pass |
Do
Use il-orange #FF5F05 for button fills, large display headings, and hover/focus accents.
These all sit at large-text or UI-component size, where 3.05:1 passes.
Don't
Set body copy, captions, or small links in il-orange #FF5F05 on a white #FFFFFF or light background.
3.05:1 fails the 4.5:1 minimum for normal text. This text is genuinely hard to read for low-vision users.
Color themes
Here's how the tokens above hold up on every page background in the system: a heading, body copy, link, and button on each, checked in context instead of a swatch grid.
Program Overview
Explore requirements, faculty, and outcomes for this program.
Program Overview
Explore requirements, faculty, and outcomes for this program.
Program Overview
Explore requirements, faculty, and outcomes for this program.
Program Overview
Explore requirements, faculty, and outcomes for this program.
Program Overview
Explore requirements, faculty, and outcomes for this program.
Program Overview
Explore requirements, faculty, and outcomes for this program.
Component: Button
Six variants, each with a default and hover/focus treatment, all built from the token rules in Color. Tab to any button below to see the real focus state. Nothing here is a screenshot.
Anatomy
48px minimum height meets the WCAG 2.5.5 target-size guidance for touch. 24px gap when two buttons sit side by side.
Element choice: <a> vs <button>
"Button" describes how this looks, not what HTML element it is. Most of what reads visually as a button on a university site (Apply Now, View Program, Request Info) actually navigates to a URL, which makes it a link.
<a href="..."> - navigates
Use when activating it takes the user to a new URL or page section.
- Enter activates it; right-click / long-press still offers "open in new tab"
- Screen readers announce it as a link
- Covers almost every marketing/CTA button: Apply, View Program, Request Info
<button> - performs an action
Use when activating it does something on the current page and goes nowhere.
- Enter and Space both activate it
- Screen readers announce it as a button, not a link
- Submit a form, open a modal, toggle a menu, delete a row, and it's the only way to natively express "disabled"
A design tool only specifies what a button looks like. The HTML element it becomes has to be decided separately for every real implementation. Getting it wrong either way is a real accessibility bug, not a style nitpick: a JS-only "button" built on a bare <a href="#"> breaks right-click/open-in-new-tab and tells screen reader users they're leaving the page when they're not. A page action wrapped in <button> and then navigated via JavaScript loses native browser history and middle-click-to-open-in-new-tab behavior.
The current live toolkit still ships this as two separate, deliberately distinct components: Global Button Styles (anchor) and Global Button Styles (button), rather than one component with a variant flag. <a class="ilw-button ilw-theme-blue-solid" href="/apply">Apply Now</a> and <button class="ilw-button ilw-theme-blue-solid">Submit</button> are two different components that happen to look identical.
Variants - live states
Use it for the one primary action on a page, like Apply Now or View Program. Default: il-blue fill, white text (14.5:1). Hover: fill and text swap, white background with il-blue text, underlined.
Use it sparingly, for a secondary action that still needs the brand orange, like a callout inside a promotional banner. Label text sits at 3.05:1, which passes only because it's bold and 16px or larger. Never shrink this label below the bold, 19px threshold. Hover: fill and text swap, same as Solid Blue, underlined.
Use it for a secondary action next to a Solid Blue button, or anywhere a button needs to sit quietly instead of competing for attention. Default: il-blue text and border on white (14.5:1). Hover: fill and text swap, il-blue background with white text, underlined.
Use it the same way as Outline Blue, when the on-brand orange accent fits the page better than blue. Label is set in il-altgeld, not il-orange (5.0:1 vs. 3.05:1): the darker tint keeps the resting label legible. Hover: fill and text swap, il-altgeld background with white text, underlined.
Use it on dark banners or photo backgrounds, where a dark-text button would disappear. Default: white text/border on il-blue (14.5:1). Hover: fill and text swap, white background with il-blue text, underlined.
Use it only when the action is temporarily unavailable and the person benefits from seeing why, like a Submit button before required fields are filled in. If the action just doesn't apply at all, remove the button instead of disabling it. White background, light-gray text and border, no hover or focus treatment, disabled attribute set: not just a visual style, so assistive tech announces it correctly. This is the one variant that has to render as <button>. Links have no native disabled state, so a "disabled link" is really just a link styled to look unclickable while still being fully clickable and focusable.
One button, every state
Solid Blue, shown default, hovered, keyboard-focused, and disabled, side by side. This is a static reference for anyone who wants to see all four without tabbing through the live buttons above.
States reference
| State | Trigger | What changes |
|---|---|---|
| Default | At rest | Base fill/border/text per variant, as specified above |
| Hover | Mouse over | Background and text swap, underline added (mouse users only) |
| Focus | Any focus, keyboard or mouse | Background swaps to a light blue tint, text becomes il-blue, underline added, no outline ring |
| Active | Mouse/key down | Not separately specified in this reconstruction; no distinct pressed style is defined here |
| Disabled | disabled attribute | White background, light-gray text and border, pointer-events removed, announced as disabled by assistive tech |
Accessibility checklist
- Contrast: every default-state label meets 4.5:1, or is bold/19px+ meeting the 3:1 large-text exception (Solid Orange only).
- Focus is never hover-only: the focus treatment renders on any
:focus, not just:hover, so keyboard and switch-device users always see it, independent of whether the pointer is anywhere near the button. - Target size: 48px minimum height meets WCAG 2.5.5 for touch and low-precision input.
- Real disabled state: uses the native
disabledattribute, not just a gray style, so screen readers announce it correctly. - Don't rely on color alone: hover and focus swap fill and text color and add an underline, not just a hue shift, for users with low color vision.
Accessible names - the same button, many times on one page
Contrast and focus states cover a button standing alone. Academic sites rarely show just one button: a program-listing page repeats the same CTA on every card: Learn More, Learn More, Learn More. A sighted user tells them apart by which card they're inside. A screen reader user navigating by a buttons/links list hears the same word repeated with no card context at all.
Any academic site with a course catalog, staff directory, or degree list has the identical problem: one visual label, applied many times, needs a distinct accessible name each time.
Don't
<!-- repeated on every program card, identical accessible name --> <a class="ilw-button" href="/programs/animal-sciences">Learn More</a> <a class="ilw-button" href="/programs/agribusiness">Learn More</a>
A screen reader's links list reads "Learn More, Learn More, Learn More…," each one indistinguishable, with no way to know which program is which without leaving list-navigation mode.
Do
<!-- visible label stays short; accessible name adds the program --> <a class="ilw-button" href="/programs/animal-sciences"> Learn More <span class="sr-only">about Animal Sciences</span> </a>
The card still reads "Learn More" visually. The accessible name becomes "Learn More about Animal Sciences," distinct in a links list, and it still starts with the visible words.
That last clause matters on its own: WCAG 2.5.3 (Label in Name) requires the accessible name to start with or contain the visible label. A tempting shortcut - aria-label="Animal Sciences program details" with no "Learn More" in it at all - fixes the screen-reader list problem but breaks voice-control users, who say "click Learn More" expecting it to match what's on screen. An aria-labelledby that points at the card's own heading plus the button text works too, and has the advantage of staying in sync automatically if the program name ever changes - it can't drift the way a hand-written aria-label can.
This is a <button>-vs-<a> question too: since "Learn More" navigates to a program page, it stays an <a href> - the accessible-name fix doesn't change the element-choice rule above, it layers on top of it.
Code - this prototype (simplified)
<a class="btn solid-blue" href="/apply">Apply Now</a> .btn { font-weight: 700; min-height: 48px; padding: 16px 20px; border-radius: 4px; } .btn.solid-blue { background: var(--il-blue); color: #fff; } .btn:focus-visible { outline: 3px solid var(--il-orange); outline-offset: 2px; }
Code - actual current production markup
<a href="/apply" class="ilw-button ilw-theme-blue-solid">Apply Now</a> <button class="ilw-button ilw-theme-blue-solid">Submit</button> // theme options: ilw-theme-blue, ilw-theme-orange, ilw-theme-blue-solid, ilw-theme-orange-solid, // ilw-theme-blue-outline, ilw-theme-orange-outline, ilw-theme-blue-inverse, ilw-theme-orange-inverse // size options: ilw-button-small, ilw-button-large // width (button only): ilw-width-full
Do
Bold, 16px+ label on the il-orange #FF5F05 fill: passes the 3:1 UI-component threshold, on-brand and legible.
Don't
A small, regular-weight il-orange #FF5F05 "link-styled button" like this fails 4.5:1: it looks like a button, but it isn't held to button-level contrast rules, so it reads as low-contrast text instead.
Explorations
What got tested and rejected along the way, and what's changed in the live system since the 2020-2023 foundation.
Focus states - the options that were tested
Three focus-indicator options were tested for links and headings, using the same real HTML page tested with keyboard and screen-reader users, before the dotted-outline treatment was adopted. Tab through each to compare.
If Tab doesn't move focus in your browser or device, this is exactly what each option looks like. Nothing above needs to be triggered to see it.
Focus, hover, and visited states were deliberately kept visually distinct from one another: a user tabbing through a page needs to tell "this is where my keyboard focus is" apart from "I've already clicked this" at a glance.
How the live system evolved
Checking the current production colors.css (WIGG, 2025) shows the orange-contrast problem got a second, more precise fix since the 2020–2023 foundation this document is built from. A page-wide orange theme now sets body text to il-blue on il-orange - 4.76:1, which passes even the 4.5:1 normal-text minimum, not just the large-text exception this document uses for button labels. White-on-orange is kept only for the button/control accent, where large-bold text and the 3:1 UI threshold still apply. Same trade-off, resolved slightly differently depending on how much of the surface is orange.
Why Components shows today's Button mechanics, not a 2020-2023 guess
The focus exploration above is real, sourced material for links and headings. Button's own hover, focus, and disabled behavior is different: there's no surviving evidence of what the original 2020-2023 build did specifically, unlike the tested-and-rejected options above. Rather than present a guess as history, Components shows the verified current production system directly, confirmed against buttons.css (WIGG, 2025).
| State | Verified current behavior, shown in Components |
|---|---|
| Hover | Background and text swap, plus an underline, the same rule for every variant. An earlier draft of this reconstruction had each variant darken to a distinct color instead; that guess is corrected here. |
| Focus | Background swaps to a light blue tint with il-blue text and an underline, no outline ring, on any :focus rather than only :focus-visible. An earlier draft showed a 3px solid il-orange outline, adapted from the link/heading choice above without direct Button-specific evidence; that guess is corrected here. |
| Disabled | White background, light-gray text and border (il-storm-lighter-1), no hover or focus treatment. An earlier draft used 45% opacity instead; that guess is corrected here. |
The exact hex behind the current focus background (il-arches-90, a newer token not in the four families this document otherwise uses) isn't independently resolved here. The swatch shown uses il-industrial-lighter-3 from the original 2020-2023 palette as the closest verified stand-in, not the confirmed current value.
Governance
Who owns this, what it's built on, and where to verify it independently.
About this reconstruction
This is authorship and provenance for the portfolio document itself, not a claim over Illinois's current, live governance.
Sources
webtheme.illinois.edu · builder3.toolkit.illinois.edu · github.com/web-illinois/toolkit-management