An accordion animated with Animate Plus
contains dl
and legend
elements within fieldset
. Everything works as it's supposed to, except fieldset
doesn't expand and legend
doesn't move with the rest of the elements.
I would like to smoothly resize fieldset
height by the same ammount dl
is increased.
My JavaScript code:
const accordions = Array.from(document.querySelectorAll("dl")).map(dl => ({ element: dl, translate: 0 })) const getButtons = accordion => Array.from( accordion.element.getElementsByTagName("button"), element => ({ element, translate: 0 }) ) const timing = { easing: "out-quartic", duration: 400 } const clear = element => Object.values(element.attributes).forEach(({ name }) => element.removeAttribute(name) ) const hide = async (accordion, buttons, collapsing) => { const objects = buttons.filter(({ translate }) => translate) const direction = "reverse" rotate(collapsing.previousElementSibling.lastElementChild, direction) slide(accordion, objects) await fold(collapsing, direction) clear(collapsing) } const show = (accordion, buttons, expanding) => { const button = expanding.previousElementSibling.lastElementChild const index = buttons.findIndex(({ element }) => element == button) const objects = buttons.slice(index + 1) const { height } = expanding.getBoundingClientRect() expanding.className = "open" rotate(button) slide(accordion, objects, height) fold(expanding) } const slide = (accordion, array, to = 0) => { center(accordion, to) animate({ ...timing, elements: array.map(({ element }) => element.parentElement), transform(index) { const object = array[index] const from = object.translate object.translate = to return [`translateY(${from}px)`, to] } }) } const center = (accordion, height) => { const from = accordion.translate const to = Math.round(-height / 2) accordion.translate = to animate({ ...timing, elements: accordion.element, transform: [`translateY(${from}px)`, to] }) } const fold = async (content, direction = "normal") => await animate({ ...timing, direction, elements: content, opacity: [0, 1], transform: ["scaleY(0)", 1] }) const rotate = ({ lastElementChild: elements }, direction = "normal") => animate({ elements, direction, easing: "out-cubic", duration: 600, transform: ["rotate(0turn)", 0.5] }) const toggle = (accordion, buttons) => async ({ target }) => { const collapsing = accordion.element.querySelector(".open") const expanding = target.parentElement.nextElementSibling if (collapsing) await hide(accordion, buttons, collapsing) if (collapsing != expanding) show(accordion, buttons, expanding) } accordions.forEach(accordion => { const buttons = getButtons(accordion) buttons.forEach( ({ element }) => element.addEventListener("click", toggle(accordion, buttons)) ) }) import animate from "https://cdn.jsdelivr.net/npm/animateplus@2/animateplus.js"
My full code for an accordion can be found on CodePen:
The issue all stems from the fact that you have:
dd {
position: absolute;
/* more styles */
}
Essentially, this makes it so that the height of this element gets ignored when calculating its parent's height.
I'm not familiar with the library you are using, but doing a quick modification to remove that, set the max-height to 0 when it's hidden, and then animate that height to the scrollHeight
of the content (ie the height of the content when maxHeight is ignored).
https://codepen.io/anon/pen/xMXbJX
dd {
opacity: 0;
max-height: 0;
}
const fold = async (content, direction = "normal") => {
const scrollHeight = content.scrollHeight
await animate({
...timing,
direction,
elements: content,
opacity: [0, 1],
maxHeight: ['0px', scrollHeight + 'px'],
transform: ["scaleY(0)", 1]
})
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.