Welcome to Rails A11y! This guide will help you get up and running with accessibility testing in your Rails application in just a few minutes.
Rails A11y is an accessibility testing gem that automatically checks your Rails views for WCAG 2.1 AA compliance. Think of it as RSpec + RuboCop for accessibility—it catches violations as you code, not after deployment.
Add to your Gemfile:
group :development, :test do
gem 'rails_accessibility_testing'
gem 'rspec-rails', '~> 8.0' # Required for system specs
gem 'axe-core-capybara', '~> 4.0'
gem 'capybara', '~> 3.40'
gem 'selenium-webdriver', '~> 4.0'
gem 'webdrivers', '~> 5.0' # Optional but recommended
endImportant: You must explicitly add selenium-webdriver to your Gemfile. It's not automatically included as a dependency.
Then run:
bundle installrails generate rails_a11y:installNote: The generator uses the short name rails_a11y for convenience. The gem name is rails_accessibility_testing.
This creates:
config/initializers/rails_a11y.rb- Configurationconfig/accessibility.yml- Check settingsspec/system/all_pages_accessibility_spec.rb- Comprehensive spec that tests all GET routes- Updates
spec/rails_helper.rb(if using RSpec) - Updates
Procfile.dev- Adds static accessibility scanner
The generator automatically adds a static accessibility scanner to your Procfile.dev:
web: bin/rails server
css: bin/rails dartsass:watch
a11y: bundle exec a11y_static_scannerThen run:
bin/devThis will:
- Start your Rails server
- Watch for CSS changes
- Continuously scan view files for accessibility issues - Only scans files that have changed since last scan
- Shows errors with exact file locations and line numbers
How it works:
- Scans all files on startup
- Only re-scans files that have been modified
- Watches for file changes and re-scans automatically
- No browser needed - scans ERB templates directly
Configuration (in config/accessibility.yml):
static_scanner:
scan_changed_only: true # Only scan changed files
check_interval: 3 # Seconds between file checks
full_scan_on_startup: true # Full scan on startupbundle exec rspec spec/system/Accessibility checks run automatically on every system test that visits a page.
Run the comprehensive spec that tests all GET routes:
bundle exec rspec spec/system/all_pages_accessibility_spec.rbCreate a simple system spec:
# spec/system/home_spec.rb
RSpec.describe "Home Page", type: :system do
it "displays the welcome message" do
visit root_path
expect(page).to have_content("Welcome")
# ✅ Accessibility checks run automatically here!
end
endWhile checks run automatically after each visit, you can also run comprehensive checks explicitly:
# spec/system/my_page_accessibility_spec.rb
require 'rails_helper'
RSpec.describe 'My Page Accessibility', type: :system do
it 'loads the page and runs comprehensive accessibility checks' do
visit root_path
check_comprehensive_accessibility # All 11 checks
end
endRails A11y runs 11 comprehensive checks automatically. These checks are WCAG 2.1 AA aligned:
- Form Labels - All form inputs have associated labels
- Image Alt Text - All images have descriptive alt attributes
- Interactive Elements - Buttons, links have accessible names
- Heading Hierarchy - Proper h1-h6 structure without skipping levels
- Keyboard Accessibility - All interactive elements are keyboard accessible
- ARIA Landmarks - Proper use of ARIA landmark roles
- Form Error Associations - Form errors are properly linked to form fields
- Table Structure - Tables have proper headers
- Duplicate IDs - No duplicate ID attributes
- Skip Links - Skip navigation links present
- Color Contrast - Text meets WCAG contrast requirements (optional, disabled by default)
Edit config/accessibility.yml:
wcag_level: AA
# Summary configuration
summary:
show_summary: true
errors_only: false
show_fixes: true
ignore_warnings: false # Set to true to hide warnings, only show errors
# Static scanner configuration
static_scanner:
scan_changed_only: true # Only scan changed files
check_interval: 3 # Seconds between file checks
full_scan_on_startup: true # Full scan on startup
checks:
form_labels: true
image_alt_text: true
interactive_elements: true
heading_hierarchy: true
keyboard_accessibility: true
aria_landmarks: true
form_errors: true
table_structure: true
duplicate_ids: true
skip_links: true
color_contrast: false # Disabled by default (expensive)development:
checks:
color_contrast: false # Skip in dev for speed
ci:
checks:
color_contrast: true # Full checks in CIignored_rules:
- rule: form_labels
reason: "Legacy form, scheduled for refactor in Q2"
comment: "Will be fixed in PR #123"# RSpec
it "does something", skip_a11y: true do
# Accessibility checks won't run
end
# Minitest
test "does something", skip_a11y: true do
# Accessibility checks won't run
end- ⭐ Read the System Specs Guide - Recommended approach for reliable accessibility testing
- Read the CI Integration Guide to set up automated checks
- Check out Writing Accessible Views for best practices
- See Working with Designers for team collaboration
Create spec/support/driver.rb:
# spec/support/driver.rb
require 'selenium-webdriver'
require 'capybara/rails'
require 'capybara/rspec'
# Configure Chrome options
browser_options = Selenium::WebDriver::Chrome::Options.new
browser_options.add_argument('--window-size=1920,1080')
browser_options.add_argument('--headless') unless ENV['SHOW_TEST_BROWSER']
# Register the driver
Capybara.register_driver :selenium_chrome_headless do |app|
Capybara::Selenium::Driver.new(
app,
browser: :chrome,
options: browser_options
)
end
# Configure RSpec to use the driver for system tests
RSpec.configure do |config|
config.before(:each, type: :system) do
driven_by :selenium_chrome_headless
end
endmacOS:
brew install --cask google-chromeLinux (Ubuntu/Debian):
sudo apt-get update
sudo apt-get install -y google-chrome-stableWindows: Download and install Chrome from google.com/chrome
The webdrivers gem will automatically download and manage the ChromeDriver binary for you.
Make sure you've added gem 'selenium-webdriver', '~> 4.0' to your Gemfile and run bundle install.
- Make sure Chrome is installed
- If using
webdriversgem, it should auto-download ChromeDriver. If not:bundle exec webdrivers chrome
Check:
- Your spec has
type: :systemmetadata spec/support/driver.rbexists and is properly configured- Chrome is installed and accessible
Disable expensive checks in development:
# config/accessibility.yml
development:
checks:
color_contrast: false # Disable expensive color contrast checks| Component | Recommended Version | Minimum Version | Required |
|---|---|---|---|
| Ruby | 3.1+ | 3.0+ | Yes |
| Rails | 7.1+ / 8.0+ | 6.0+ | Yes |
| RSpec Rails | 8.0+ | 6.0+ | Yes (for system specs) |
| Capybara | ~> 3.40 | 3.0+ | Yes |
| selenium-webdriver | ~> 4.10 | 4.0+ | Yes |
| webdrivers | ~> 5.3 | 5.0+ | Optional |
A: No! Rails A11y works with your existing system tests. Just run them as usual.
A: Checks only run when you visit a page in a system test. The checks are fast, and you can disable expensive ones (like color contrast) in development.
A: Yes! See the Minitest integration in the main README.
A: You can disable specific checks in config/accessibility.yml or ignore specific rules with a reason.
- Documentation: See the main README
- Issues: GitHub Issues
- Email: imregan@umich.edu
Ready to make your Rails app accessible? Run your tests and start fixing issues! 🚀