-1

I have some HTML that creates a form enriched with access keys, combined with a stylesheet that adds the accesskey attribute value after it.

It works nicely for labels, but it does not work for radio buttons, check boxes and submit buttons. Alternatively I have tried some scripting that produces the same effect (without causing any exception).

Can someone explain why it is like that, and more importantly how to fix that (easily)? The solution does not have to be CSS (while actually being preferred); it could be JavaScript, too (e.g. like https://stackoverflow.com/a/7035862/6607497 or https://stackoverflow.com/a/32293101/6607497).

Sketch of my form code (the actual form has many more elements, but those follow the same pattern):

[accesskey]:after {
    margin-left: 0.5em;
    content: "[" attr(accesskey) "]";
    font-family: monospace;
}
<!DOCTYPE html
 PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="de-DE" xml:lang="de-DE">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  </head>
  <body>
    <form method="post" action="..." enctype="multipart/form-data" class="sf">
      <fieldset class="sf-fset">
        <legend class="sf-legend" accesskey="s">Suchkriterien</legend>
        <table summary="Suchkriterien" class="sf">
          <tbody>
            <tr><td><label class="sf" for="srch-a-cn" accesskey="n">Name</label></td> <td><input type="text" name="srch-a-cn" size="30" maxlength="80" id="srch-a-cn" class="field" pattern=".*" /></td></tr>
            <tr><td></td> <td><label class="sf" for="srch-match-cn" /><label><input type="radio" name="srch-match-cn" value="E" checked="checked" id="srch-match-cn-E" accesskey="1"/>genau</label> <label><input type="radio" name="srch-match-cn" value="M" id="srch-match-cn-M" accesskey="2"/>ähnlich</label></td></tr>
          </tbody>
        </table>
      </fieldset>
      <p />
      <fieldset class="sf-fset"><legend class="sf-legend" accesskey="u">Suchmodus</legend>
        <table class="sf" summary="Suchmodus">
          <tbody>
            <tr>
              <td><label for="srch-mode" accesskey="m" class="sf-lab">Modus</label></td>
              <td><label><input type="radio" name="srch-mode" value="telephoneNumber" checked="checked" id="srch-mode-telephoneNumber" accesskey="t" title="telephoneNumber"/>Telefon</label>
                <label><input type="radio" name="srch-mode" value="pager" accesskey="f" title="pager" id="srch-mode-pager"/>Funk</label>
              </td>
            </tr>
          </tbody>
        </table>
      </fieldset>
      <p></p>
      <input type="submit" name=".submit" value="Suchen" accesskey="c" />
    </form>
  </body>
</html>

Here is a partial screenshot that shows how it looks (with some extra styling applied):

Partial screenshot of form

(Ignore the underlined character; that's from the script I tried to highlight the accesskey, too (and it fails in the same cases). The important thing is that the individual radio buttons don't show the accesskey)

U. Windl
  • 3,480
  • 26
  • 54
  • The issues is that self-closing tags cannot have children. This includes `::before` and `::after`. – Ouroborus Dec 15 '22 at 08:35
  • I don't quite get it: Does that mean that `:after` does *not* insert the content *after* the element, but *inside* it? I somewhat understand it for the submit button, but why won't it work for the `label`? The `accesskey`s work for all those elements. – U. Windl Dec 15 '22 at 10:30
  • Yes, that's correct, `:before` and `:after` add virtual children. Which label? Only one of them has `accesskey` set. – Ouroborus Dec 15 '22 at 10:48
  • The label wrapping "ähnlich" is malformed. The open tag is actually written to be self-closing, leaving a spurious closing tag, and is not actually wrapping anything. – Ouroborus Dec 15 '22 at 10:56
  • OK, I'll update the HTML with a more recent version. Meanwhile I noticed that Microsoft edge displays the accesskey hints for radio buttons, and even a `[accesskey] { background-color: gray }` does not affect submit buttons and radio buttons in Firefox. – U. Windl Dec 15 '22 at 13:02
  • I've updated the HTML code; now it has accesskeys for even the fieldsets. – U. Windl Dec 15 '22 at 13:29
  • Looks like it's working fine. All elements that can have children and have `accesskey` set are showing that css, just as they're supposed to. – Ouroborus Dec 15 '22 at 13:48
  • But the access keys for the radio button labels (e.g.: `1` and `2`) are not visible, just as the access key for the "Suchen" button isn't shown. – U. Windl Dec 15 '22 at 15:00
  • As was mentioned before, those are written as self-closing and so can't have children. Therefor, `:before` and `:after` doesn't work with them. – Ouroborus Dec 16 '22 at 02:40
  • I understand, but going back to the question: *How to fix it?* The labels for the radio buttons seem easy, while the submit button is probably a bit trickier. – U. Windl Dec 16 '22 at 09:00
  • You can add the text manually to the inputs' values. You won't be able to add the text to the inputs themselves via CSS. (Also, [MDN's docs for `accesskey`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/accesskey#accessibility_concerns) recommend not using it, saying "it is generally advised not to use `accesskey`s for most general-purpose websites and web apps.") – Ouroborus Dec 16 '22 at 09:40

1 Answers1

0

This answer is not complete yet, but due to lack of anything better, I'm summarizing what I found out:

Radio Buttons (<input type="radio">, CGI::radio_group())

It seems to be a "feature" of CGI.pm from perl 5.18.2 to create two nested label elements for a radio_group:

  • The outer label covers the whole button group (all buttons in the group)
  • The inner label covers the actual input element and the text label, and it is repeated for every button in the group.

Unfortunately any accesskey attribute as passed via -attributes is attached to the input element. Playing with Firefox' Inspector, I found out that accesskey is displayed properly if the attribute is attached to the inner label instead.

However I found no way to do that with CGI.pm.

Submit Button (<input type="submit">)

Also with experimenting I found out that I can wrap the submit button in a label "for" the ID of the submit button, also moving the accesskey from the input element to the label element. So the accesskey is being displayed and it still triggers the submit button.

Solution

This is the HTML after JavaScript mangling (I copied the code from the browser as snippets won't allow DOM modifications it seems). Styling may be overly complicated, I know.

body { color: #000000; background-color: #ffffff }
label { font-family: sans-serif; font-weight: bolder }
legend { font-family: sans-serif; font-size: medium; font-weight: bolder }
.legend { font-family: sans-serif }

/* generic tables */
table { background-color: #ffffff; color: #000000; margin-top: 1ex; margin-bottom: 1ex }
td { padding-left: 1mm; padding-right: 1mm }

/* search form */
.sf { }
.sf-fset { }
.sf-legend { font-size: medium; font-family: sans-serif }
.sf-lab { font-family: sans-serif; font-weight: bolder }
.sf-lab2 { font-family: sans-serif; font-weight: bolder; font-size: small }

input.field { background-color: #fefee1 }
input:required { border-color: #9b1415 }
input:invalid { background-color: #fdc7c7 }
input:valid { border-color: #8bd88b }

/* generic styling */
div.vsp { height: 1em }
div.vsp[name="vsp-big"] { height: 1.5em }

@media screen {
    span.ak { /* accesskey (key) */
        text-decoration: underline;
    }
    span.akw { /* accesskey wrapper (includes span.ak) */
        margin-left: 0.5em;
        font-weight: normal; color: #228924
    }
    span.akw span.ak { /* accesskey (key) */
        font-family: monospace; font-weight: bold
    }
}
<!DOCTYPE html
    PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="de-DE" xml:lang="de-DE">
  <head>
    <title>...</title>
    <link rev="made" href="mailto:me" />
  </head>
  <body>
    <script type="text/javascript">fix_CSS()</script>
    <form method="post" action="/query/2" enctype="multipart/form-data" class="sf">
      <fieldset class="sf-fset"><legend accesskey="s" data-i="0" class="sf-legend"><span class="ak">S</span>uchkriterien</legend>
      <table class="sf" summary="Suchkriterien">
        <tbody>
          <tr>
            <td><label data-i="0" class="sf" for="srch-a-cn" accesskey="n"><span class="ak">N</span>ame</label></td>
            <td><input type="text" name="srch-a-cn"  size="30" maxlength="80" pattern=".*" class="field" placeholder="Name" id="srch-a-cn" /></td>
          </tr>
          <tr>
            <td></td>
            <td><label class="sf" for="srch-match-cn" /><label><input type="radio" name="srch-match-cn" value="E" checked="checked"  data-i="-1" id="srch-match-cn-E" accesskey="1"/>genau<span class="akw">[<span class="ak">1</span>]</span></label> <label><input type="radio" name="srch-match-cn" value="M"  id="srch-match-cn-M" accesskey="2" data-i="-1"/>ähnlich<span class="akw">[<span class="ak">2</span>]</span></label></td>
          </tr>
      </tbody></table>
  </fieldset>
  <div class="vsp"></div>
  <fieldset class="sf-fset"><legend class="sf-legend" data-i="1" accesskey="u">S<span class="ak">u</span>chmodus</legend>
  <table summary="Suchmodus" class="sf">
  <tbody>
    <tr>
      <td><label class="sf-lab" data-i="1" for="srch-mode" accesskey="o">M<span class="ak">o</span>dus</label></td>
      <td><label><input type="radio" name="srch-mode" value="telephoneNumber" checked="checked"  accesskey="t" title="telephoneNumber" id="srch-mode-telephoneNumber" data-i="0"/><span class="ak">T</span>elefon</label> <label><input type="radio" name="srch-mode" value="pager"  title="pager" id="srch-mode-pager" accesskey="f" data-i="0"/><span class="ak">F</span>unk</label></td>
    </tr>
  </tbody></table>
  </fieldset>
  <div name="vsp-big" class="vsp"></div>
  <label data-i="2" class="sf-lab" for="submit" accesskey="c"><input type="submit" name=".submit" value="Suchen" id="submit"><span class="akw">[<span class="ak">c</span>]</span></label>
</form>
</body>
</html>

I deliberately chose digits for the upper radio group as I wanted to preserver some letters and the same label will repeat a few times. Also the form shown is reduced (other elements with an accesskey were omitted), so the choice of accesskeys may seem a bit odd without seeing the other elements.

U. Windl
  • 3,480
  • 26
  • 54