Previous Comments
In Organizing Information Accessibly, I spoke briefly about labelling strings. Semantically associating a <label> with text via the for property is sadly not included in any HTML specification, so my advice basically amounted to relying on DOM proximity or using a <table>.
I didn't find that particularly satisfactory at the time, but after digging around others' blog posts and trawling forms for a while I was not able to find a better answer. Oddly, this issue is rather hard to find discussion about, and I found myself second-guessing my need for doing this in the first place. Surely I'm not the only one who wants to display read-only key/value string pairings, right?
Regardless, without an answer I was forced to write what I had so I could move on with my life. Life, as it turned out, wasn't done bugging me about this though.
It Keeps Coming Up
Just a few days ago, my officemate at work spun his chair around to pick my brain about something he was working on. I'd been listening to the faint sound of JAWS through his headphones over the preceding hour, so I was looking forward to discussing some accessibility consideration until I realized he was running into the very thing which had left me stumped way back in September: he needed to label some strings.
After inspecting his control for a minute, I had to give him the disappointing news that basic text <span>s couldn't really be given an accessible name separate from their content, and that <label>s wouldn't have effect. This was especially troubling since the label was meant to apply to multiple fragments of text which were only visually associated with it; they were nowhere close in the DOM, and couldn't be converted to a <table> or brought closer without a complete redesign.
So, I got to watch the disgust on his face as I explained that his best option was probably to add a clear label to each text fragment so that the association could be established. It meant duplicating the contents of the label across all of the fragments intended to be labelled, but fortunately this label is meant to be static and probably won't fall out of date with the clear labels.
I shared his disgust, and its taste stuck with me into that evening through to the next morning. I woke up an hour before I needed to actually rise and sleepily dug through the internet on my phone once again looking for a better solution as my cat purred on my lap. It was about the time I was futilely trying to come up with reasons why disabled fields might not be that bad for this after all when I came across an odd passage on the ARIA Authoring Practices Guide:
In some cases, the most effective name for an element is its own content combined with the content of another element. Because aria-labelledby has highest precedence in name calculation, in those situations, it is possible to use aria-labelledby to reference both the element itself and the other element.
And that's when a lightbulb went off.
A New Idea
The cited example includes an anchor element which is labelled both by itself and a heading, which, if the link were just text, would be exactly what we would want: a single text element which has both a value and an accessible name. Unfortunately, being able to apply an accessible name to the anchor element is contingent on it having a role, in this case "link", so the href is required.
While testing this though, I noticed that if the href-less anchor element also had no content, it could be given an accessible name via aria-labelledby. This is really convenient, since an <a> won't visually display without inner text, so it's automatically hidden. As such, it can be easily snuck inside a <span> with a text value to reference a <label> elsewhere on the page without duplicating its content!
This <a> could just as easily be a <span>, but I kind of like using an anchor element here since we're "linking" to another element on the page. I went ahead and set aria-hidden on the <label> since it's now effectively duplicitive with its referrer inside the labelled text.
I've also deliberately kept the <a> and the #text within the same <span> so that they are read together in a single virtual cursor stop.
The Problem
After I posted this originally, Curtis Wilcox was kind enough to point out that this approach does not work very well using VoiceOver, where the href-less anchor element was not only a separate virtual cursor stop from the #text, it also had an inferred role of group.
That isn't great, but the behavior is worse using both Firefox and TalkBack, where the anchor element is entirely ignored, which completely defeats what I'm trying to do here. So, unfortunately, I'm left to yearm for official support of adding an accessible name to elements with a generic role.
Alternatives
The scenario for which this came up recently, where the #label fragments and their associated <label> are separated in the DOM, is usually avoidable, fortunately. The clear label approach I mentioned should work well enough in this exception case.
Curtis also brought up the description list, which is a good tool for semantically associating text elements with each other in some cases. Regrettably, its user-agent support is a little lacking in my opinion; description lists tend to be read very similarly to unordered lists, which is especially poorly suited to a single key/value pair. I did play around with adding the definition and term roles to <a>s, <span>s, and <label>s in various permutations, but the results were no better than my original idea.
Another thing Curtis mentioned was using ::before and ::after pseudo-elements to augment user-agent interperitation of semantic HTML, as outlined in a blog post by Steve Faulkner. It sadly doesn't really help us here more than clear labels, but it's a cool enough concept that I wanted to include it anyway.
Conclusion
So, after much ado, we're sadly back to where we started. I suppose the lessons here are to keep in mind these sorts of limitations early on when designing a project so that you don't end up painted into a corner of remedial solutions, to only fall back on ARIA if you really have to, and to always verify (don't even trust but verify) cross-browser and user-agent support of accessibilty features.