Tạo Hiệu Ứng Accordion

Trong bài học này chúng ta sẽ tìm hiểu cách sử dụng JavaScript để tạo hiệu ứng accordion cho trang FAQ.

Với hiệu ứng accordion này thì ban đầu khi trình duyệt tải về trang faq.html thì nội dung các câu trả lời sẽ được ẩn đi và chỉ khi nào người dùng click vào từng câu hỏi thì phần nội dung của câu trả lời tương ứng mới được hiển thị. Ngoài ra chúng ta cũng sẽ thêm vào một biểu tượng ẩn/hiện (toogle display icon) để người dùng có thể dựa trên đó nhận biết được nội dung câu trả lời đang được hiển thị hay bị ẩn đi.

Thêm HTML cho Toogle Display Icon

Để bắt đầu bạn lần lượt thêm vào ngay sau từng thẻ mở <div class="question"> đoạn mã HTML cho toogle display icon như sau:

<div class="question">
    <strong class="toggle-display">+</strong> ...
...

Bây giờ khi mở lại trang faq.html trên trình duyệt bạn sẽ thấy kết quả hiển thị như sau:

Hiển thị toogle display icon

Cập Nhật CSS

Trong tập tin main.css, ở ngay phía trước dòng CSS comment dành cho sticky foooter, chúng ta sẽ thêm vào đoạn mã CSS để trang trí cho biểu tượng ẩn/hiện câu trả lời như sau:

..
.toggle-display {
    border: 1px solid #aaa;
    padding: 1px 5px;
    margin-right: 5px;
    cursor: pointer;
}

/* sticky footer */
...

Đồng thời ẩn hiển thị nội dung câu trả lời mặc định khi trang được tải về:

...
.answer {
    padding: 15px;
    display: none;
}
...

Nếu tải lại trang faq.html lúc này bạn sẽ thấy câu trả lời cho từng câu hỏi đã được ẩn đi:

Ẩn hiển thị nội dung các câu trả lời

Thêm JavaScript tạo Accordion

Sau khi thêm mã HTML cho toogle display icon và trang trí lại nó cũng như ẩn nội dung câu trả lời thì bước tiếp theo chúng ta cần thực hiện là thêm vào mã JavaScript để tạo hiệu ứng accordion trên trang.

Trong phía cuối tập tin script.js bạn thêm vào đoạn mã JavaScript sau:

...

var questions = document.getElementsByClassName('question');
for (var j = 0; j < questions.length; j++) {
    var question = questions[j];

    question.onclick = function () {
        // var answer = question.nextElementSibling; // Lỗi khi dùng cách này!!!
        var answer = this.nextElementSibling; // Dùng 'this' => OK (y)(y)(y)
        console.log(answer);
    }

}

Đoạn mã trên lặp qua các phần tử div.question trên trang và gắn vào hàm lắng nghe cho sự kiện click chuột đối với từng phần tử:

    ...
    question.onclick = function () {
        ...
    }
    ...

Bên trong hàm lắng nghe bạn cũng chú ý có 1 dòng code JavaScript đã được comment đi (vô hiệu hoá) bởi vì dòng này sử dụng biến question được khai báo phía ngoài hàm và điều này sẽ gây ra lỗi bới khi hàm được gọi biến question này có thể sẽ không phải là phần tử mà người dùng click (giống như trường hợp của hàm lắng nghe sử dụng tạo lightbox mà chúng ta đã đề cập ở bài học refactor code).

Thay vào đó chúng ta sử dụng biến this và bạn có thể kiểm tra giá trị của biến answer bằng cách click vào từng biểu tượng đấu cộng và bật tab Console trong developer tool để theo dõi giá trị phần tử được log ra màn hình (bấm vào biểu tượng mũi tên nằm phía trái mỗi giá trị để mở rộng các thông tin của phần tử):

Giá trị của biến answer khi sử dụng this

Bây giờ bạn comment dòng console.log() đi và thêm vào đưới dòng này đoạn code sau:

    ...
    // console.log(answer);

    // ẩn/hiện câu trả lời
    var display = answer.style.display;
    answer.style.display = display == 'block' ? 'none' : 'block';

    // thay đổi nội dung của toogle display icon
    var iconText = this.getElementsByClassName('toggle-display')[0].innerText;
    this.getElementsByClassName('toggle-display')[0].innerText = (iconText == '+') ? '-' : '+';
    ...

Đoạn code trên sẽ thực hiện hai tác vụ:

  • Ẩn hoặc hiện một cách tương ứng nội dung của câu trả lời cho câu hỏi mà người dùng click chuột nên trên nội dung của nó.
  • Thay đổi nội dung của icon toolge display, từ dầu cộng sang dấu trừ hoặc ngược lại.

Bạn hãy tải lại trang faq.html một lần nữa và thực hiện việc click vào nội dung của các câu hỏi để kiểm tra.

Kiểm tra hiệu ứng accordion của trang FAQ

Tới đây bạn đã hoàn tất việc tạo ra hiệu ứng accordion cho trang FAQ.

Thiết Kế Web JavaScript Frontend HTML CSS Frontend
Thêm Bình Luận: