sass-a11y 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +4 -0
- data/README.md +38 -0
- data/lib/sass-a11y.rb +17 -0
- data/stylesheets/_a11y.scss +1 -0
- data/stylesheets/a11y/_colors.scss +2 -0
- data/stylesheets/a11y/colors/_contrast--closest.scss +26 -0
- data/stylesheets/a11y/colors/_contrast--find.scss +60 -0
- data/stylesheets/a11y/colors/_contrast--output.scss +9 -0
- data/stylesheets/a11y/colors/_contrast--overlay.scss +38 -0
- data/stylesheets/a11y/colors/_contrast--settings.scss +22 -0
- data/stylesheets/a11y/colors/_contrast.scss +67 -0
- data/stylesheets/a11y/colors/_luminance.scss +29 -0
- metadata +84 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c893d23e4d73668987613c85926c9bd3948567ea
|
4
|
+
data.tar.gz: d26210d167b440fa70e798ca1360197898f4b86e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 22c12a1a31e28f2e3a6b3feee406e800f08478e6c26e0ac497993222c4fe1a0e6befee6bfe22991e1c4b689a217072248754a68618e7d8731df374256388529e
|
7
|
+
data.tar.gz: 4244a9dbda05881e91b4c9df13b472bfb29caec8ed29bb52270c548e901e87f80d523eb2f77751d37510141f0080b198512d25cb841fa52316a3573001c68ae0
|
data/CHANGELOG.md
ADDED
data/README.md
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# Sass A11Y
|
2
|
+
Accessibility helpers for Sass.
|
3
|
+
|
4
|
+
While working in Sass, it's useful to check to ensure your decisions are accessible ones. This Compass plugin (for the time being, until Sass gets an exponent function) will assist you in ensuring your designs are accessible as much as it can without having your whole site rendered.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Add the following to your Gemfile:
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
gem 'sass-a11y', '<1.0'
|
12
|
+
```
|
13
|
+
|
14
|
+
And the following to `config.rb`:
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
require 'sass-a11y'
|
18
|
+
```
|
19
|
+
|
20
|
+
Finally, import the partials
|
21
|
+
|
22
|
+
```scss
|
23
|
+
@import "a11y";
|
24
|
+
```
|
25
|
+
|
26
|
+
## Functions
|
27
|
+
|
28
|
+
### `a11y-contrast($color, $background)`
|
29
|
+
|
30
|
+
Will determine if the color passes [W3C Contrast Minimums](http://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html) when placed on the given background. Based on Lea Verou's fantastic [contrast-ratio site](http://leaverou.github.io/contrast-ratio/) so it works with transparent colors as well!
|
31
|
+
|
32
|
+
Failing color combinations will throw an error, everything else will debug out the contrast minimum it passes. Failing color combinations will return `false`, passing ones will return `true`.
|
33
|
+
|
34
|
+
To suppress messages, set `$A11Y--Contrast-Output-Warnings: false;`.
|
35
|
+
|
36
|
+
### `a11y-luminance($color)`
|
37
|
+
|
38
|
+
W3C [relative luminance](http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef) functionality. Luminance is the relative brightness of any point in a colorspace, normalized to 0 for darkest black and 1 for lightest white based on the sRGB colorspace. Returns a unitless number.
|
data/lib/sass-a11y.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
base_directory = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
2
|
+
a11y_stylesheets_path = File.join(base_directory, 'stylesheets')
|
3
|
+
|
4
|
+
if (defined? Compass)
|
5
|
+
require 'sass-a11y'
|
6
|
+
Compass::Frameworks.register(
|
7
|
+
"sassy-math",
|
8
|
+
:path => base_directory
|
9
|
+
)
|
10
|
+
else
|
11
|
+
ENV["SASS_PATH"] = [ENV["SASS_PATH"], a11y_stylesheets_path].compact.join(File::PATH_SEPARATOR)
|
12
|
+
end
|
13
|
+
|
14
|
+
module SassA11y
|
15
|
+
VERSION = "0.1.0"
|
16
|
+
DATE = "2014-09-25"
|
17
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
@import "a11y/colors";
|
@@ -0,0 +1,26 @@
|
|
1
|
+
//////////////////////////////
|
2
|
+
// Closest, used for contrast in alpha
|
3
|
+
//////////////////////////////
|
4
|
+
@function a11y-ContrastClosest($color, $background, $alpha: 1) {
|
5
|
+
$fColors: (
|
6
|
+
'red': red($background),
|
7
|
+
'green': green($background),
|
8
|
+
'blue': blue($background)
|
9
|
+
);
|
10
|
+
|
11
|
+
$bColors : (
|
12
|
+
'red': red($color),
|
13
|
+
'green': green($color),
|
14
|
+
'blue': blue($color)
|
15
|
+
);
|
16
|
+
|
17
|
+
$return: ();
|
18
|
+
|
19
|
+
@each $color, $value in $fColors {
|
20
|
+
$val: max(0, (map-get($bColors, $color) - ($value * $alpha)) / (1 - $alpha));
|
21
|
+
$val: min($val, 255);
|
22
|
+
$return: map-merge($return, ($color: $val));
|
23
|
+
}
|
24
|
+
|
25
|
+
@return rgb(map-get($return, 'red'), map-get($return, 'green'), map-get($return, 'blue'));
|
26
|
+
}
|
@@ -0,0 +1,60 @@
|
|
1
|
+
@import "contrast--settings";
|
2
|
+
|
3
|
+
//////////////////////////////
|
4
|
+
// Contrast Find
|
5
|
+
//////////////////////////////
|
6
|
+
@function a11y-ContrastFind($color, $background) {
|
7
|
+
$alpha: alpha($background);
|
8
|
+
|
9
|
+
@if $alpha >= 1 {
|
10
|
+
@if alpha($color) < 1 {
|
11
|
+
$color: a11y-ContrastOverlayOn($color, $background);
|
12
|
+
}
|
13
|
+
|
14
|
+
$l1: a11y-luminance($background) + .05;
|
15
|
+
$l2: a11y-luminance($color) + .05;
|
16
|
+
|
17
|
+
$ratio: $l1 / $l2;
|
18
|
+
|
19
|
+
@if ($l2 > $l1) {
|
20
|
+
$ratio: 1 / $ratio;
|
21
|
+
}
|
22
|
+
|
23
|
+
@return (
|
24
|
+
'ratio': $ratio,
|
25
|
+
'error': 0,
|
26
|
+
'min': $ratio,
|
27
|
+
'max': $ratio
|
28
|
+
);
|
29
|
+
}
|
30
|
+
// If we’re here, it means we have a semi-transparent background
|
31
|
+
// The text color may or may not be semi-transparent, but that doesn't matter
|
32
|
+
$onBlack: a11y-ContrastOverlayOn($background, map-get($A11Y--Contrast-Colors, 'black'));
|
33
|
+
$onBlack: a11y-ContrastFind($onBlack, $color);
|
34
|
+
$onBlack: map-get($onBlack, 'ratio');
|
35
|
+
|
36
|
+
$onWhite: a11y-ContrastOverlayOn($background, map-get($A11Y--Contrast-Colors, 'white'));
|
37
|
+
$onWhite: a11y-ContrastFind($onWhite, $color);
|
38
|
+
$onWhite: map-get($onWhite, 'ratio');
|
39
|
+
|
40
|
+
$max: max($onBlack, $onWhite);
|
41
|
+
|
42
|
+
$closest: a11y-ContrastClosest($color, $background, $alpha);
|
43
|
+
|
44
|
+
$min: a11y-ContrastOverlayOn($background, $closest);
|
45
|
+
$min: a11y-ContrastFind($color, $min);
|
46
|
+
$min-ratio: map-get($min, 'ratio');
|
47
|
+
|
48
|
+
$far: map-get($A11Y--Contrast-Colors, 'black');
|
49
|
+
@if $onWhite == $max {
|
50
|
+
$far: map-get($A11Y--Contrast-Colors, 'white');
|
51
|
+
}
|
52
|
+
|
53
|
+
@return (
|
54
|
+
'ratio': ($max + $min-ratio) / 2,
|
55
|
+
'error': ($max - $min-ratio) / 2,
|
56
|
+
'min': $min-ratio,
|
57
|
+
'max': $max,
|
58
|
+
'farthest': $far
|
59
|
+
);
|
60
|
+
}
|
@@ -0,0 +1,38 @@
|
|
1
|
+
//////////////////////////////
|
2
|
+
// Overlay colors
|
3
|
+
//////////////////////////////
|
4
|
+
@function a11y-ContrastOverlayOn($foreground, $background) {
|
5
|
+
$overlaid: $foreground;
|
6
|
+
|
7
|
+
$alpha: alpha($foreground);
|
8
|
+
$bAlpha: alpha($background);
|
9
|
+
|
10
|
+
@if $alpha >= 1 {
|
11
|
+
@return $overlaid;
|
12
|
+
}
|
13
|
+
|
14
|
+
$Colors: (
|
15
|
+
'red': red($foreground),
|
16
|
+
'green': green($foreground),
|
17
|
+
'blue': blue($foreground)
|
18
|
+
);
|
19
|
+
|
20
|
+
@each $color in map-keys($Colors) {
|
21
|
+
$fVal: call($color, $overlaid) * $alpha;
|
22
|
+
$bVal: call($color, $background);
|
23
|
+
|
24
|
+
$bVal: $bVal * $bAlpha * (1 - $alpha);
|
25
|
+
|
26
|
+
$cVal: $fVal + $bVal;
|
27
|
+
|
28
|
+
$Colors: map-merge($Colors, ($color: $cVal));
|
29
|
+
}
|
30
|
+
|
31
|
+
// @debug alpha($color);
|
32
|
+
|
33
|
+
$cAlpha: $alpha + alpha($background) * (1 - $alpha);
|
34
|
+
|
35
|
+
$Colors: map-merge($Colors, ('alpha': $cAlpha));
|
36
|
+
|
37
|
+
@return rgba(map-get($Colors, 'red'), map-get($Colors, 'green'), map-get($Colors, 'blue'), map-get($Colors, 'alpha'));
|
38
|
+
}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
$A11Y--Contrast-Sizes: (
|
2
|
+
'semitransparent': 'The background is semi-transparent, so the contrast ratio cannot be precise. Depending on what’s going to be underneath, it could be any of the following:',
|
3
|
+
'fail': 'Fails WCAG 2.0 :-(',
|
4
|
+
'aa-large': 'Passes AA for large text (above 18pt or bold above 14pt)',
|
5
|
+
'aa': 'Passes AA level for any size text and AAA for large text (above 18pt or bold above 14pt)',
|
6
|
+
'aaa': 'Passes AAA level for any size text'
|
7
|
+
);
|
8
|
+
|
9
|
+
$A11Y--Contrast-Output-Warnings: true !default;
|
10
|
+
|
11
|
+
$A11Y--Contrast-Levels: (
|
12
|
+
'fail': 0 3,
|
13
|
+
'aa-large': 3 4.5,
|
14
|
+
'aa': 4.5 7,
|
15
|
+
'aaa': 7 22
|
16
|
+
);
|
17
|
+
|
18
|
+
$A11Y--Contrast-Colors: (
|
19
|
+
'black': rgb(0, 0, 0),
|
20
|
+
'gray': rgb(127.5, 127.5, 127.5),
|
21
|
+
'white': rgb(255, 255, 255)
|
22
|
+
);
|
@@ -0,0 +1,67 @@
|
|
1
|
+
@import "contrast--settings";
|
2
|
+
@import "luminance";
|
3
|
+
@import "contrast--overlay";
|
4
|
+
@import "contrast--closest";
|
5
|
+
@import "contrast--find";
|
6
|
+
@import "contrast--output";
|
7
|
+
|
8
|
+
@function a11y-contrast($color, $background) {
|
9
|
+
$semi: false;
|
10
|
+
$results: ();
|
11
|
+
$return: true;
|
12
|
+
|
13
|
+
@if $A11Y--Contrast-Output-Warnings {
|
14
|
+
@debug 'Accessibility results for `' + $color + '` text on `' + $background + '` background';
|
15
|
+
}
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
@if apha($background) {
|
20
|
+
@if $A11Y--Contrast-Output-Warnings {
|
21
|
+
@warn map-get($A11Y--Contrast-Sizes, 'semitransparent');
|
22
|
+
}
|
23
|
+
|
24
|
+
$semi: true;
|
25
|
+
}
|
26
|
+
|
27
|
+
$contrast: a11y-ContrastFind($color, $background);
|
28
|
+
|
29
|
+
|
30
|
+
$results: a11y-ContrastOutput(map-get($contrast, 'ratio'));
|
31
|
+
@if $semi {
|
32
|
+
$min-output: a11y-ContrastOutput(map-get($contrast, 'min'));
|
33
|
+
$max-output: a11y-ContrastOutput(map-get($contrast, 'max'));
|
34
|
+
$holder: ();
|
35
|
+
|
36
|
+
|
37
|
+
$holder: append($holder, $min-output);
|
38
|
+
|
39
|
+
@if $results != $min-output {
|
40
|
+
$holder: append($holder, $results);
|
41
|
+
}
|
42
|
+
|
43
|
+
@if $max-output != $min-output and $max-output != results {
|
44
|
+
$holder: append($holder, $max-output);
|
45
|
+
}
|
46
|
+
|
47
|
+
$results: $holder;
|
48
|
+
}
|
49
|
+
|
50
|
+
@each $level in $results {
|
51
|
+
@if $level == 'fail' {
|
52
|
+
@if $A11Y--Contrast-Output-Warnings {
|
53
|
+
@error map-get($A11Y--Contrast-Sizes, $level);
|
54
|
+
$return: false;
|
55
|
+
}
|
56
|
+
|
57
|
+
}
|
58
|
+
@else {
|
59
|
+
@if $A11Y--Contrast-Output-Warnings {
|
60
|
+
@debug map-get($A11Y--Contrast-Sizes, $level);
|
61
|
+
}
|
62
|
+
|
63
|
+
}
|
64
|
+
}
|
65
|
+
|
66
|
+
@return $return;
|
67
|
+
}
|
@@ -0,0 +1,29 @@
|
|
1
|
+
//////////////////////////////
|
2
|
+
// Luminance
|
3
|
+
//
|
4
|
+
// From http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
|
5
|
+
//////////////////////////////
|
6
|
+
@function a11y-luminance($color) {
|
7
|
+
$colors: (
|
8
|
+
'red': red($color),
|
9
|
+
'green': green($color),
|
10
|
+
'blue': blue($color)
|
11
|
+
);
|
12
|
+
|
13
|
+
@each $name, $value in $colors {
|
14
|
+
$adjusted: 0;
|
15
|
+
$value: $value / 255;
|
16
|
+
|
17
|
+
@if $value < 0.03928 {
|
18
|
+
$value: $value / 12.92;
|
19
|
+
}
|
20
|
+
@else {
|
21
|
+
$value: ($value + .055) / 1.055;
|
22
|
+
$value: pow($value, 2.4);
|
23
|
+
}
|
24
|
+
|
25
|
+
$colors: map-merge($colors, ($name: $value));
|
26
|
+
}
|
27
|
+
|
28
|
+
@return (map-get($colors, 'red') * .2126) + (map-get($colors, 'green') * .7152) + (map-get($colors, 'blue') * .0722);
|
29
|
+
}
|
metadata
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sass-a11y
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sam Richard
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-09-25 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: sass
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.4'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.4'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: sassy-math
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.5'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.5'
|
41
|
+
description: Accessibility helpers for Sass
|
42
|
+
email:
|
43
|
+
- sam@snug.ug
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- README.md
|
49
|
+
- CHANGELOG.md
|
50
|
+
- lib/sass-a11y.rb
|
51
|
+
- stylesheets/_a11y.scss
|
52
|
+
- stylesheets/a11y/_colors.scss
|
53
|
+
- stylesheets/a11y/colors/_contrast--closest.scss
|
54
|
+
- stylesheets/a11y/colors/_contrast--find.scss
|
55
|
+
- stylesheets/a11y/colors/_contrast--output.scss
|
56
|
+
- stylesheets/a11y/colors/_contrast--overlay.scss
|
57
|
+
- stylesheets/a11y/colors/_contrast--settings.scss
|
58
|
+
- stylesheets/a11y/colors/_contrast.scss
|
59
|
+
- stylesheets/a11y/colors/_luminance.scss
|
60
|
+
homepage: https://github.com/Team-Sass/sass-a11y
|
61
|
+
licenses:
|
62
|
+
- MIT
|
63
|
+
metadata: {}
|
64
|
+
post_install_message:
|
65
|
+
rdoc_options: []
|
66
|
+
require_paths:
|
67
|
+
- lib
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - '>='
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
73
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 1.3.6
|
78
|
+
requirements: []
|
79
|
+
rubyforge_project: sass-a11y
|
80
|
+
rubygems_version: 2.0.14
|
81
|
+
signing_key:
|
82
|
+
specification_version: 4
|
83
|
+
summary: Function to assist in accessibility while developing.
|
84
|
+
test_files: []
|