【问题标题】:Collapsible section with WAI-ARIA: additional "hide" button?带有 WAI-ARIA 的可折叠部分:附加“隐藏”按钮?
【发布时间】:2020-10-12 02:23:06
【问题描述】:

我正在使用 this code snippet(解释为 here)使用 WAI-ARIA 创建可折叠部分。我的可折叠文本很长,所以我想在文本底部添加一个额外的“隐藏”按钮,这样读者就不必向上滚动点击原始按钮来折叠该部分。我不太明白如何让这样的按钮工作。非常感谢您的帮助。

HTML:

<main> 
  <h3>Section 1</h3>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque commodo purus quis mi cursus hendrerit eu eu metus. Aliquam aliquam arcu eget aliquet scelerisque. Pellentesque sodales turpis vitae venenatis vehicula.</p> 
    <p>Ut id porta velit. Ut eu dignissim dui, quis gravida est. Cras quis venenatis mauris, a bibendum enim. Sed at augue libero. Nullam tortor metus, tincidunt ut urna id, posuere placerat orci. Ut quis risus dictum risus facilisis imperdiet quis sed eros.</p>
  <h3>Section 2</h3>
    <p>Nullam tortor metus, tincidunt ut urna id, posuere placerat orci.</p> 
    <p>Ut quis risus dictum risus facilisis imperdiet quis sed eros. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p> 
    <p>Quisque commodo purus quis mi cursus hendrerit eu eu metus. Aliquam aliquam arcu eget aliquet scelerisque. Pellentesque sodales turpis vitae venenatis vehicula. Ut id porta velit. Ut eu dignissim dui, quis gravida est. Cras quis venenatis mauris, a bibendum enim. Sed at augue libero.</p>
</main>

CSS:

body {
  max-width: 40rem;
  margin: 0 auto;
  padding: 1em;
}

main {
  border-width: 2px 0;
  border-style: solid;
}

main h2 {
  margin: 0;
}

main > div + h2 {
  border-top: 2px solid;
}

h2 button {
  all: inherit;
  border: 0;
  display: flex;
  justify-content: space-between;
  width: 100%;
  padding: 0.5em 0;
}   
    
h2 button:focus svg {
  outline: 2px solid;
}

button svg {
  height: 1em;
  margin-left: 0.5em;
}

[aria-expanded="true"] .vert {
  display: none;
}

[aria-expanded] rect {
  fill: currentColor;
}

/* page styles */

html {
  font-family: Arial, sans-serif;
}

* {
  box-sizing: border-box;
}

JavaScript:

 (function() {
  // Get all the <h2> headings
  const headings = document.querySelectorAll('main h2')
  
  Array.prototype.forEach.call(headings, heading => {
    // Give each <h2> a toggle button child
    // with the SVG plus/minus icon
    heading.innerHTML = `
      <button aria-expanded="false">
        ${heading.textContent}
        <svg aria-hidden="true" focusable="false" viewBox="0 0 10 10">
          <rect class="vert" height="8" width="2" y="1" x="4"/>
          <rect height="2" width="8" y="4" x="1"/>
        </svg>
      </button>
    `
    
    // Function to create a node list 
    // of the content between this <h2> and the next
    const getContent = (elem) => {
      let elems = []
      while (elem.nextElementSibling && elem.nextElementSibling.tagName !== 'H2') {
        elems.push(elem.nextElementSibling)
        elem = elem.nextElementSibling
      }
      
      // Delete the old versions of the content nodes
      elems.forEach((node) => {
        node.parentNode.removeChild(node)
      })

      return elems
    }
    
    // Assign the contents to be expanded/collapsed (array)
    let contents = getContent(heading)
    
    // Create a wrapper element for `contents` and hide it
    let wrapper = document.createElement('div')
    wrapper.hidden = true
    
    // Add each element of `contents` to `wrapper`
    contents.forEach(node => {
      wrapper.appendChild(node)
    })
    
    // Add the wrapped content back into the DOM 
    // after the heading
    heading.parentNode.insertBefore(wrapper, heading.nextElementSibling)
    
    // Assign the button
    let btn = heading.querySelector('button')
    
    btn.onclick = () => {
      // Cast the state as a boolean
      let expanded = btn.getAttribute('aria-expanded') === 'true' || false
      
      // Switch the state
      btn.setAttribute('aria-expanded', !expanded)
      // Switch the content's visibility
      wrapper.hidden = expanded    
    }
  })
})()

