<div class="accordion-01 js-accordion-01">
    <div class="accordion-01__head">
        <p class="accordion-01__sub-heading"><span>ACCORDION 01-1</span></p>
        <h3 class="accordion-01__heading">アコーディオン 01-1</h3>
        <div class="accordion-01__icon"></div>
    </div>
    <div class="accordion-01__content-wrapper">
        <div class="accordion-01__content">テキストが入ります。テキストが入ります。テキストが入ります。テキストが入ります。テキストが入ります。テキストが入ります。テキストが入ります。</div>
    </div>
</div>
<div class="accordion-01 js-accordion-01">
    <div class="accordion-01__head">
        <p class="accordion-01__sub-heading"><span>ACCORDION 01-2</span></p>
        <h3 class="accordion-01__heading">アコーディオン 01-2</h3>
        <div class="accordion-01__icon"></div>
    </div>
    <div class="accordion-01__content-wrapper">
        <div class="accordion-01__content">テキストが入ります。テキストが入ります。テキストが入ります。テキストが入ります。テキストが入ります。テキストが入ります。テキストが入ります。</div>
    </div>
</div>
each accordion in accordionItems
  .accordion-01.js-accordion-01
    .accordion-01__head
      p.accordion-01__sub-heading
        span #{ accordion.subHeading }
      h3.accordion-01__heading #{ accordion.heading }
      .accordion-01__icon
    .accordion-01__content-wrapper
      .accordion-01__content #{ accordion.content }
{
  "accordionItems": [
    {
      "subHeading": "ACCORDION 01-1",
      "heading": "アコーディオン 01-1",
      "content": "テキストが入ります。テキストが入ります。テキストが入ります。テキストが入ります。テキストが入ります。テキストが入ります。テキストが入ります。"
    },
    {
      "subHeading": "ACCORDION 01-2",
      "heading": "アコーディオン 01-2",
      "content": "テキストが入ります。テキストが入ります。テキストが入ります。テキストが入ります。テキストが入ります。テキストが入ります。テキストが入ります。"
    }
  ]
}
  • Content:
    $BLOCK_NAME: '.accordion-01';
    
    // 変数
    $color_primary: #e60000;
    $color_black: #272727;
    $color_gray: #8e8e8e;
    $duration_default: 0.6s;
    $easing_default: cubic-bezier(0.23, 1, 0.32, 1);
    
    #{ $BLOCK_NAME } {
      padding: 0 16px;
      font-family: 'Noto Sans JP', sans-serif;
      border-bottom: 1px solid $color_black;
      &:nth-of-type(1) {
        border-top: 1px solid $color_black;
      }
    
      &__head {
        position: relative;
        padding: 20px 0;
        cursor: pointer;
      }
    
      &__sub-heading {
        font-size: 36px;
        font-weight: 500;
        line-height: 1;
        & > span {
          display: inline-block;
          background: linear-gradient(
            to right,
            $color_black 0%,
            $color_black 50%,
            $color_primary 50%,
            $color_primary 100%
          );
          background-position: 200% 0;
          -webkit-background-clip: text;
          background-size: 200% 100%;
          animation: accordion01TextMaskOut $duration_default $easing_default
            forwards;
          -webkit-text-fill-color: transparent;
          @at-root #{ $BLOCK_NAME }:hover & {
            animation: accordion01TextMask $duration_default $easing_default
              forwards;
          }
          @at-root #{ $BLOCK_NAME }.is-open & {
            animation: accordion01TextMask $duration_default $easing_default
              forwards;
          }
        }
      }
    
      &__heading {
        margin-top: 8px;
        font-size: 14px;
        color: $color_gray;
      }
    
      &__icon {
        position: absolute;
        top: 0;
        right: 0;
        bottom: 0;
        display: block;
        width: 26px;
        height: 26px;
        margin: auto;
        content: '';
        &::before,
        &::after {
          position: absolute;
          top: 0;
          right: 0;
          bottom: 0;
          left: 0;
          display: block;
          height: 3px;
          margin: auto;
          content: '';
          background: #000;
          transition: background-color 0.3s;
          @at-root #{ $BLOCK_NAME }:hover & {
            background: $color_primary;
          }
        }
        &::after {
          transition: all 0.3s;
          transform: rotate(90deg);
          @at-root #{ $BLOCK_NAME }.is-open & {
            background: $color_primary;
            transform: rotate(0);
          }
        }
      }
    
      &__content-wrapper {
        height: 0;
        overflow: hidden;
      }
    
      &__content {
        padding-bottom: 16px;
        opacity: 0;
        transition: all 0.3s;
        transform: translateY(4px);
        @at-root #{ $BLOCK_NAME }.is-open & {
          opacity: 1;
          transition-delay: 0.5s;
          transform: translateY(0);
        }
      }
    }
    
    @keyframes accordion01TextMask {
      0% {
        background-position: 200% 0;
      }
      to {
        background-position: 100% 0;
      }
    }
    
    @keyframes accordion01TextMaskOut {
      0% {
        background-position: 100% 0;
      }
      to {
        background-position: 0 0;
      }
    }
    
  • URL: /components/raw/accordion01/accordion01.scss
  • Filesystem Path: src/components/accordions/accordion01/accordion01.scss
  • Size: 2.8 KB
  • Content:
    'use strict';
    import { gsap } from 'gsap';
    
    export function accordion01() {
      const elList = document.getElementsByClassName('js-accordion-01');
      [...elList].forEach(el => {
        const accordion = new Accordion01(<HTMLElement>el);
        accordion.init();
      })
    }
    
    class Accordion01 {
      el: HTMLElement;
      headEl: HTMLElement;
      contentEl: HTMLElement;
      isOpen: Boolean;
      isRunning: Boolean;
      speed: number; // second
      cssAnimSpeed: number; // millisecond
      constructor(accordionEl: HTMLElement) {
        this.el = accordionEl;
        this.headEl = this.el.querySelector('.accordion-01__head');
        this.contentEl = this.el.querySelector('.accordion-01__content-wrapper');
        this.isOpen = false;
        this.isRunning = false;
        this.speed = .5;
        this.cssAnimSpeed = 300;
      }
    
      /**
       * Initialize accordion script
       */
      init(): void {
        this.onHeadClick();
      }
    
      /**
       * Open accordion content
       */
      openContent(): void {
        // In animation, end the process
        if (this.isRunning) return;
        // Open accordion content
        const self = this;
        this.isRunning = true;
        self.el.classList.add('is-open');
        gsap.to(this.contentEl, {
          duration: this.speed,
          height: 'auto',
          onComplete() {
            self.isOpen = true;
            self.isRunning = false;
          }
        });
      }
    
      /**
       * Close accordion content
       */
      closeContent(): void {
        // In animation, end the process
        if (this.isRunning) return;
        // Close accordion after CSS animation
        const self = this;
        this.isRunning = true;
        this.el.classList.remove('is-open');
        setTimeout(() => {
          gsap.to(this.contentEl, {
            duration: this.speed,
            height: 0,
            onComplete() {
              self.isOpen = false;
              self.isRunning = false;
            }
          });
        }, this.cssAnimSpeed);
      }
    
      /**
       * Toggle accordion content
       */
      toggleContent(): void {
        if (this.isOpen) {
          this.closeContent();
        } else {
          this.openContent();
        }
      }
    
      /**
       * Behavior settings when the heading is clicked
       */
      onHeadClick(): void {
        this.el.addEventListener('click', () => {
          this.toggleContent();
        });
      }
    }
    
  • URL: /components/raw/accordion01/accordion01.ts
  • Filesystem Path: src/components/accordions/accordion01/accordion01.ts
  • Size: 2.3 KB