<section class="card">
    <h2 class="card__header">Markets</h2>
    <ul class="accordion accordion-js">
        <li class="accordion__item">
            <h3 class="accordion-item__title">
                <button
                    data-accordion-control="text"
                    data-accordion-expanded="false"
                    class="accordion-item__button"
                >
                    Total Points
                    <span class="accordion-item__arrow">
                        <svg
                            xmlns="http://www.w3.org/2000/svg"
                            width="14"
                            height="8"
                            viewBox="0 0 14 8"
                            fill="none"
                        >
                            <path
                                d="M1 1L7 7L13 1"
                                stroke="white"
                                stroke-width="2"
                                stroke-linejoin="round"
                            />
                        </svg>
                    </span>
                </button>
            </h3>
            <div
                class="accordion-item__content"
                data-accordion-expanded="false"
                data-accordion-content="text"
                hidden
            >
                <ul class="user-list">
                    <li class="user-list__item">
                        Jacob Mullins
                        <span class="user-list__budget">$4.42</span>
                    </li>
                    <li class="user-list__item">
                        Frank Scott
                        <span class="user-list__budget">$0.62</span>
                    </li>
                    <li class="user-list__item">
                        Brad Butter
                        <span class="user-list__budget">$1.89</span>
                    </li>
                    <li class="user-list__item">
                        Sasha Avocado
                        <span class="user-list__budget">$3.55</span>
                    </li>
                    <li class="user-list__item">
                        Mike Bad
                        <span class="user-list__budget">$2.12</span>
                    </li>
                    <li class="user-list__item">
                        Anna Milk
                        <span class="user-list__budget">$2.31</span>
                    </li>
                </ul>
            </div>
        </li>
<!--         <li class="accordion__item">
            <h3 class="accordion-item__title">
                <button
                    data-accordion-control="text2"
                    data-accordion-expanded="false"
                    class="accordion-item__button"
                >
                    Total Points
                    <span class="accordion-item__arrow">
                        <svg
                            xmlns="http://www.w3.org/2000/svg"
                            width="14"
                            height="8"
                            viewBox="0 0 14 8"
                            fill="none"
                        >
                            <path
                                d="M1 1L7 7L13 1"
                                stroke="white"
                                stroke-width="2"
                                stroke-linejoin="round"
                            />
                        </svg>
                    </span>
                </button>
            </h3>
            <div
                class="accordion-item__content"
                data-accordion-content="text2"
                data-accordion-expanded="false"
                hidden
            >
                <ul class="user-list">
                    <li class="user-list__item">
                        Jacob Mullins
                        <span class="user-list__budget">$4.42</span>
                    </li>
                    <li class="user-list__item">
                        Frank Scott
                        <span class="user-list__budget">$0.62</span>
                    </li>
                    <li class="user-list__item">
                        Brad Butter
                        <span class="user-list__budget">$1.89</span>
                    </li>
                    <li class="user-list__item">
                        Sasha Avocado
                        <span class="user-list__budget">$3.55</span>
                    </li>
                    <li class="user-list__item">
                        Mike Bad
                        <span class="user-list__budget">$2.12</span>
                    </li>
                    <li class="user-list__item">
                        Anna Milk
                        <span class="user-list__budget">$2.31</span>
                    </li>
                </ul>
            </div>
        </li>
        <li class="accordion__item">
            <h3 class="accordion-item__title">
                <button
                    data-accordion-control="text3"
                    class="accordion-item__button"
                    data-accordion-expanded="false"
                >
                    Total Points
                    <span class="accordion-item__arrow">
                        <svg
                            xmlns="http://www.w3.org/2000/svg"
                            width="14"
                            height="8"
                            viewBox="0 0 14 8"
                            fill="none"
                        >
                            <path
                                d="M1 1L7 7L13 1"
                                stroke="white"
                                stroke-width="2"
                                stroke-linejoin="round"
                            />
                        </svg>
                    </span>
                </button>
            </h3>
            <div
                class="accordion-item__content"
                data-accordion-content="text3"
                data-accordion-expanded="false"
                hidden
            >
                <ul class="user-list">
                    <li class="user-list__item">
                        Jacob Mullins
                        <span class="user-list__budget">$4.42</span>
                    </li>
                    <li class="user-list__item">
                        Frank Scott
                        <span class="user-list__budget">$0.62</span>
                    </li>
                    <li class="user-list__item">
                        Brad Butter
                        <span class="user-list__budget">$1.89</span>
                    </li>
                    <li class="user-list__item">
                        Sasha Avocado
                        <span class="user-list__budget">$3.55</span>
                    </li>
                    <li class="user-list__item">
                        Mike Bad
                        <span class="user-list__budget">$2.12</span>
                    </li>
                    <li class="user-list__item">
                        Anna Milk
                        <span class="user-list__budget">$2.31</span>
                    </li>
                </ul>
            </div>
        </li> -->
    </ul>
    <div class="control">
      <input type="checkbox" id="contain" />
      <label for="contain">contain: size</label>
    </div>