【问题讨论】:

    标签: javascript html wai-aria


    【解决方案1】:

    如何将它们粘在上面,这样你就可以随时折叠。

    这是一个例子 https://jsfiddle.net/zb0xkuL5/

    这是代码

    <html>
    <body>
     
    
    <main>
        <h2>Section 1</h2>
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque commodo purus quis mi cursus hendrerit eu eu metus. Aliquam aliquam arcu eget aliquet scelerisque. Pellentesque sodales turpis vitae venenatis vehicula.</p> 
        <p>Ut id porta velit. Ut eu dignissim dui, quis gravida est. Cras quis venenatis mauris, a bibendum enim. Sed at augue libero. Nullam tortor metus, tincidunt ut urna id, posuere placerat orci. Ut quis risus dictum risus facilisis imperdiet quis sed eros.</p>
        <p>Nullam tortor metus, tincidunt ut urna id, posuere placerat orci.</p> 
        <p>Ut quis risus dictum risus facilisis imperdiet quis sed eros. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p> 
        <p>Quisque commodo purus quis mi cursus hendrerit eu eu metus. Aliquam aliquam arcu eget aliquet scelerisque. Pellentesque sodales turpis vitae venenatis vehicula. Ut id porta velit. Ut eu dignissim dui, quis gravida est. Cras quis venenatis mauris, a bibendum enim. Sed at augue libero.</p>
        <p>Nullam tortor metus, tincidunt ut urna id, posuere placerat orci.</p> 
        <p>Ut quis risus dictum risus facilisis imperdiet quis sed eros. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p> 
        <p>Quisque commodo purus quis mi cursus hendrerit eu eu metus. Aliquam aliquam arcu eget aliquet scelerisque. Pellentesque sodales turpis vitae venenatis vehicula. Ut id porta velit. Ut eu dignissim dui, quis gravida est. Cras quis venenatis mauris, a bibendum enim. Sed at augue libero.</p>
        <p>Nullam tortor metus, tincidunt ut urna id, posuere placerat orci.</p> 
        <p>Ut quis risus dictum risus facilisis imperdiet quis sed eros. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p> 
        <p>Quisque commodo purus quis mi cursus hendrerit eu eu metus. Aliquam aliquam arcu eget aliquet scelerisque. Pellentesque sodales turpis vitae venenatis vehicula. Ut id porta velit. Ut eu dignissim dui, quis gravida est. Cras quis venenatis mauris, a bibendum enim. Sed at augue libero.</p>
        <p>Nullam tortor metus, tincidunt ut urna id, posuere placerat orci.</p> 
        <p>Ut quis risus dictum risus facilisis imperdiet quis sed eros. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p> 
        <p>Quisque commodo purus quis mi cursus hendrerit eu eu metus. Aliquam aliquam arcu eget aliquet scelerisque. Pellentesque sodales turpis vitae venenatis vehicula. Ut id porta velit. Ut eu dignissim dui, quis gravida est. Cras quis venenatis mauris, a bibendum enim. Sed at augue libero.</p>
        <p>Nullam tortor metus, tincidunt ut urna id, posuere placerat orci.</p> 
        <p>Ut quis risus dictum risus facilisis imperdiet quis sed eros. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p> 
        <p>Quisque commodo purus quis mi cursus hendrerit eu eu metus. Aliquam aliquam arcu eget aliquet scelerisque. Pellentesque sodales turpis vitae venenatis vehicula. Ut id porta velit. Ut eu dignissim dui, quis gravida est. Cras quis venenatis mauris, a bibendum enim. Sed at augue libero.</p>
        <p>Nullam tortor metus, tincidunt ut urna id, posuere placerat orci.</p> 
        <p>Ut quis risus dictum risus facilisis imperdiet quis sed eros. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p> 
        <p>Quisque commodo purus quis mi cursus hendrerit eu eu metus. Aliquam aliquam arcu eget aliquet scelerisque. Pellentesque sodales turpis vitae venenatis vehicula. Ut id porta velit. Ut eu dignissim dui, quis gravida est. Cras quis venenatis mauris, a bibendum enim. Sed at augue libero.</p>
        <p>Nullam tortor metus, tincidunt ut urna id, posuere placerat orci.</p> 
        <p>Ut quis risus dictum risus facilisis imperdiet quis sed eros. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p> 
        <p>Quisque commodo purus quis mi cursus hendrerit eu eu metus. Aliquam aliquam arcu eget aliquet scelerisque. Pellentesque sodales turpis vitae venenatis vehicula. Ut id porta velit. Ut eu dignissim dui, quis gravida est. Cras quis venenatis mauris, a bibendum enim. Sed at augue libero.</p>
    
        <h2>Section 2</h2>
        <p>Nullam tortor metus, tincidunt ut urna id, posuere placerat orci.</p> 
        <p>Ut quis risus dictum risus facilisis imperdiet quis sed eros. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p> 
        <p>Quisque commodo purus quis mi cursus hendrerit eu eu metus. Aliquam aliquam arcu eget aliquet scelerisque. Pellentesque sodales turpis vitae venenatis vehicula. Ut id porta velit. Ut eu dignissim dui, quis gravida est. Cras quis venenatis mauris, a bibendum enim. Sed at augue libero.</p>
        <p>Nullam tortor metus, tincidunt ut urna id, posuere placerat orci.</p> 
        <p>Ut quis risus dictum risus facilisis imperdiet quis sed eros. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p> 
        <p>Quisque commodo purus quis mi cursus hendrerit eu eu metus. Aliquam aliquam arcu eget aliquet scelerisque. Pellentesque sodales turpis vitae venenatis vehicula. Ut id porta velit. Ut eu dignissim dui, quis gravida est. Cras quis venenatis mauris, a bibendum enim. Sed at augue libero.</p>
        <p>Nullam tortor metus, tincidunt ut urna id, posuere placerat orci.</p> 
        <p>Ut quis risus dictum risus facilisis imperdiet quis sed eros. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p> 
        <p>Quisque commodo purus quis mi cursus hendrerit eu eu metus. Aliquam aliquam arcu eget aliquet scelerisque. Pellentesque sodales turpis vitae venenatis vehicula. Ut id porta velit. Ut eu dignissim dui, quis gravida est. Cras quis venenatis mauris, a bibendum enim. Sed at augue libero.</p>
        <p>Nullam tortor metus, tincidunt ut urna id, posuere placerat orci.</p> 
        <p>Ut quis risus dictum risus facilisis imperdiet quis sed eros. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p> 
        <p>Quisque commodo purus quis mi cursus hendrerit eu eu metus. Aliquam aliquam arcu eget aliquet scelerisque. Pellentesque sodales turpis vitae venenatis vehicula. Ut id porta velit. Ut eu dignissim dui, quis gravida est. Cras quis venenatis mauris, a bibendum enim. Sed at augue libero.</p>
        <p>Nullam tortor metus, tincidunt ut urna id, posuere placerat orci.</p> 
        <p>Ut quis risus dictum risus facilisis imperdiet quis sed eros. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p> 
        <p>Quisque commodo purus quis mi cursus hendrerit eu eu metus. Aliquam aliquam arcu eget aliquet scelerisque. Pellentesque sodales turpis vitae venenatis vehicula. Ut id porta velit. Ut eu dignissim dui, quis gravida est. Cras quis venenatis mauris, a bibendum enim. Sed at augue libero.</p>
        <p>Nullam tortor metus, tincidunt ut urna id, posuere placerat orci.</p> 
        <p>Ut quis risus dictum risus facilisis imperdiet quis sed eros. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p> 
        <p>Quisque commodo purus quis mi cursus hendrerit eu eu metus. Aliquam aliquam arcu eget aliquet scelerisque. Pellentesque sodales turpis vitae venenatis vehicula. Ut id porta velit. Ut eu dignissim dui, quis gravida est. Cras quis venenatis mauris, a bibendum enim. Sed at augue libero.</p>
        <p>Nullam tortor metus, tincidunt ut urna id, posuere placerat orci.</p> 
        <p>Ut quis risus dictum risus facilisis imperdiet quis sed eros. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p> 
        <p>Quisque commodo purus quis mi cursus hendrerit eu eu metus. Aliquam aliquam arcu eget aliquet scelerisque. Pellentesque sodales turpis vitae venenatis vehicula. Ut id porta velit. Ut eu dignissim dui, quis gravida est. Cras quis venenatis mauris, a bibendum enim. Sed at augue libero.</p>
    
    </main>  </body>
    </html>
    <style>  
     body {
      max-width: 40rem;
      margin: 0 auto;
      padding: 1em;
    }
    
    main {
      border-width: 2px 0;
      border-style: solid;
    }
    
    main h2 {
        top: 0;
        position: sticky;
        background: #fff;
      margin: 0;
    }
    
    main > div + h2 {
      border-top: 2px solid;
    }
    
    h2 button {
      all: inherit;
      border: 0;
      display: flex;
      justify-content: space-between;
      width: 100%;
      padding: 0.5em 0;
    }
    
    
    
    h2 button:focus svg {
      outline: 2px solid;
    }
    
    button svg {
      height: 1em;
      margin-left: 0.5em;
    }
    
    [aria-expanded="true"] .vert {
      display: none;
    }
    
    [aria-expanded] rect {
      fill: currentColor;
    }
    
    /* page styles */
    
    html {
      font-family: Arial, sans-serif;
    }
    
    * {
      box-sizing: border-box;
    }
    </style>
    <script>  
        (function() {
       // Get all the <h2> headings
       const headings = document.querySelectorAll('main h2')
       
       Array.prototype.forEach.call(headings, heading => {
         // Give each <h2> a toggle button child
         // with the SVG plus/minus icon
         heading.innerHTML = `
           <button aria-expanded="false">
             ${heading.textContent}
             <svg aria-hidden="true" focusable="false" viewBox="0 0 10 10">
               <rect class="vert" height="8" width="2" y="1" x="4"/>
               <rect height="2" width="8" y="4" x="1"/>
             </svg>
           </button>
         `
         
         // Function to create a node list 
         // of the content between this <h2> and the next
         const getContent = (elem) => {
           let elems = []
           while (elem.nextElementSibling && elem.nextElementSibling.tagName !== 'H2') {
             elems.push(elem.nextElementSibling)
             elem = elem.nextElementSibling
           }
           
           // Delete the old versions of the content nodes
           elems.forEach((node) => {
             node.parentNode.removeChild(node)
           })
     
           return elems
         }
         
         // Assign the contents to be expanded/collapsed (array)
         let contents = getContent(heading)
         
         // Create a wrapper element for `contents` and hide it
         let wrapper = document.createElement('div')
         wrapper.hidden = true
         
         // Add each element of `contents` to `wrapper`
         contents.forEach(node => {
           wrapper.appendChild(node)
         })
         
         // Add the wrapped content back into the DOM 
         // after the heading
         heading.parentNode.insertBefore(wrapper, heading.nextElementSibling)
         
         // Assign the button
         let btn = heading.querySelector('button')
         
         btn.onclick = () => {
           // Cast the state as a boolean
           let expanded = btn.getAttribute('aria-expanded') === 'true' || false
           
           // Switch the state
           btn.setAttribute('aria-expanded', !expanded)
           // Switch the content's visibility
           wrapper.hidden = expanded    
         }
       })
     })()
          </script>
    

    【讨论】:

    • 我真的很喜欢!不幸的是,我不能在我当前的项目中使用 Bootstrap :( 非常感谢!
    • 谢谢!但是您不需要那里的引导程序,这是错误的..现在看这个jsfiddle.net/moti013/2ducyLnr
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-29
    • 1970-01-01
    • 1970-01-01
    • 2016-04-01
    • 2019-01-05
    • 2013-07-24
    • 2023-03-19
    相关资源
    最近更新 更多