javascript - 带有 WAI-ARIA 的可折叠部分:附加“隐藏”按钮?
问题描述
我正在使用此代码片段(在此处解释)使用 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
}
})
})()
解决方案
怎么把它们粘在上面,这样你总是可以崩溃的。
这是示例 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>
推荐阅读
- jquery - 插件更新后 jQuery 验证错误“jquery.format 不是函数”
- google-analytics - GTM 的 Google 同意模式
- cookies - 如何为 next.js 中的每个页面使用 getServerSideProps?
- algorithm - 二进制迷宫生成器
- sql - Sql按日期获取表中的最新行-双选vs order by
- r - 你如何呈现一个表格(和图表)来说明 R 中排列组大小的频率?
- sql - 如何通过多项选择在键表中选择值
- excel - 如何在保存的文件名中添加时间?
- node.js - 来自 Firebase 的 Node.js 值未及时更新数组以进行函数调用(即使使用 Async Await)
- gradle - 没有为代码覆盖率生成 JaCoCo XML 报告