</section>
html {
    height: 100%;
}

body {
    margin: 0;
    padding: 0;
    line-height: 1.6;
    font-size: 16px;
    font-family: 'Poppins', sans-serif;
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100%;
    background-color: #f6483a;
    overflow-x: hidden;
    color: #41413b;
}

.card {
    background-color: #f0f0f6;
    border-radius: 8px;
    padding: 32px 24px 68px;
    box-sizing: border-box;
    width: 340px;
    position: relative;
}

.card__header {
    margin: 0;
    font-size: 16px;
    line-height: 1;
    margin-bottom: 1em;
}

.accordion {
    list-style: none;
    margin: 0;
    padding: 0;
}

.accordion__item:not(:last-of-type) {
    margin-bottom: 12px;
}

.accordion-item__title {
    margin: 0;
}

.accordion-item__button {
    display: flex;
    background-color: #fff;
    border-radius: 4px;
    border: 0;
    width: 100%;
    cursor: pointer;
    padding: 12px;
    position: relative;
    font-weight: 600;
    font-family: inherit;
    color: inherit;
    justify-content: space-between;
    align-items: center;
    z-index: 1;

    &[data-accordion-expanded='true'] {
        border-bottom-left-radius: 0;
        border-bottom-right-radius: 0;
        box-shadow: 0px 7px 12px 0px rgba(0, 0, 0, 0.1);
    }
}

.accordion-item__arrow {
    background-color: #41413b;
    border-radius: 50%;
    width: 24px;
    height: 24px;
    display: flex;
    position: relative;
    align-items: center;
    justify-content: center;

    & > svg {
        transform: translateY(1px);
    }
}

.accordion-item__button[data-accordion-control-animation='true']
    .accordion-item__arrow {
    transition: 250ms background-color ease, 250ms transform ease;
    will-change: transform;
}

.accordion-item__button[data-accordion-expanded='true'] .accordion-item__arrow {
    background-color: #f6483a;
    transform: rotate(180deg);
}

.accordion-item__content {
    border-bottom-left-radius: 4px;
    border-bottom-right-radius: 4px;
    background-color: #fff;
    padding: 0 12px;
}

.accordion-item__content[data-accordion-expanded='true'] {
    margin-top: 4px;
}

.accordion-item__content[data-accordion-content-animation] {
    transition-property: height;
    transition-duration: 300ms;
    transition-timing-function: ease-in-out;
    overflow: hidden;
}

.user-list {
    list-style: none;
    padding: 0;
    margin: 0;
    font-weight: 300;
}

.user-list__item {
    display: flex;
    font-size: 0.9em;
    justify-content: space-between;
    align-items: center;
    padding: 10px 0;

    &:not(:last-of-type) {
        border-bottom: 1px solid #f0f0f6;
    }
}

.user-list__budget {
    background-color: #46c581;
    padding: 2px 12px;
    border-radius: 4px;
    font-weight: 400;
    color: #fff;
    min-width: 44px;
    text-align: center;
}

.control {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 20px;
  display: flex;
  justify-content: center;
  align-items: center;
}

