Updating Alma Letter Accessibility
Common Accessibility Issues to Check in Your Alma Letters
CARLI is actively reviewing I-Share Alma letters for accessibility issues and working to bring them into compliance with WCAG 2.1 Level AA. This page documents common issues we have identified across Alma letter XSL templates, along with the specific changes CARLI has made to the shared letter components distributed through the Network Zone. We will update this page as our review continues.
Last Updated: Sept. 9, 2026
Structure and Markup
Missing language declaration
Every letter should have lang="en" on the <html> tag. Without it, screen readers may guess the wrong language and mispronounce content.
Instead of:
<html>
Use:
<html lang="en">
Non-descriptive image alt text
Most Alma letters use the header.xsl template to display the library logo, but some letters have the code for the logo written into the letter's XSL.
Search your letter's XSL for <img and check the alt= value. If it says alt="logo" that needs to be fixed. It should either be your institution's name, or alt="" if the letter heading already identifies the sender.
Instead of:
<img src="cid:logo.jpg" alt="logo"/>
Use:
<img src="cid:logo.jpg" alt=""/>
or
<img src="cid:logo.jpg" alt="University Library"/>
Invalid HTML tags: <h>
<h> is not a real HTML element and carries no meaning for assistive technology. Replace with <p> for body text, or a proper heading tag (<h2>, <h3>) if it is actually a heading.
Presentational <b> instead of semantic <strong>
For text that needs to convey emphasis or importance, use <strong> rather than <b>. Most email clients render them identically but <strong> carries meaning for assistive technology.
Tables and Styling
Data tables missing column scope
Any table displaying item data (titles, due dates, barcodes, etc.) should have scope="col" on each <th> element so screen readers can associate headers with the correct data cells.
Instead of:
<th>Title</th>
Use:
<th scope="col">Title</th>
Deprecated bgcolor attribute
The bgcolor attribute is old HTML and not reliably supported. Replace with an inline style.
Instead of:
<tr bgcolor="#f5f5f5">
Use:
<tr style="background-color:#f5f5f5;">
Hardcoded small font size
If your letter has font-size:80% in the body style, remove it or set it to 100%. Shrinking text below the user's default is an accessibility problem, especially for low vision users.
<br/> used for spacing inside tables
Line breaks placed inside a <table> but outside a <td> are invalid HTML and can behave unpredictably across email clients. Use padding or margin on surrounding elements instead.
What CARLI Changed in the Shared Letter Templates
The following changes were made to the shared Alma letter component templates in the I-Share Network Zone and propagated to all member libraries. If you have made local customizations to any of these templates, your version was not overwritten and you may need to apply these changes manually.
style.xsl
The global CSS stylesheet inherited by all letters. Changes here propagate across every letter automatically.
Fixed h4 line-height
The original value of 0.2em collapsed heading text on itself. 1.4em is the accessible standard.
Before:
h4 {line-height: 0.2em}After:
h4 {line-height: 1.4em}Bumped font size from 80% to 100%
Forcing body text to 80% of the user's default is an accessibility problem, especially for low vision users who have deliberately set their browser text size larger.
Before:
font-family: Tahoma; color:#333; margin:0; padding:0em; font-size:80%
After:
font-family: Tahoma, Arial, sans-serif; color:#333333; margin:0; padding:0; font-size:100%
Removed text-shadow calls
White shadow on a light gray header and dark shadow on a dark footer both render invisibly and serve no purpose. Removed from both headerTableStyleCss and footerTableStyleCss.
Before (header):
background-color:#e9e9e9; width:100%; height:30px; text-shadow:1px 1px 1px #fff;
After (header):
background-color:#e9e9e9; width:100%; height:30px;
Before (footer):
background-color:#444; width:100%; text-shadow:1px 1px 1px #333; color:#fff; margin-top:1em; font-weight:700; line-height:2em; font-size:150%;
After (footer):
background-color:#333333; width:100%; color:#ffffff; margin-top:1em; font-weight:700; line-height:2em; font-size:150%;
Improved footer contrast
The original footer background of #444 gave a contrast ratio of ~5.7:1 against white text — borderline for WCAG AA. Darkening to #333333 brings it to ~7:1, comfortably above the threshold.
Standardized hex colors to 6 digits
Shorthand hex values were expanded to their 6-digit equivalents throughout for consistency and to avoid ambiguity across email clients.
Examples:
#fff → #ffffff #eee → #eeeeee #333 → #333333
Added font fallback stack
Added Arial, sans-serif as fallbacks after Tahoma. If Tahoma is unavailable, email clients now fall back gracefully rather than guessing.
Before:
font-family: Tahoma;
After:
font-family: Tahoma, Arial, sans-serif;
header.xsl
Provides the logo and letter title header used by most letters via <xsl:call-template name="head" />.
Fixed logo alt text
The institution logo in the main header is decorative — the letter name in the <h1> below it already identifies the context. Empty alt text tells screen readers to skip it. The I-Share logo in receiptPrinterHead has no accompanying heading, so it gets descriptive alt text instead.
Before (both templates):
<img src="cid:logo.jpg" alt="logo"/>
After (head template — decorative):
<img src="cid:logo.jpg" alt=""/>
After (receiptPrinterHead — descriptive):
<img src="https://www.carli.illinois.edu/.../iShare-stacked-color.jpg" width="200" height="57" alt="I-Share"/>
footer.xsl
Provides the address footer and contact/account links used by most letters.
Removed misapplied list styles
The listStyleCss template was being applied to a <tr> element in the lastFooter template. List styles on table rows have no effect and were removed.
Before:
<tr>
<xsl:attribute name="style">
<xsl:call-template name="listStyleCss" />
</xsl:attribute>After:
<tr>
mailReason.xsl
Provides the salutation template used by letters that call toWhomIsConcerned. No accessibility changes were needed to this template's structure or styling.
recordTitle.xsl
Displays the title, author, and volume/issue description for a physical item.
Removed whitespace spacers
The original template used three literal spaces before each value to create visual indentation. Screen readers may announce or stumble over leading whitespace. Replaced with margin-bottom: 0.5em on each <div> for proper spacing.
Before:
<div class="recordTitle"> <span class="spacer_after_1em"> <xsl:value-of select="..."/></span> </div>
After:
<div class="recordTitle" style="margin-bottom:0.5em;"> <xsl:value-of select="..."/> </div>
Removed undefined class and unnecessary wrapper spans
The spacer_after_1em class is not defined anywhere in style.xsl and was doing nothing. The extra wrapping <span> elements and empty class="" attributes were also removed.
senderReceiver.xsl
Displays the patron and institution address block used by most letters.
Removed misapplied list styles
The listStyleCss template was being applied to <table> elements in all three address blocks. List styles on tables have no effect. Removed from the user_for_printing, receiver/user, and organization_unit blocks.
Before:
<table cellspacing="0" cellpadding="5" border="0">
<xsl:attribute name="style">
<xsl:call-template name="listStyleCss" />
</xsl:attribute>After:
<table cellspacing="0" cellpadding="5" border="0">
Added conditional checks for empty address lines
The receiver and organization unit address blocks were rendering all address lines unconditionally, which could produce empty <tr> rows for patrons or libraries with incomplete address data. Added <xsl:if> checks to match the pattern already established in the user_for_printing block.
Before (receiver block — unconditional):
<tr><td><xsl:value-of select="user_address_list/user_address/line1"/></td></tr> <tr><td><xsl:value-of select="user_address_list/user_address/line2"/></td></tr>
After (receiver block — conditional):
<xsl:variable name="rline1" select="user_address_list/user_address/line1"/> <xsl:if test="$rline1 != ''"><tr><td><xsl:value-of select="$rline1"/></td></tr></xsl:if> <xsl:variable name="rline2" select="user_address_list/user_address/line2"/> <xsl:if test="$rline2 != ''"><tr><td><xsl:value-of select="$rline2"/></td></tr></xsl:if>