Issue:
There are some situations in which it would be valuable to be able to present a portion of link text visually, and a portion of link text invisibly (for screen-reader users, within the same link.
Two examples of this are providing invisible linked text to indicate which tab on a list of tabs is "selected" or which blog article you are going to "Read more" of.
Recommendation:
Allow l() to accept a parameter for additional invisible linked text and use the classes being defined in #473396: Defining System-Wide Approaches to Remove, Make Invisible & Push Content Off-screen with CSS to make this text visible to screen-readers only.
Example markup:
1. <a href="url">Edit<span class="visibility-invisible">selected</span></a>
2. <a href="url">Read more...<span class="visibility-invisible">about blog-post-name-here</span></a>
Resources:
C7: Using CSS to hide a portion of the link text (Techniques for WCAG 2.0) - http://www.w3.org/TR/2008/NOTE-WCAG20-TECHS-20081211/C7
#521852: Local tasks lack semantic markup to indicate an active task - related current issue.
#49428: Include node title in "Read more" link for better accessibility and SEO - somewhat related older issue.
| Comment | File | Size | Author |
|---|---|---|---|
| #22 | issue-526712-1.patch | 1.58 KB | Everett Zufelt |
| #15 | 526712-15-l-accessibility.patch | 1.56 KB | tic2000 |
Comments
Comment #1
Everett Zufelt commentedL() - http://api.drupal.org/api/function/l/7
Comment #2
mgiffordFits nicely in with this discussion from the groups - http://groups.drupal.org/node/17627
Now that we're very close on a means to push the content off-screen it will be good to start providing a mechanism to provide fuller more meaningful links that allow sites to become WCAG 2.0 compliant.
Comment #3
avpadernoIsn't enough to pass
array('html' => TRUE)as value for the parameter$options, to be able to use HTML in the text passed tol()?Try with
l("Read more...<span class="visibility-invisible">about blog-post-name-here</span>", $url, array('html' => TRUE)).Comment #4
Everett Zufelt commented@KiamLaLuno
Thanks for the question. I don't think that passing the link text with the
<span class="visibility-invisible">...</span>inline is enough.If we are aiming for a fully accessible d7 then changes need to be made to core to most easily facilitate core developers and module contributors to make their contributions accessible. The ability to pass "additional accessible text" asa a param to l() is far more likely to make this happen then to have developers add an additional html element within the link text, if for no other reason than that the method you have suggested will likely only be documented on the accessibility pages, where the method I am suggesting will be documented in the api reference for l().
Comment #5
avpadernoThe point is that there is already a way to do what you are suggesting to do using another option passed to
l(). I am not sure the additional option you are suggesting will be added.Comment #6
Everett Zufelt commented@KiamLaLuno
Thanks for the comment. I do see value in reducing the burden for developers by providing a parameter through which l() can insert this markup automatically. There are a great number of ways in which this added functionality may be implemented and it will be easier for developers, and more likely to be implemented, it it is handled through the one function call to generate the markup for the link.
Comment #7
webchickI tend to agree with Everett here.
But... is there a common word for what you're proposing we add here? "hidden link text" is not very semantic.
Comment #8
avpadernoDoes "Add options for semantic content to l()" sound better?
Comment #9
avpadernoRather than adding a further option to
l()why don't we add a set of new functions?if I want to make my page more semantic, it's more probable I will not need just
l(), which is suggested to not be used togethert()(the example in the documentation fort()suggests to useurl()). There are many occasions where I could need to output semantic HTML, including in a menu callback.Comment #10
Everett Zufelt commented@KiamLaLuno
l() actually calls url() to generate the URL. The API documentation for l() recommends that: "...all internal links output by modules
should be generated by this function if possible". Perhaps it is necessary to also add translation functionality to l(), but that should be a separate issue.
@webchick
I have renamed the issue and would recommend a parameter like $text-screenreader-supplemental or $text-screenreader-extra. The lengthy naming is to make it clear that 1. this text is for screenreaders and 2. that the text will be used to supplement, not replace, $text.
IMO It is not ideal to have to make special situations like this for screen-reader users, however, I feel that this is an exception as screen-reader users cannot perceive the visual groupings and styles that can add context to link text.
Clearly this change will require thorough documentation, which I am more than happy to contribute.
I also recommend that if $text-screenreader-extra is not empty that $html be implicitly set to true.
Comment #11
lilou commentedAdd tag.
Comment #12
annmcmeekin commentedSubscribe.
Comment #13
webchickEverett, something that could maybe help in determining the direction is describing a few use cases in core in which we would use this, and a few more in which we would NOT use this. I think that could help us nail the syntax down. Also, pointers to existing high-profile sites that already are adding similar text to their navigation elements would be super helpful for reference as well.
Like Kiam, I do get kind of an ooky feeling from overloading a function intended for outputting just links to instead output links along with weird "special" text (along with its own "special" markup) that Drupal will spit out at random places. In addition to this breaking our degradation in browsers that don't support CSS or have it shut off, I think it also may cause problems for themers that randomly some links have these phantom invisible spans next to them and others don't.
Are we totally breaking new ground here? Are there no best practices from how other CMSes/Frameworks/etc. are dealing with this requirement? Do link title attributes not fulfill this requirement? Those are at least part of the XHTML spec, and l() already supports them.
Comment #14
Everett Zufelt commented@webchick
I have no examples of other sites or CMSs that are doing this correctly, I will attempt to find some, but I would say that it is not unlikely that we are breaking new ground.
1. Many screen-readers must be specially configured to read the title attribute, and even if configured the title attribute can harm, not assist, in the understanding of link text, (see http://www.rnib.org.uk/wacblog/articles/too-much-accessibility/too-much-... ). Even though using the title attribute is a suggested technique of WCAG 2.0 (see http://www.w3.org/TR/2008/NOTE-WCAG20-TECHS-20081211/H33.html ), it fails because of poor implementation by browser and assistive technology vendors.
2. Many screen-reader users get their first impression of a page by navigating by links, 35% of respondents in the WebAIM screen-reader survey, (see http://webaim.org/projects/screenreadersurvey/ ).
3. The technique of using CSS to hide a portion of link text is one of the techniques offered as suggestions for the W3C WCAG 2.0 recommendation (see http://www.w3.org/TR/2008/NOTE-WCAG20-TECHS-20081211/C7 ). It is meant to help in satisfying success criterion 2.4.4 (http://www.w3.org/TR/2008/NOTE-UNDERSTANDING-WCAG20-20081211/navigation-...).
4. Several areas could use more descriptive link text, I imagine that themers would be happier with it being hidden than visible to all users, but I'm happy to be corrected about this. A few examples from drupal.org:
a. Links to user profile pages e.g. "Everett Zufelt". Where does this go? "Everett Zufelt's Profile" is more meaningful.
b.Links to expand and collapse fieldsets, like the "Tags" link / fieldset lower on this page.
c. "Read more..." about what?
d. Links that are tabs (and possibly active / selected)
e. "News and Announcements" appears as a link on the homepage 5 times, news about what?
5. A place where this is not necessary is when link text states clearly on its own what the function of the link is. For example, from http://drupal.org: "Modules", "Themes", and "Translations" as they are part of a list that comes under the heading (not marked up as a heading) "Contributions"; "", "Download Drupal 6.13", as it is clear that this link will take me to download Drupal 6.13.
Comment #15
tic2000 commentedIt needs work. Probably the span should be a theme function. The text surely needs improvement.
But is just a starting point to have something "tangible" to talk about.
Comment #16
Everett Zufelt commented@tic2000
Patch in #15 looks like a good start, thanks for rolling it.
A couple of questions that I have for rolling an improvement.
1. Will it make a difference for RTL languages which end of the $text that the accessible text goes on, it is currently going to the right of $text
2. @mikey_p suggested on IRC that there be an accessible-prefix and accessible-suffix. Would be interested to hear what people think of this idea, or if one accessible suffix is sufficient.
Comment #17
tic2000 commented@Everett Zufelt
Using suffix or prefix wouldn't help. When you write a l function inside a module you don't know if it will be used on a LTR or RTL site. A possible solution is to check for the global language direction and place the text accordingly.
Comment #18
mikey_p commented@tic2000: Why would prefix, suffix not work in RTL languages? Right now you have implemented a suffix, even though you haven't called it that.
Looking at this further, I think one of the biggest problems will be, that the entire string (with invisible and visible) will no longer be in context. If I setup a link in my module with separate strings for link, and accessible text, then those would be translated separately and may no longer make sense in context. Maybe some sort of replacement patterns similar to t would make sense.
Also, you should add this documentation to l() as well, since the options apply there as well.
BTW, can you roll your patches with -p option? It make it easier to read if one could tell which function is being patched.
Comment #19
Brigadier commentedIt has to be easy, when appropriate, to add extra descriptive text for screenreaders. It shouldn't be needed very often compared to the number of places links are used that have sufficient contextual information. The best example I know of is the state of tabs as Everett mentioned earlier. The state information is visually conveyed by highlighting one of several tabs using CSS. Adding hidden text to the name on the tab performs the same function for a screenreader (with a side-effect of showing it to any user without CSS).
I'm a little concerned about using hidden text for the cases in #14.4. As a sighted user, I'd like to be able to perceive all the information on a "Read More..." link. Similarly, it's quite possible for a themer to overuse this technique for differentiating link text presented to a screenreader when there's a more usable design that would work for any user agent.
If the extra option is added to the l() function then it's important to be clear about where it's meant to be used, referring to the WCAG best practices.
The patch in #15 looks okay but shouldn't $accessibility be passed through check_plain() too?
I'm also not a fan of the name "accessibility" for the text, it's specifically meant for screenreaders and it'll be rendered hidden with CSS. Maybe $hidden_after (possibly along with "$hidden_before" in line with the suggestion in #16.2).
Comment #20
bowersox commented+1 for the patch in #15
It is important to get this in core and to document the best practices. Without this change, it is hard for Drupal sites to meet accessibility standards. We end up killing kittens or using tricky overrides. This change would encourage the whole Drupal community to add accessibility text into a link in a consistent, clean way.
Regarding prefix and suffix, I believe we only need a suffix, although it does no harm to provide both. It is my understanding of RTL languages that the order of content in the HTML source code is always in the same order -- the order in which it will be read or spoken by the sighted user or the screenreader -- regardless of its arrangement on screen. So I think we only need a suffix.
A prime use case is the "Read More" links (#49428). I understand that not everyone will want to use this capability in every situation, but that's why we should provide a standard way to do it in core and document the best practices.
Comment #21
cliff@Brigadier, not to be snide, but as a sighted user, to perceive all information on the "Read more…" links being discussed, just glance at the
<h2>for that post.I hope all who are following this discussion are also aware of the recent posts in http://groups.drupal.org/node/17627, a related active discussion in http://groups.drupal.org/accessibility.
Just sayin'.
Comment #22
Everett Zufelt commentedBuilding on the patch in comment 15, this patch:
1. Defines text-screenreader-before and text-screenreader-after in the $options array.
2. if the options are not empty styles the text with
<span class="element-invisible"></span>.3. Checks to make sure the text is plain
4. Prepends / appends the invisible spans to the output link text.
Comment #23
mikey_p commentedOne problem I see with this approach is that (while I don't do much localization) I suppose it's rather bad form to concat translated strings together. Imagine the following examples from the node/add page:
(Text inside parenthesis is assumed to be invisible, but accessible text):
Link text: Page
Full text: (Create new) Page.
This example (verb-adjective-noun) works well in English, but may not work well languages with a verb-noun-adjective construct.
What I would propose, is a complete string be provided for the accessible text, with a placeholder similar to the t() function, for the link text. With that in mind, one might provide the following link text, and accessible text to the example above:
Link text: "Page"
Accessible text: "Create new %link_text"
Output:
<a href=""><span class="element-invisible">Create new </span>Page</a>Thoughts?
Comment #24
Everett Zufelt commented@mikey_p
I would like it if l() did perform translation, however, l() currently performs no translation at all. I tink translation improvements should be left for another issue.
I believe that the reason that l() does not perfrom translation is:
Comment #25
damien tournoud commentedI don't think this is necessary at all.
will work perfectly for that. The
<span>is part of the sentence, we have to keep it in the same string for translation purposes.The pattern itself is nice, and I would love to see this "additional information" added to a few links all around core.
Comment #26
tic2000 commentedAnd honestly is the only way so translations can work properly
Comment #27
Everett Zufelt commented@Damien Tournoud
I agree, accessibility is about making information accessible to the greatest number of people. Your proposed solution will ensure accessible links for screen-reader users, while preserving the ability to do correct translation.
I would be happy to set this issue to "By design" if someone can recommend a good place to document this methodology for ensuring accessible link text.
Comment #28
damien tournoud commented@Everett: what about using this issue to add 'supplemental text' to a few links of core?
For example, we could start with the "selected tab" issue, except if you have a better idea.
Comment #29
Everett Zufelt commented@Damien Tournoud
I have researched the approach required for #521852: Local tasks lack semantic markup to indicate an active task and have provided details in comment #2.
I still believe that the approach in comment #25 above needs to be documented somewhere for module and core developers.
Comment #30
mgiffordAbsolutely this should be documented better and encouraged more. Adding it here would help --> http://drupal.org/node/394094
Other than the read more links, which should probably be addressed on a theming level, are there priority modules where you'd like to see greater use of this hidden text?
There is a suggestion for use here
#510094: Add description to the link items of the toolbar
#49428: Include node title in "Read more" link for better accessibility and SEO
Comment #31
mgiffordI added some documentation to the link above, but should be brought into core D7 theme & module docs. Where are those?
Comment #32
Everett Zufelt commentedAs the steps for making elements (including text within an anchor, invisible to sighted users, but available to screen-readers is now documented at http://drupal.org/node/394094 I am setting this issue to by design.
Comment #33
liam morland