.accordion__item {
  border: 1px dashed #015fcc;
  border-radius: 4px;
  box-shadow: 0 0px 1px 1px #015fcc;
}

.size {
  contain: size;
}
View Compiled
interface Subject {
    subscribe(observer: AccordionObserver): void;
    unsubscribe(observer: AccordionObserver): void;
    notify(): void;
}

class Accordion implements Subject {
    private observers: Set<AccordionObserver> = new Set<AccordionObserver>();

    public activeItem: string = '';

    subscribe(observer: AccordionObserver): void {
        const inObserverExists = this.observers.has(observer);

        if (inObserverExists) {
            return;
        }

        this.observers.add(observer);
    }

    unsubscribe(observer: AccordionObserver): void {
        const inObserverExists = this.observers.has(observer);

        if (inObserverExists) {
            return;
        }

        this.observers.delete(observer);
    }

    notify() {
        for (const observer of Array.from(this.observers)) {
            observer.update(this);
        }
    }

    updateActiveItem(activeItem: string): void {
        this.activeItem = this.activeItem === activeItem ? '' : activeItem;

        this.notify();
    }
}

abstract class AccordionObserver {
    abstract update(context: Accordion): void;

    static controlAttribute = 'data-accordion-control';

    static contentAttribute = 'data-accordion-content';

    public mainElement: HTMLElement = null;

    constructor(mainItem: string) {
        this.mainElement = document.querySelector(mainItem);
    }

    protected getActiveControl(activeItem: string): HTMLElement | null {
        if (!activeItem) {
            return null;
        }

        const activeControlSelector = `[${AccordionObserver.controlAttribute}=${activeItem}]`;

        return this.mainElement.querySelector(activeControlSelector);
    }

    protected getActiveContent(activeItem: string): HTMLElement | null {
        if (!activeItem) {
            return null;
        }

        const activeContentSelector = `[${AccordionObserver.contentAttribute}=${activeItem}]`;

        return this.mainElement.querySelector(activeContentSelector);
    }

    protected get controls(): HTMLElement[] {
        const controlsSelector = `[${AccordionObserver.controlAttribute}]`;

        return Array.from(this.mainElement.querySelectorAll(controlsSelector));
    }

    protected get contents(): HTMLElement[] {
        const contentsSelector = `[${AccordionObserver.contentAttribute}]`;

        return Array.from(this.mainElement.querySelectorAll(contentsSelector));
    }

    static addEventListener(mainItem: string, accordion: Accordion) {
        const mainElement = document.querySelector(mainItem);
        const controlsSelector = `[${AccordionObserver.controlAttribute}]`;
        const controls = mainElement.querySelectorAll(controlsSelector);

        Array.from(controls).forEach((control) => {
            control.addEventListener('click', (e: MouseEvent) => {
                const targetElement = e.target as HTMLElement;
                const controlValue = targetElement.getAttribute(
                    AccordionObserver.controlAttribute
                );

                if (!controlValue) {
                    return;
                }

                accordion.updateActiveItem(controlValue);
            });
        });
    }
}

class AccordionInterfaceObserver extends AccordionObserver {
    update(context: Accordion): void {
        this.updateInterface(context.activeItem);
    }

    private resetInterface() {
        this.contents.forEach((content) => {
            content.setAttribute('hidden', 'true');
            content.setAttribute('data-accordion-expanded', 'false');
        });

        this.controls.forEach((controls) => {
            controls.setAttribute('data-accordion-expanded', 'false');
        });
    }

    private updateInterface(activeItem: string): void {
        const activeContent = this.getActiveContent(activeItem);
        const activeControl = this.getActiveControl(activeItem);
        this.resetInterface();

        if (!activeContent) {
            return;
        }

        activeContent.removeAttribute('hidden');
        activeControl.setAttribute('data-accordion-expanded', 'true');
        activeContent.setAttribute('data-accordion-expanded', 'true');
    }
}

class AccordionAriaObserver extends AccordionObserver {
    constructor(mainItem: string) {
        super(mainItem);

        this.initAriaAttributes();
    }

    update(context: Accordion): void {
        this.updateAria(context.activeItem);
    }

    private initAriaAttributes(): void {
        this.controls.forEach((control) => {
            const controlValue = control.getAttribute('data-accordion-control');

            control.setAttribute('aria-expanded', 'false');
            control.setAttribute('aria-controls', controlValue);
        });

        this.contents.forEach((content) => {
            const contentValue = content.getAttribute('data-accordion-content');

            content.setAttribute('id', contentValue);
        });
    }

    private resetAria(): void {
        this.controls.forEach((control) => {
            control.setAttribute('aria-expanded', 'false');
        });
    }

    private updateAria(activeItem: string): void {
        const activeControl = this.getActiveControl(activeItem);
        this.resetAria();

        if (!activeControl) {
            return;
        }

        activeControl.setAttribute('aria-expanded', 'true');
    }
}

class AccordionAnimationObserver extends AccordionObserver {
    static CONTROLS_ANIMATION_ATTR: string = 'data-accordion-control-animation';
    static CONTENT_ANIMATION_ATTR: string = 'data-accordion-content-animation';

    prevContent: string;

    constructor(mainItem: string) {
        super(mainItem);
        this.prevContent = '';

        this.setControlAnimation();
        this.setContentAnimation();
    }

    update(context: Accordion): void {
        this.animate(context.activeItem);
    }

    private setControlAnimation(): void {
        this.controls.forEach((control) => {
            control.setAttribute(
                AccordionAnimationObserver.CONTROLS_ANIMATION_ATTR,
                'true'
            );
        });
    }

    private setContentAnimation(): void {
        this.contents.forEach((control) => {
            control.setAttribute(
                AccordionAnimationObserver.CONTENT_ANIMATION_ATTR,
                'false'
            );
        });
    }

    private animateActiveContent(activeItem: string): void {
        const activeContent = this.getActiveContent(activeItem);

        if (!activeContent) {
            return;
        }

        const animateToHeight = activeContent.offsetHeight;
        activeContent.style.height = '0px';

        requestAnimationFrame(() => {
            requestAnimationFrame(() => {
            activeContent.style.height = `${animateToHeight}px`;
            activeContent.setAttribute(
                AccordionAnimationObserver.CONTENT_ANIMATION_ATTR,
                'true'
            );
                  });
        });
    }

    private hidePreviousContent(): void {
        if (!this.prevContent) {
            return;
        }

        const activePrevContent = this.getActiveContent(this.prevContent);

        activePrevContent.removeAttribute('hidden');
        activePrevContent.style.height = '0px';
        activePrevContent.setAttribute(
            AccordionAnimationObserver.CONTENT_ANIMATION_ATTR,
            'false'
        );

        activePrevContent.addEventListener(
            'transitionend',
            function hidePrevContent() {
                activePrevContent.setAttribute('hidden', 'true');
                activePrevContent.style.height = '';
                activePrevContent.removeEventListener(
                    'transitionend',
                    hidePrevContent
                );
            }
        );
    }

    private animate(activeItem: string): void {
        this.hidePreviousContent();
        this.animateActiveContent(activeItem);

        this.prevContent = activeItem;
    }
}

const accordion = new Accordion();
const accordionInterfaceObserver = new AccordionInterfaceObserver(
    '.accordion-js'
);
const accordionAriaObserver = new AccordionAriaObserver('.accordion-js');
const accordionAnimationObserver = new AccordionAnimationObserver(
    '.accordion-js'
);

accordion.subscribe(accordionInterfaceObserver);
accordion.subscribe(accordionAriaObserver);
accordion.subscribe(accordionAnimationObserver);

AccordionObserver.addEventListener('.accordion-js', accordion);

const checkBox = document.getElementById('contain')
const itemElement = document.querySelector('.accordion__item')

checkBox.addEventListener('input', (etv) => {
  console.log(etv.target.checked)
  if (etv.target.checked) {
    itemElement.classList.add('size')
  } else {
    itemElement.classList.remove('size')
  }
})
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.