【问题标题】:Angular material radio button label and VoiceOver/ScreenReaderAngular 材质单选按钮标签和 VoiceOver/ScreenReader
【发布时间】:2023-03-16 08:27:01
【问题描述】:

我有一个 Angular Material mat-radio-group。当我使用 Apple 的 VoiceOver 对其进行测试时,它会将每个单选标签读取为“[标签] 和另一个项目”

例如,

<mat-radio-button value="envelope">Envelope</mat-radio-button>

在聚焦时被大声读出为“信封和另外一项”。为什么?

这是整套:

<mat-radio-group aria-label="My Package Type" [(ngModel)]="myPackageType" class="radio-package-type mat-radio-small">
   <mat-radio-button value="box">Box</mat-radio-button>
   <mat-radio-button value="envelope">Envelope</mat-radio-button>
   <mat-radio-button value="irregular">Irregular</mat-radio-button>
</mat-radio-group>

这是从开发工具复制的渲染 HTML:

<mat-radio-group
  _ngcontent-gkg-c241=""
  role="radiogroup"
  aria-label="My Package Type"
  class="mat-radio-group radio-package-type mat-radio-small ng-pristine ng-valid is-value ng-touched"
  ng-reflect-model="box"
  ><mat-radio-button
    _ngcontent-gkg-c241=""
    value="box"
    class="mat-radio-button mat-accent mat-radio-checked"
    ng-reflect-value="box"
    tabindex="-1"
    id="mat-radio-2"
    ><label class="mat-radio-label" for="mat-radio-2-input"
      ><div class="mat-radio-container">
        <div class="mat-radio-outer-circle"></div>
        <div class="mat-radio-inner-circle"></div>
        <input
          type="radio"
          class="mat-radio-input cdk-visually-hidden"
          id="mat-radio-2-input"
          tabindex="0"
          name="mat-radio-group-0"
          value="box"
        />
        <div
          mat-ripple=""
          class="mat-ripple mat-radio-ripple mat-focus-indicator"
          ng-reflect-trigger="[object HTMLLabelElement]"
          ng-reflect-disabled="false"
          ng-reflect-centered="true"
          ng-reflect-radius="20"
          ng-reflect-animation="[object Object]"
        >
          <div class="mat-ripple-element mat-radio-persistent-ripple"></div>
        </div>
      </div>
      <div class="mat-radio-label-content">
        <span style="display: none;">&nbsp;</span>Box
      </div></label
    ></mat-radio-button
  ><mat-radio-button
    _ngcontent-gkg-c241=""
    value="envelope"
    class="mat-radio-button mat-accent"
    ng-reflect-value="envelope"
    tabindex="-1"
    id="mat-radio-3"
    ><label class="mat-radio-label" for="mat-radio-3-input"
      ><div class="mat-radio-container">
        <div class="mat-radio-outer-circle"></div>
        <div class="mat-radio-inner-circle"></div>
        <input
          type="radio"
          class="mat-radio-input cdk-visually-hidden"
          id="mat-radio-3-input"
          tabindex="0"
          name="mat-radio-group-0"
          value="envelope"
        />
        <div
          mat-ripple=""
          class="mat-ripple mat-radio-ripple mat-focus-indicator"
          ng-reflect-trigger="[object HTMLLabelElement]"
          ng-reflect-disabled="false"
          ng-reflect-centered="true"
          ng-reflect-radius="20"
          ng-reflect-animation="[object Object]"
        >
          <div class="mat-ripple-element mat-radio-persistent-ripple"></div>
        </div>
      </div>
      <div class="mat-radio-label-content">
        <span style="display: none;">&nbsp;</span>Envelope
      </div></label
    ></mat-radio-button
  ><mat-radio-button
    _ngcontent-gkg-c241=""
    value="irregular"
    class="mat-radio-button mat-accent"
    ng-reflect-value="irregular"
    tabindex="-1"
    id="mat-radio-4"
    ><label class="mat-radio-label" for="mat-radio-4-input"
      ><div class="mat-radio-container">
        <div class="mat-radio-outer-circle"></div>
        <div class="mat-radio-inner-circle"></div>
        <input
          type="radio"
          class="mat-radio-input cdk-visually-hidden"
          id="mat-radio-4-input"
          tabindex="0"
          name="mat-radio-group-0"
          value="irregular"
        />
        <div
          mat-ripple=""
          class="mat-ripple mat-radio-ripple mat-focus-indicator"
          ng-reflect-trigger="[object HTMLLabelElement]"
          ng-reflect-disabled="false"
          ng-reflect-centered="true"
          ng-reflect-radius="20"
          ng-reflect-animation="[object Object]"
        >
          <div class="mat-ripple-element mat-radio-persistent-ripple"></div>
        </div>
      </div>
      <div class="mat-radio-label-content">
        <span style="display: none;">&nbsp;</span>Irregular
      </div></label
    ></mat-radio-button
  ></mat-radio-group
>

【问题讨论】:

  • 您能否将输出的 HTML 粘贴到您的问题中,在您的问题中看起来不错,但我怀疑生成的标记不太正确或添加了导致此行为的其他项目。
  • 添加到问题中
  • 很难从它创建的混乱 HTML 中分辨出来,但我注意到标签包裹着所有东西,但也与 for="mat-radio-3-input" 相关联,这可能会导致奇怪的行为。此外,因为标签包裹在所有东西上,原因很可能是“涟漪”,但我需要看看它是如何根据焦点、检查等变化的。很抱歉很痛苦,但你有可能把它变成小提琴,所以我可以检查一些东西,稍微摆弄一下,然后返回的不仅仅是有根据的猜测。

标签: angular accessibility angular-material2 voiceover


【解决方案1】:

我遇到过类似问题(macOS 10.15.3、Safari 13.0.5 和 10.15.4、13.1,我无法在 Mac Chrome 80 或 iOS 13.3.1 Safari 中重现)。当&lt;label&gt; 具有带有 display:block 的子元素时,似乎会发生这种情况,特别是如果混合有带和不带 display: 块的子元素或 TextNodes 和带有 display:block 的元素的混合。

在您的情况下,标签既是隐式的(输入是标签的子级)又是显式的(标签具有引用输入 id 的属性)。虽然这是不必要的重复(就像将 tagindex="0" 添加到 &lt;input&gt; 元素一样),但它与问题无关。我已经用仅隐式和仅显式标签和输入重现了该问题。重现问题似乎需要两件事:

  1. &lt;label&gt;改为display:block
  2. &lt;label&gt; 至少有一个 display:block 子元素,但不是所有带有 display:block 的子元素

更改标签元素以便不满足这两个要求之一似乎可以解决它。

<!-- VoiceOver is saying "First Nameandone more item, edit text" -->
<!-- implicit -->
<label style="display:block"> 
    <span style="display:block">First Name</span>
    <input type="text"> 
</label>

<!-- explicit -->
<div>
    <label for="firstname3" class="block"> 
        First Name
        <span style="display:block">Test</span>
    </label>
    <input id="firstname3" type="text">
</div>

【讨论】:

  • 代码 sn-ps 用于演示 Mac Safari 中的问题,没有原始问题中示例的所有复杂性。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-27
  • 2020-11-20
  • 2021-10-07
  • 2017-07-01
  • 2015-08-28
  • 1970-01-01
相关资源
最近更新 更多