Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
298 views
in Technique[技术] by (71.8m points)

accessibility - Accessible CSS-only tab view

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>
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...