-
Notifications
You must be signed in to change notification settings - Fork 3.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Core Css class for visually invisible but screen-reader accessible elements #5542
Conversation
* changing width from 1 to 0 would prevent TalkBack from activating (clicking) | ||
* buttons despite TalkBack reading them just fine. | ||
*/ | ||
.amp-screen-reader { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.-amp-screen-reader
We dont want to make this overridable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we will be doing most of the a11y for things with interactions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although I don't want it to be overridable, I do want page authors to use it in their own markup to fix a11y issues in their page. For now renamed to -amp
but this is something we should expose as part of the core kick-start Css.
* buttons despite TalkBack reading them just fine. | ||
*/ | ||
.amp-screen-reader { | ||
position: fixed !important; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure if more of these elements would make fixed layer operations slow. May be we should just whitelist from fixed layer somehow.
CC @dvoytenko
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed elements in our runtime css are not added to fixed layer by default. This should never make it to fixed layer, not because of performance but because fixed layer breaks DOM hierarchy which breaks accessibility.
border: none !important; | ||
margin: 0 !important; | ||
padding: 0 !important; | ||
display: block !important; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does this matter? once you set positioning-absolute/static i think you dont have to set this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am setting display:block !important
to ensure when this class is used in combination with other classes/styles on an element, the display is never set to none
(which would defeat the purpose of this class all together). Will add some comments to the code to clarify.
* changing width from 1 to 0 would prevent TalkBack from activating (clicking) | ||
* buttons despite TalkBack reading them just fine. | ||
*/ | ||
.amp-screen-reader { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than doing this in the css i would create a method in dom.js that would add this div and this would make it explicit when being called from inside the extension's build callback.
@dvoytenko what do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is not always a div
( actually most cases it would be a button
or a p
) and it is not always a new element that is created in a component, sometimes we want to toggle this class on an existing node (for example to fix #5487 we could just add this to the next/previous buttons when hiding them).
We can add dom.js
utilities but we should keep this in Css (another reason to keep it in Css is that we want to expose this to page authors as part of the kick-start core Css)
@jridgewell Please review the |
@@ -44,7 +44,11 @@ describe('amp-fx-flying-carpet', () => { | |||
iframe = i; | |||
toggleExperiment(iframe.win, 'amp-fx-flying-carpet', true); | |||
|
|||
iframe.doc.body.style.height = '400vh'; | |||
const bodyResizer = iframe.doc.createElement('div'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
different way of sizing the body's height. We now install the runtime Css when creating the test iframe and therefore iframe.doc.body.style.height = '400vh' was not being applied because of !important! rules coming from runtime Css was overriding it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, ok.
@@ -99,7 +99,19 @@ export class AmpSidebar extends AMP.BaseElement { | |||
this.close_(); | |||
} | |||
}); | |||
//TODO (skrish, #2712) Add history support on back button. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't delete this todo.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's done though...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whooops.
screenReaderCloseButton.addEventListener('click', () => { | ||
this.close_(); | ||
}); | ||
this.element.appendChild(screenReaderCloseButton); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this element going to be removed eventually?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nope, will always be there.
screenReaderCloseButton.textContent = 'Close the sidebar'; | ||
screenReaderCloseButton.classList.add('-amp-screen-reader'); | ||
// This is for screen-readers only, should not get a tab stop. | ||
screenReaderCloseButton.tabIndex = -1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be better to create a screenReaderElement
function that does this stuff for you?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
generic one doesn't make sense cause these elements could be buttons, paragraphs, links, etc.. depending on the use-case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yah, but we can pass the element to make. Essentially, if we always want .-amp-screen-reader
and tabIndex = -1
, it'd be helpful because we're gonna forget the tabIndex
.
function createScreenReaderElement(tag) {
const elem = doc.create(tag);
// ... psuedocode...
return elem;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I thought this was being added on open.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about
/**
* Visually hides an element but keeps it accessible to screen readers.
* If opt_visibleOnlyForScreenReaders is false or element was already only
* visible to screen-readers, it removes the screen-reader specific styling
* from the element.
* @param {boolean=} opt_visibleOnlyForScreenReaders
*/
export function toggleScreenReaderVisibility(element, opt_visibleOnlyForScreenReaders) {
if (opt_visibleOnlyForScreenReaders === undefined) {
opt_visibleOnlyForScreenReaders = !(element.classList.contains('-amp-screen-reader'));
}
element.classList.toggle('-amp-screen-reader');
//TODO have to check whether default is '' or null or undefined
element.tabIndex = opt_visibleOnlyForScreenReaders ? -1 : '';
}
in style.js
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We would need to hide hide these when they aren't visible. But I like the idea.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no, I don't want this to be used to hide hide things. There are cases where you want to apply ''-amp-screen-reader" to an existing visible node and then remove ''-amp-screen-reader" later to make the node visible again for everyone. Let's do the refactoring later when we have more uses of this, I think refactoring this right now might be premature.
@mkhatib @camelburrito @jridgewell PTAL, I like to merge this to unblock #5487 and #5503. Thanks! |
@@ -121,11 +121,44 @@ i-amp-sizer { | |||
} | |||
|
|||
.-amp-replaced-content { | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔪
This PR introduced a new core Css class
amp-screen-reader
that can be used by us or page authors to visually hide elements but keep them accessible to screen-readers.We use this new class in sidebar to fix #5517.
Also as part of this PR, we are now installing core styles in the testing iframe so that we can use computedStyles to ensure proper Css is being applied.
/cc @camelburrito @dvoytenko