skip to Main Content

So I have a div where the image is shown by default, and the list is hidden. But clicking the button shows the list and hides the image. There will be a grid of these item divs.

<div class="item">
  <div class="item__content">
    <img src="..." alt="<Relevant text>" id="image">
    <ul class="hidden" id="list">
      <li>Detail 1</li>
      <li>Detail 2</li>
      <li>Detail 3</li>
      <li>Detail 4</li>
    </ul>
  </div>
  <div class="item__heading">
    <div class="item__heading__text">
      <h3>Item name</h3>
      <h4>Item brand</h4>
    </div>
    <button onclick="toggleContent()" aria-controls="image list">Details</button>
  </div>
</div>

And currently I just have a CSS class like

.hidden {
   display: none;
}

and a JS function

function toggleContent() {
  const image = document.getElementById("image");
  const list = document.getElementById("list");
  image.classList.toggle("hidden");
  list.classList.toggle("hidden");
}

Is there a better way to approach this? I’m unsure about the method of hiding things, and also if there is any need for aria-hidden?

I should probably note that the alt text of the image is important, as the image displays information that users would otherwise not be able to decude.

The two states should look something likeenter image description here

2

Answers


  1. Chosen as BEST ANSWER
    <div class="item">
        <div class="item__content">
          <img src="..." alt="..." id="image">
          <ul class="hidden" id="list">
            <li>Detail 1</li>
            <li>Detail 2</li>
            <li>Detail 3</li>
            <li>Detail 4</li>
          </ul>
        </div>
        <div class="item__heading">
          <div class="item__heading__text">
            <h3>Item name</h3>
            <h4>Item brand</h4>
          </div>
          <button onclick="toggleContent()" aria-controls="list">Details</button>
        </div>
      </div>
    
    .sr-only {
        border: 0 !important;
        clip: rect(1px 1px 1px 1px);
        clip-path: polygon(0px 0px, 0px 0px,0px 0px, 0px 0px);
        -webkit-clip-path: polygon(0px 0px, 0px 0px,0px 0px, 0px 0px);
        height: 1px;
        margin: -1px;
        overflow: hidden !important;
        padding: 0;
        position: absolute;
        width: 1px;
        word-wrap: normal !important;
    }
    
    ul {
      display: flex;
      flex-direction: column;
    }
    
    .hidden {
      display: none;
    }
    
    function toggleContent() {
      const image = document.getElementById("image");
      const list = document.getElementById("list");
      image.classList.toggle("sr-only");
      list.classList.toggle("hidden");
    }
    

    Perhaps this makes sense? As mentioned in the comments, this way the list is the only thing really being toggled for screenreader users?


  2. To solve the problem using only HTML and CSS, you can utilize the :checked pseudo-class along with the adjacent sibling selector + to toggle the visibility of the image and list. Here’s an example:

    .hidden {
      display: none;
    }
    
    #toggle:checked + .item__content #image {
      display: none;
    }
    
    #toggle:checked + .item__content #list {
      display: block;
    }
    <div class="item">
      <input type="checkbox" id="toggle" class="hidden">
      <div class="item__content">
      <img src="https://fastly.picsum.photos/id/656/200/300.jpg?hmac=zNqhDDzELUTnZCZ7v7jsgm_qu5rVv4qCgahu6YqfG_A" alt="<Relevant text>" id="image">
        <ul class="hidden" id="list">
          <li>Detail 1</li>
          <li>Detail 2</li>
          <li>Detail 3</li>
          <li>Detail 4</li>
        </ul>
      </div>
      <div class="item__heading">
        <div class="item__heading__text">
          <h3>Item name</h3>
          <h4>Item brand</h4>
        </div>
        <label for="toggle">click</label>
      </div>
    </div>

    In this updated code, the JavaScript function is replaced with an element of type checkbox with the hidden class. The label with for="toggle" is used as a clickable element to toggle the checkbox state.

    The CSS uses the :checked pseudo-class along with the adjacent sibling selector + to select the appropriate elements based on the checkbox state. When the checkbox is checked, it will target the adjacent .item__content #image to hide it, and target the adjacent .item__content #list to display it.

    This way, clicking the "edit" label will toggle the visibility of the image and list without the need for JavaScript.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search