Accessible CSS-only tab view

旧城冷巷雨未停 提交于 2021-02-04 06:31:47

问题


I'm working on a site that needs to (a) work without JavaScript and (b) be keyboard-accessible.

I have used the label target trick to build a tab view (https://css-tricks.com/functional-css-tabs-revisited/), but I've noticed that it relies on the label being clicked. I can't figure out how to make it work with the keyboard. Is this possible?

.tabs {
  background-color: #eee;
  min-height: 400px;
}

.tabs__list {
  border-bottom: 1px solid black;
  display: flex;
  flex-direction: row;
  list-style: none;
  margin: 0;
  padding: 0;
  position: relative;
}

.tabs__tab {
  padding: 0.5rem;
}

.tabs__content {
  display: none;
  left: 0;
  padding: 0.5rem;
  position: absolute;
  top: 100%;
}

.tabs__input {
  display: none;
}

.tabs__input+label {
  cursor: pointer;
}

.tabs__input:focus,
.tabs__input:hover {
  color: red;
}

.tabs__input:checked+label {
  color: red;
}

.tabs__input:checked~.tabs__content {
  display: block;
}
<div class="tabs">
  <ul class="tabs__list">
    <li class="tabs__tab">
      <input class="tabs__input" type="radio" id="tab-0" name="tab-group" checked>
      <label for="tab-0" class="tabs__label" tabindex="0" role="button">Tab 0</label>
      <div class="tabs__content">
        Tab 0 content
      </div>
    </li>
    <li class="tabs__tab">
      <input class="tabs__input" type="radio" id="tab-1" name="tab-group">
      <label for="tab-1" class="tabs__label" tabindex="0" role="button">Tab 1</label>
      <div class="tabs__content">
        Tab 1 content
      </div>
    </li>
  </ul>
</div>

回答1:


Accepted answer is not an accessible solution.

I have made some corrections and some observations here. Do not use the accepted answer in production if you stumble across this question in the future. It is an awful experience with a keyboard.

The answer below fixes some of the CSS issues to make it more accessible.

However I would recommend you reconsider the no JavaScript requirement.

I can understand having a good fall-back (which the example I give below with the fixes is) but there is no way you can make a fully accessible set of CSS only tabs.

Firstly you should use WAI-ARIA to complement your HTML to make things even more clear for screen readers. See the tabs examples on W3C to see what WAI-ARIA roles you should be using. This is NOT possible without JavaScript as states need to change (aria-hidden for example should change).

Secondly, you should be able to use certain shortcut keys. Press the home key for example in order to return to the first tab, something you can only do with a little JS help.

With that being said here are a few things I fixed with the accepted answer to at least give you a good starting point as your 'no JavaScript fallback'.

Problem 1 - tabindex on the label.

By adding this you are creating a focusable element that cannot be activated via keyboard (you cannot press space or Enter on the label to change selection, unless you use JavaScript).

In order to fix this I simply removed the tabindex from the labels.

Problem 2 - no focus indicators when navigating via keyboard.

In the example the tabs only work when you are focused on the radio buttons (which are hidden). However at this point there is no focus indicator as the styling is applying styling to the checkbox when it is focused and not to its label.

In order to fix this I adjusted the CSS with the following

/*make it so when the checkbox is focused we add a focus indicator to the label.*/
.tabs__input:focus + label {
  outline: 2px solid #333;
}

Problem 3 - using the same state for :hover and :focus states.

This is another bad practice that needs to go away, always have a different way of showing hover and focus states. Some screen reader and screen magnifier users will use their mouse to check they have the correct item focused and orientate themselves on a page. Without a separate hover state it is difficult to check you are hovered over a focused item.

/*use a different colour background on hover, you should not use the same styling for hover and focus states*/
.tabs__label:hover{
   background-color: #ccc;
}

Example

In the example I have added a hyperlink at the top so you can see where your focus indicator is when using a keyboard.

When your focus indicator is on one of the two tabs you can press the arrow keys to change tab (which is expected behaviour) and the focus indicator will adjust accordingly to make it clear which tab was selected.

.tabs {
  background-color: #eee;
  min-height: 400px;
}

.tabs__list {
  border-bottom: 1px solid black;
  display: flex;
  flex-direction: row;
  list-style: none;
  margin: 0;
  padding: 0;
  position: relative;
}

.tabs__tab {
  padding: 0.5rem;
}

.tabs__content {
  display: none;
  left: 0;
  padding: 0.5rem;
  position: absolute;
  top: 100%;
}

.tabs__input {
  position: fixed;
  top:-100px;
}

.tabs__input+label {
  cursor: pointer;
}


.tabs__label:hover{
   background-color: #ccc;
}

.tabs__input:focus + label {
  outline: 2px solid #333;
}

.tabs__input:checked+label {
  color: red;
}

.tabs__input:checked~.tabs__content {
  display: block;
}
<a href="#">A link so you can see where your focus indicator is</a>
<div class="tabs">
  <ul class="tabs__list">
    <li class="tabs__tab">
      <input class="tabs__input" type="radio" id="tab-0" name="tab-group" checked>
      <label for="tab-0" class="tabs__label" role="button">Tab 0</label>
      <div class="tabs__content">
        Tab 0 content
      </div>
    </li>
    <li class="tabs__tab">
      <input class="tabs__input" type="radio" id="tab-1" name="tab-group">
      <label for="tab-1" class="tabs__label" role="button">Tab 1</label>
      <div class="tabs__content">
        Tab 1 content
      </div>
    </li>
  </ul>
</div>



回答2:


It is just radio buttons... Keyboard can be used to navigate through them using tab and space bar to check them.

I'd use :focus to highlight the chosen tab and the tabindex property to make it work as I wanted.

Please provide more dept if you have problem with a SPECIFIC problem related to it, and provide a basic code example here, no linking.

Since hidden inputs cannot be selected through keyboard, make them visible...

.tabs {
  background-color: #eee;
  min-height: 400px;
}

.tabs__list {
  border-bottom: 1px solid black;
  display: flex;
  flex-direction: row;
  list-style: none;
  margin: 0;
  padding: 0;
  position: relative;
}

.tabs__tab {
  padding: 0.5rem;
}

.tabs__content {
  display: none;
  left: 0;
  padding: 0.5rem;
  position: absolute;
  top: 100%;
}

.tabs__input {
  position: fixed;
  top:-100px;
}

.tabs__input+label {
  cursor: pointer;
}

.tabs__input:focus
.tabs__input:hover {
  color: red;
}

.tabs__input:checked+label {
  color: red;
}

.tabs__input:checked~.tabs__content {
  display: block;
}
<div class="tabs">
  <ul class="tabs__list">
    <li class="tabs__tab">
      <input class="tabs__input" type="radio" id="tab-0" name="tab-group" checked>
      <label for="tab-0" class="tabs__label" tabindex="0" role="button">Tab 0</label>
      <div class="tabs__content">
        Tab 0 content
      </div>
    </li>
    <li class="tabs__tab">
      <input class="tabs__input" type="radio" id="tab-1" name="tab-group">
      <label for="tab-1" class="tabs__label" tabindex="0" role="button">Tab 1</label>
      <div class="tabs__content">
        Tab 1 content
      </div>
    </li>
  </ul>
</div>


来源:https://stackoverflow.com/questions/61205581/accessible-css-only-tab-view

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!