FAQ Section HTML CSS JS #2

This FAQ section HTML CSS JS tutorial shows you how to build a tabbed FAQ accordion with category switching. Clicking a category tab on the left swaps the questions on the right, and each question opens and closes with a smooth accordion animation.

The layout collapses to a single column on mobile with the category tabs switching to a horizontal scrollable row.

Final output:

Frequently Asked Questions

Can’t find what you’re looking for?
Talk to us directly.

  • Billing
  • Integrations
  • Security
  • Product
01Can I switch plans mid-cycle without losing my data?

Yes, upgrades apply instantly, downgrades apply next cycle, data stays intact.

02Can I pay annually and get a discount?

Yes, annual billing saves 20%, switchable anytime.

03What happens when I hit my usage limit?

You get an email at 80% and 100%, plus a grace period before features pause.

04Do you offer refunds?

Full refund within 14 days of purchase, no questions asked.

01Do you support SSO with providers other than Google and GitHub?

Yes, SAML SSO for Okta, Azure AD, and OneLogin on paid plans.

02How does the webhook retry logic work?

Failed webhooks retry with exponential backoff, 5 attempts over 24 hours.

03Is there a rate limit on the REST API?

100 req/min standard, 1000 req/min enterprise.

04Do you have a Zapier integration?

Yes, with pre-built triggers for common events.

01Where is data stored and can I choose the region?

AWS us-east-1 by default. EU and APAC available on business plans.

02Are you SOC 2 compliant?

Yes, SOC 2 Type II certified, reports on request.

03Do you have a bug bounty program?

Yes, via HackerOne, $50 to $2,500 per report depending on severity.

01Can I export my data?

Yes, anytime, as CSV or JSON.

02Do you offer a free trial?

14 days, no card required.

03Is there a mobile app?

iOS and Android apps are in beta.

04Can I invite team members?

Yes, unlimited seats on business plans.


Steps for FAQ Section HTML CSS JavaScript #2

1. Let’s start with a section element with the class faq-section. Inside it, add a .faq-header div and a .faq-content-wrapper div.

<section class="faq-section">
    <div class="faq-header"></div>
    <div class="faq-content-wrapper"></div>
</section>

Link the DM Sans and Unbounded fonts from Google Fonts in the head.

<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link
    href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,100..1000;1,9..40,100..1000&family=Unbounded:wght@200..900&display=swap"
    rel="stylesheet">

Reset margins, set DM Sans as the font family, and give the section a light blue background with some padding.

* {
    margin: 0;
    box-sizing: border-box;
}
body {
    font-family: "DM Sans", sans-serif;
}
.faq-section {
    padding: 7rem 5%;
    background-color: #b0e0e6;
}

Now add your heading and a short description to .faq-header. Split it into a .faq-header-left with the label and heading, and a .faq-header-right with the description and a contact link.

<div class="faq-header">
    <div class="faq-header-left">
        <span class="section-label">FAQs</span>
        <h2>Frequently Asked Questions</h2>
    </div>
    <div class="faq-header-right">
        <p>Can't find what you're looking for? <br>
            <a href="#">Talk to us directly.</a>
        </p>
    </div>
</div>

Use a two-column grid on .faq-header with align-items set to end so that the description aligns to the bottom of the heading. And on mobile, collapse to a single column with a smaller gap.

.faq-section .faq-header {
    display: grid;
    grid-template-columns: 1.5fr 1fr;
    gap: 10rem;
    align-items: end;
}
@media (max-width: 600px) {
    .faq-section .faq-header {
        grid-template-columns: 1fr;
        gap: 1.5rem;
    }
}

Output:

Frequently Asked Questions

Can’t find what you’re looking for?
Talk to us directly.

2. Style the section label, heading, and description. Use clamp() on the heading font size so that it scales smoothly between screen sizes. Use the Unbounded font for the heading with a light font weight to contrast the bold label above it.

.faq-section .section-label {
    font-size: .75rem;
    line-height: 16.5px;
    letter-spacing: 1.65px;
    text-transform: uppercase;
    color: hsl(0, 0%, 30%);
}
.faq-section .faq-header-left h2 {
    font-family: "Unbounded", sans-serif;
    font-weight: 300;
    font-size: clamp(2rem, calc(2vw + 1rem), 3.75rem);
    line-height: 1.1;
    letter-spacing: -1.22px;
    text-transform: capitalize;
    margin-top: .75rem;
}
.faq-section .faq-header-right {
    font-size: 1rem;
    line-height: 1.5;
    color: hsl(0, 0%, 50%);
}
.faq-section .faq-header-right a {
    color: #000;
    text-underline-offset: .1rem;
}

Output:

Frequently Asked Questions

Can’t find what you’re looking for?
Talk to us directly.

3. Now add the .faq-content-wrapper. Inside it, add .faq-content-left with the category list and .faq-content-right with the FAQ panels. Each panel is a .faq-category div with a data-category attribute. Only the active panel is visible at a time.

<div class="faq-content-wrapper">
    <div class="faq-content-left">
        <ul class="faq-categories">
            <li data-category="billing" class="active">Billing</li>
            <li data-category="integrations">Integrations</li>
            <li data-category="security">Security</li>
            <li data-category="product">Product</li>
        </ul>
    </div>
    <div class="faq-content-right">
        <div class="faq-category active" data-category="billing">
            <!-- billing questions -->
        </div>
        <div class="faq-category" data-category="integrations">
            <!-- integrations questions -->
        </div>
        <div class="faq-category" data-category="security">
            <!-- security questions -->
        </div>
        <div class="faq-category" data-category="product">
            <!-- product questions -->
        </div>
    </div>
</div>

Now, just like the header, use a two-column grid on .faq-content-wrapper, giving the category list less space than the FAQ panel. On mobile, collapse to a single column.

.faq-section .faq-content-wrapper {
    margin-top: 4rem;
    display: grid;
    grid-template-columns: 1fr 3fr;
}
@media (max-width: 600px) {
    .faq-section .faq-content-wrapper {
        margin-top: 2.5rem;
        grid-template-columns: 1fr;
    }
}

Output:

Frequently Asked Questions

Can’t find what you’re looking for?
Talk to us directly.

  • Billing
  • Integrations
  • Security
  • Product

4. Style the category list. Each list item gets a hover state and an active state that adds a light background. On mobile, switch the list to a horizontal scrollable row so all categories are reachable without taking up too much vertical space.

.faq-section .faq-categories {
    list-style: none;
    padding: 0;
    margin: 0;
    font-size: 1rem;
    display: inline-block;
}
@media (max-width: 600px) {
    .faq-section .faq-content-left {
        margin-bottom: 20px;
        overflow: hidden;
    }
    .faq-section .faq-categories {
        display: flex;
        gap: .5rem;
        overflow-x: auto;
    }
}
.faq-section .faq-categories li {
    padding: .5rem 1rem;
    margin-bottom: .5rem;
    border-radius: .25rem;
    letter-spacing: .5px;
    color: hsl(0, 0%, 30%);
    cursor: pointer;
    transition: background 0.15s, color 0.15s;
}
.faq-section .faq-categories li.active {
    background-color: hsl(0, 0%, 97%);
    color: #000;
}
@media (max-width: 600px) {
    .faq-section .faq-categories li {
        white-space: nowrap;
    }
}

Output:

Frequently Asked Questions

Can’t find what you’re looking for?
Talk to us directly.

  • Billing
  • Integrations
  • Security
  • Product

5. Set all .faq-category panels to display: none by default. Only the one with the active class gets shown. This is because the JavaScript switches it when a category tab is clicked.

.faq-section .faq-category {
    display: none;
}
.faq-section .faq-category.active {
    display: block;
}

Now add the FAQ items inside each .faq-category. Each item uses a details element with a summary for the question. The .icon span inside the summary acts as the plus/minus indicator.

The answer goes inside a .faq-content div with a wrapper div inside it for the smooth animation.

<div class="faq-category active" data-category="billing">
    <details>
        <summary>
            <span>01</span>
            Can I switch plans mid-cycle without losing my data?
            <span class="icon"></span>
        </summary>
        <div class="faq-content">
            <div>
                <p>Yes, upgrades apply instantly, downgrades apply next cycle, data stays intact.</p>
            </div>
        </div>
    </details>
    <!-- add more questions -->
</div>

Frequently Asked Questions

Can’t find what you’re looking for?
Talk to us directly.

  • Billing
  • Integrations
  • Security
  • Product
01Can I switch plans mid-cycle without losing my data?

Yes, upgrades apply instantly, downgrades apply next cycle, data stays intact.

02Can I pay annually and get a discount?

Yes, annual billing saves 20%, switchable anytime.

03What happens when I hit my usage limit?

You get an email at 80% and 100%, plus a grace period before features pause.

04Do you offer refunds?

Full refund within 14 days of purchase, no questions asked.

01Do you support SSO with providers other than Google and GitHub?

Yes, SAML SSO for Okta, Azure AD, and OneLogin on paid plans.

02How does the webhook retry logic work?

Failed webhooks retry with exponential backoff, 5 attempts over 24 hours.

03Is there a rate limit on the REST API?

100 req/min standard, 1000 req/min enterprise.

04Do you have a Zapier integration?

Yes, with pre-built triggers for common events.

01Where is data stored and can I choose the region?

AWS us-east-1 by default. EU and APAC available on business plans.

02Are you SOC 2 compliant?

Yes, SOC 2 Type II certified, reports on request.

03Do you have a bug bounty program?

Yes, via HackerOne, $50 to $2,500 per report depending on severity.

01Can I export my data?

Yes, anytime, as CSV or JSON.

02Do you offer a free trial?

14 days, no card required.

03Is there a mobile app?

iOS and Android apps are in beta.

04Can I invite team members?

Yes, unlimited seats on business plans.

6. Let’s style the details and summary elements. Give each details element a light background and some padding. Remove the default browser arrow on summary using ::-webkit-details-marker. Use flexbox on summary to lay out the number, question text, and icon in a row. Hide the number span on mobile since space is tight.

.faq-section .faq-content-right details {
    padding: 0 1rem;
    border-radius: .5rem;
    background: hsl(0, 0%, 97%);
    margin-bottom: 1rem;
}
.faq-section .faq-content-right summary {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 1.25rem 0;
    cursor: pointer;
    list-style: none;
    font-size: 1.063rem;
    flex-wrap: nowrap;
}
.faq-section .faq-content-right summary::-webkit-details-marker {
    display: none;
}
.faq-section .faq-content-right summary > span:first-child {
    color: hsl(0, 0%, 50%);
    font-size: .75rem;
    min-width: 1rem;
}
@media (max-width: 600px) {
    .faq-section .faq-content-right summary > span:first-child {
        display: none;
    }
}

Frequently Asked Questions

Can’t find what you’re looking for?
Talk to us directly.

  • Billing
  • Integrations
  • Security
  • Product
01Can I switch plans mid-cycle without losing my data?

Yes, upgrades apply instantly, downgrades apply next cycle, data stays intact.

02Can I pay annually and get a discount?

Yes, annual billing saves 20%, switchable anytime.

03What happens when I hit my usage limit?

You get an email at 80% and 100%, plus a grace period before features pause.

04Do you offer refunds?

Full refund within 14 days of purchase, no questions asked.

01Do you support SSO with providers other than Google and GitHub?

Yes, SAML SSO for Okta, Azure AD, and OneLogin on paid plans.

02How does the webhook retry logic work?

Failed webhooks retry with exponential backoff, 5 attempts over 24 hours.

03Is there a rate limit on the REST API?

100 req/min standard, 1000 req/min enterprise.

04Do you have a Zapier integration?

Yes, with pre-built triggers for common events.

01Where is data stored and can I choose the region?

AWS us-east-1 by default. EU and APAC available on business plans.

02Are you SOC 2 compliant?

Yes, SOC 2 Type II certified, reports on request.

03Do you have a bug bounty program?

Yes, via HackerOne, $50 to $2,500 per report depending on severity.

01Can I export my data?

Yes, anytime, as CSV or JSON.

02Do you offer a free trial?

14 days, no card required.

03Is there a mobile app?

iOS and Android apps are in beta.

04Can I invite team members?

Yes, unlimited seats on business plans.

7. Style the .icon span as a plus sign using ::before and ::after pseudo-elements. Set the left margin to auto to push it to the right edge of the summary row. When the details is open, rotate the whole icon 135 degrees to turn the plus into an X shape.ody tag.

.faq-section .icon {
    width: 1.5rem;
    height: 1.5rem;
    border: 1px solid hsl(0, 0%, 70%);
    border-radius: 50%;
    position: relative;
    flex-shrink: 0;
    margin-left: auto;
    transition: border-color 0.2s, transform 0.25s;
}
.faq-section .icon::before,
.faq-section .icon::after {
    content: '';
    position: absolute;
    background: hsl(0, 0%, 30%);
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}
.faq-section .icon::before {
    width: 8px;
    height: 1px;
}
.faq-section .icon::after {
    width: 1px;
    height: 8px;
}
.faq-section details[open] .icon {
    transform: rotate(135deg);
    border-color: hsl(0, 0%, 30%);
}

Output:

Frequently Asked Questions

Can’t find what you’re looking for?
Talk to us directly.

  • Billing
  • Integrations
  • Security
  • Product
01Can I switch plans mid-cycle without losing my data?

Yes, upgrades apply instantly, downgrades apply next cycle, data stays intact.

02Can I pay annually and get a discount?

Yes, annual billing saves 20%, switchable anytime.

03What happens when I hit my usage limit?

You get an email at 80% and 100%, plus a grace period before features pause.

04Do you offer refunds?

Full refund within 14 days of purchase, no questions asked.

01Do you support SSO with providers other than Google and GitHub?

Yes, SAML SSO for Okta, Azure AD, and OneLogin on paid plans.

02How does the webhook retry logic work?

Failed webhooks retry with exponential backoff, 5 attempts over 24 hours.

03Is there a rate limit on the REST API?

100 req/min standard, 1000 req/min enterprise.

04Do you have a Zapier integration?

Yes, with pre-built triggers for common events.

01Where is data stored and can I choose the region?

AWS us-east-1 by default. EU and APAC available on business plans.

02Are you SOC 2 compliant?

Yes, SOC 2 Type II certified, reports on request.

03Do you have a bug bounty program?

Yes, via HackerOne, $50 to $2,500 per report depending on severity.

01Can I export my data?

Yes, anytime, as CSV or JSON.

02Do you offer a free trial?

14 days, no card required.

03Is there a mobile app?

iOS and Android apps are in beta.

04Can I invite team members?

Yes, unlimited seats on business plans.

8. Style .faq-content using the same grid-template-rows trick from the FAQ Section post to animate the height smoothly without needing to know the exact pixel height. The inner div needs overflow set to hidden to clip the content while it animates.

.faq-section .faq-content {
    padding-left: 2.5rem;
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows 0.25s ease;
}
@media (max-width: 600px) {
    .faq-section .faq-content {
        padding-left: 0;
    }
}
.faq-section .faq-content > div {
    overflow: hidden;
}
.faq-section .faq-content p {
    margin: 0 0 1.25rem;
    color: #6b6862;
    font-size: 1rem;
    line-height: 1.65;
}

Now for the JavaScript. Add a script.js file and link it before the closing body tag. You can reuse the same closeDetail and openDetail functions from the FAQ Section post since the animation logic is identical. These handle the smooth open and close transition by animating grid-template-rows and waiting for the transition to finish before toggling the open attribute.

document.addEventListener("DOMContentLoaded", () => {

    function closeDetail(el, content) {
        if (!el.open) return;
        content.style.gridTemplateRows = '1fr';
        requestAnimationFrame(() => requestAnimationFrame(() => {
            content.style.gridTemplateRows = '0fr';
        }));
        content.addEventListener('transitionend', function handler(e) {
            if (e.propertyName !== 'grid-template-rows') return;
            el.open = false;
            content.removeEventListener('transitionend', handler);
        });
    }

    function openDetail(el, content) {
        el.open = true;
        content.style.gridTemplateRows = '0fr';
        requestAnimationFrame(() => requestAnimationFrame(() => {
            content.style.gridTemplateRows = '1fr';
        }));
    }
});

Now attach click listeners to all summary elements. When a question is clicked, if it’s already open, close it. If it’s closed, first close any other open questions, then open the clicked one. This ensures only one question is open at a time.

document.querySelectorAll('details').forEach(el => {
    const content = el.querySelector('.faq-content');
    el.querySelector('summary').addEventListener('click', e => {
        e.preventDefault();
        if (el.open) {
            closeDetail(el, content);
        } else {
            document.querySelectorAll('details[open]').forEach(other => {
                if (other !== el) closeDetail(other, other.querySelector('.faq-content'));
            });
            openDetail(el, content);
        }
    });
});

Output:

Frequently Asked Questions

Can’t find what you’re looking for?
Talk to us directly.

  • Billing
  • Integrations
  • Security
  • Product
01Can I switch plans mid-cycle without losing my data?

Yes, upgrades apply instantly, downgrades apply next cycle, data stays intact.

02Can I pay annually and get a discount?

Yes, annual billing saves 20%, switchable anytime.

03What happens when I hit my usage limit?

You get an email at 80% and 100%, plus a grace period before features pause.

04Do you offer refunds?

Full refund within 14 days of purchase, no questions asked.

01Do you support SSO with providers other than Google and GitHub?

Yes, SAML SSO for Okta, Azure AD, and OneLogin on paid plans.

02How does the webhook retry logic work?

Failed webhooks retry with exponential backoff, 5 attempts over 24 hours.

03Is there a rate limit on the REST API?

100 req/min standard, 1000 req/min enterprise.

04Do you have a Zapier integration?

Yes, with pre-built triggers for common events.

01Where is data stored and can I choose the region?

AWS us-east-1 by default. EU and APAC available on business plans.

02Are you SOC 2 compliant?

Yes, SOC 2 Type II certified, reports on request.

03Do you have a bug bounty program?

Yes, via HackerOne, $50 to $2,500 per report depending on severity.

01Can I export my data?

Yes, anytime, as CSV or JSON.

02Do you offer a free trial?

14 days, no card required.

03Is there a mobile app?

iOS and Android apps are in beta.

04Can I invite team members?

Yes, unlimited seats on business plans.

9. Finally, add the category tab switching. When a tab is clicked, remove the active class from all tabs and add it to the clicked one. Then close any open questions so the next panel starts fresh. Finally, loop through all panels and toggle the active class based on whether the panel’s data-category matches the clicked tab’s data-category.

const tabs = document.querySelectorAll('.faq-categories li');
    const panels = document.querySelectorAll('.faq-category');

    tabs.forEach(tab => {
        tab.addEventListener('click', () => {
            const target = tab.dataset.category;

            tabs.forEach(t => t.classList.remove('active'));
            tab.classList.add('active');

            document.querySelectorAll('details[open]').forEach(el => {
                closeDetail(el, el.querySelector('.faq-content'));
            });

            panels.forEach(panel => {
                panel.classList.toggle('active', panel.dataset.category === target);
            });
        });
    });
});

Output:

Frequently Asked Questions

Can’t find what you’re looking for?
Talk to us directly.

  • Billing
  • Integrations
  • Security
  • Product
01Can I switch plans mid-cycle without losing my data?

Yes, upgrades apply instantly, downgrades apply next cycle, data stays intact.

02Can I pay annually and get a discount?

Yes, annual billing saves 20%, switchable anytime.

03What happens when I hit my usage limit?

You get an email at 80% and 100%, plus a grace period before features pause.

04Do you offer refunds?

Full refund within 14 days of purchase, no questions asked.

01Do you support SSO with providers other than Google and GitHub?

Yes, SAML SSO for Okta, Azure AD, and OneLogin on paid plans.

02How does the webhook retry logic work?

Failed webhooks retry with exponential backoff, 5 attempts over 24 hours.

03Is there a rate limit on the REST API?

100 req/min standard, 1000 req/min enterprise.

04Do you have a Zapier integration?

Yes, with pre-built triggers for common events.

01Where is data stored and can I choose the region?

AWS us-east-1 by default. EU and APAC available on business plans.

02Are you SOC 2 compliant?

Yes, SOC 2 Type II certified, reports on request.

03Do you have a bug bounty program?

Yes, via HackerOne, $50 to $2,500 per report depending on severity.

01Can I export my data?

Yes, anytime, as CSV or JSON.

02Do you offer a free trial?

14 days, no card required.

03Is there a mobile app?

iOS and Android apps are in beta.

04Can I invite team members?

Yes, unlimited seats on business plans.


Final Output Code for FAQ Section HTML CSS JavaScript #2:

Head

<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link
    href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,100..1000;1,9..40,100..1000&family=Unbounded:wght@200..900&display=swap"
    rel="stylesheet">

HTML

<section class="faq-section">
    <div class="faq-header">
        <div class="faq-header-left">
            <span class="section-label">FAQs</span>
            <h2>Frequently Asked Questions</h2>
        </div>
        <div class="faq-header-right">
            <p>Can't find what you're looking for? <br>
                <a href="#">Talk to us directly.</a>
            </p>
        </div>
    </div>
    <div class="faq-content-wrapper">
        <div class="faq-content-left">
            <ul class="faq-categories">
                <li data-category="billing" class="active">Billing</li>
                <li data-category="integrations">Integrations</li>
                <li data-category="security">Security</li>
                <li data-category="product">Product</li>
            </ul>
        </div>
        <div class="faq-content-right">
            <div class="faq-category active" data-category="billing">
                <details>
                    <summary><span>01</span>Can I switch plans mid-cycle without losing my data?<span
                            class="icon"></span>
                    </summary>
                    <div class="faq-content">
                        <div>
                            <p>Yes, upgrades apply instantly, downgrades apply next cycle, data stays intact.</p>
                        </div>
                    </div>
                </details>
                <details>
                    <summary><span>02</span>Can I pay annually and get a discount?<span class="icon"></span>
                    </summary>
                    <div class="faq-content">
                        <div>
                            <p>Yes, annual billing saves 20%, switchable anytime.</p>
                        </div>
                    </div>
                </details>
                <details>
                    <summary><span>03</span>What happens when I hit my usage limit?<span class="icon"></span>
                    </summary>
                    <div class="faq-content">
                        <div>
                            <p>You get an email at 80% and 100%, plus a grace period before features pause.</p>
                        </div>
                    </div>
                </details>
                <details>
                    <summary><span>04</span>Do you offer refunds?<span class="icon"></span></summary>
                    <div class="faq-content">
                        <div>
                            <p>Full refund within 14 days of purchase, no questions asked.</p>
                        </div>
                    </div>
                </details>
            </div>
            <div class="faq-category" data-category="integrations">
                <details>
                    <summary><span>01</span>Do you support SSO with providers other than Google and GitHub?<span
                            class="icon"></span>
                    </summary>
                    <div class="faq-content">
                        <div>
                            <p>Yes, SAML SSO for Okta, Azure AD, and OneLogin on paid plans.</p>
                        </div>
                    </div>
                </details>
                <details>
                    <summary><span>02</span>How does the webhook retry logic work?<span class="icon"></span>
                    </summary>
                    <div class="faq-content">
                        <div>
                            <p>Failed webhooks retry with exponential backoff, 5 attempts over 24 hours.</p>
                        </div>
                    </div>
                </details>
                <details>
                    <summary><span>03</span>Is there a rate limit on the REST API?<span class="icon"></span>
                    </summary>
                    <div class="faq-content">
                        <div>
                            <p>100 req/min standard, 1000 req/min enterprise.</p>
                        </div>
                    </div>
                </details>
                <details>
                    <summary><span>04</span>Do you have a Zapier integration?<span class="icon"></span></summary>
                    <div class="faq-content">
                        <div>
                            <p>Yes, with pre-built triggers for common events.</p>
                        </div>
                    </div>
                </details>
            </div>
            <div class="faq-category" data-category="security">
                <details>
                    <summary><span>01</span>Where is data stored and can I choose the region?<span class="icon"></span>
                    </summary>
                    <div class="faq-content">
                        <div>
                            <p>AWS us-east-1 by default. EU and APAC available on business plans.</p>
                        </div>
                    </div>
                </details>
                <details>
                    <summary><span>02</span>Are you SOC 2 compliant?<span class="icon"></span></summary>
                    <div class="faq-content">
                        <div>
                            <p>Yes, SOC 2 Type II certified, reports on request.</p>
                        </div>
                    </div>
                </details>
                <details>
                    <summary><span>03</span>Do you have a bug bounty program?<span class="icon"></span></summary>
                    <div class="faq-content">
                        <div>
                            <p>Yes, via HackerOne, $50 to $2,500 per report depending on severity.</p>
                        </div>
                    </div>
                </details>
            </div>
            <div class="faq-category" data-category="product">
                <details>
                    <summary><span>01</span>Can I export my data?<span class="icon"></span>
                    </summary>
                    <div class="faq-content">
                        <div>
                            <p>Yes, anytime, as CSV or JSON.</p>
                        </div>
                    </div>
                </details>
                <details>
                    <summary><span>02</span>Do you offer a free trial?<span class="icon"></span></summary>
                    <div class="faq-content">
                        <div>
                            <p>14 days, no card required.</p>
                        </div>
                    </div>
                </details>
                <details>
                    <summary><span>03</span>Is there a mobile app?<span class="icon"></span></summary>
                    <div class="faq-content">
                        <div>
                            <p>iOS and Android apps are in beta.</p>
                        </div>
                    </div>
                </details>
                <details>
                    <summary><span>04</span>Can I invite team members?<span class="icon"></span></summary>
                    <div class="faq-content">
                        <div>
                            <p>Yes, unlimited seats on business plans.</p>
                        </div>
                    </div>
                </details>
            </div>
        </div>
    </div>
</section>

CSS

* {
    margin: 0;
    box-sizing: border-box;
}
body {
    font-family: "DM Sans", sans-serif;
}
.faq-section {
    padding: 7rem 5%;
    background-color: #b0e0e6;
}
.faq-section .faq-header {
    display: grid;
    grid-template-columns: 1.5fr 1fr;
    gap: 10rem;
    align-items: end;
}
@media (max-width: 600px) {
    .faq-section .faq-header {
        grid-template-columns: 1fr;
        gap: 1.5rem;
    }
}
.faq-section .section-label {
    font-size: .75rem;
    line-height: 16.5px;
    letter-spacing: 1.65px;
    text-transform: uppercase;
    color: hsl(0, 0%, 30%);
}
.faq-section .faq-header-left h2 {
    font-family: "Unbounded", sans-serif;
    font-weight: 300;
    font-size: clamp(2rem, calc(2vw + 1rem), 3.75rem);
    line-height: 1.1;
    letter-spacing: -1.22px;
    text-transform: capitalize;
    margin-top: .75rem;
}
.faq-section .faq-header-right {
    font-size: 1rem;
    line-height: 1.5;
    color: hsl(0, 0%, 50%);
}
.faq-section .faq-header-right a {
    color: #000;
    text-underline-offset: .1rem;
}
.faq-section .faq-content-wrapper {
    margin-top: 4rem;
    display: grid;
    grid-template-columns: 1fr 3fr;
}
@media (max-width: 600px) {
    .faq-section .faq-content-wrapper {
        margin-top: 2.5rem;
        grid-template-columns: 1fr;
    }
}
.faq-section .faq-categories {
    list-style: none;
    padding: 0;
    margin: 0;
    font-size: 1rem;
    display: inline-block;
}
@media (max-width: 600px) {
    .faq-section .faq-content-left {
        margin-bottom: 20px;
        overflow: hidden;
    }
    .faq-section .faq-categories {
        display: flex;
        gap: .5rem;
        overflow-x: auto;
    }
}
.faq-section .faq-categories li {
    padding: .5rem 1rem;
    margin-bottom: .5rem;
    border-radius: .25rem;
    letter-spacing: .5px;
    color: hsl(0, 0%, 30%);
    cursor: pointer;
    transition: background 0.15s, color 0.15s;
}
.faq-section .faq-categories li.active {
    background-color: hsl(0, 0%, 97%);
    color: #000;
}
@media (max-width: 600px) {
    .faq-section .faq-categories li {
        white-space: nowrap;
    }
}
.faq-section .faq-category {
    display: none;
}
.faq-section .faq-category.active {
    display: block;
}
.faq-section .faq-content-right details {
    padding: 0 1rem;
    border-radius: .5rem;
    background: hsl(0, 0%, 97%);
    margin-bottom: 1rem;
}
.faq-section .faq-content-right summary {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 1.25rem 0;
    cursor: pointer;
    list-style: none;
    font-size: 1.063rem;
    flex-wrap: nowrap;
}
.faq-section .faq-content-right summary::-webkit-details-marker {
    display: none;
}
.faq-section .faq-content-right summary > span:first-child {
    color: hsl(0, 0%, 50%);
    font-size: .75rem;
    min-width: 1rem;
}
@media (max-width: 600px) {
    .faq-section .faq-content-right summary > span:first-child {
        display: none;
    }
}
.faq-section .icon {
    width: 1.5rem;
    height: 1.5rem;
    border: 1px solid hsl(0, 0%, 70%);
    border-radius: 50%;
    position: relative;
    flex-shrink: 0;
    margin-left: auto;
    transition: border-color 0.2s, transform 0.25s;
}
.faq-section .icon::before,
.faq-section .icon::after {
    content: '';
    position: absolute;
    background: hsl(0, 0%, 30%);
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}
.faq-section .icon::before {
    width: 8px;
    height: 1px;
}
.faq-section .icon::after {
    width: 1px;
    height: 8px;
}
.faq-section details[open] .icon {
    transform: rotate(135deg);
    border-color: hsl(0, 0%, 30%);
}
.faq-section .faq-content {
    padding-left: 2.5rem;
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows 0.25s ease;
}
@media (max-width: 600px) {
    .faq-section .faq-content {
        padding-left: 0;
    }
}
.faq-section .faq-content > div {
    overflow: hidden;
}
.faq-section .faq-content p {
    margin: 0 0 1.25rem;
    color: #6b6862;
    font-size: 1rem;
    line-height: 1.65;
}

JS:

document.addEventListener("DOMContentLoaded", () => {

    function closeDetail(el, content) {
        if (!el.open) return;
        content.style.gridTemplateRows = '1fr';
        requestAnimationFrame(() => requestAnimationFrame(() => {
            content.style.gridTemplateRows = '0fr';
        }));
        content.addEventListener('transitionend', function handler(e) {
            if (e.propertyName !== 'grid-template-rows') return;
            el.open = false;
            content.removeEventListener('transitionend', handler);
        });
    }

    function openDetail(el, content) {
        el.open = true;
        content.style.gridTemplateRows = '0fr';
        requestAnimationFrame(() => requestAnimationFrame(() => {
            content.style.gridTemplateRows = '1fr';
        }));
    }

    document.querySelectorAll('details').forEach(el => {
        const content = el.querySelector('.faq-content');
        el.querySelector('summary').addEventListener('click', e => {
            e.preventDefault();
            if (el.open) {
                closeDetail(el, content);
            } else {
                document.querySelectorAll('details[open]').forEach(other => {
                    if (other !== el) closeDetail(other, other.querySelector('.faq-content'));
                });
                openDetail(el, content);
            }
        });
    });

    const tabs = document.querySelectorAll('.faq-categories li');
    const panels = document.querySelectorAll('.faq-category');

    tabs.forEach(tab => {
        tab.addEventListener('click', () => {
            const target = tab.dataset.category;

            tabs.forEach(t => t.classList.remove('active'));
            tab.classList.add('active');

            document.querySelectorAll('details[open]').forEach(el => {
                closeDetail(el, el.querySelector('.faq-content'));
            });

            panels.forEach(panel => {
                panel.classList.toggle('active', panel.dataset.category === target);
            });
        });
    });
});

If you have any doubts or stuck somewhere, you can reach out through Coding Yaar's Discord server.

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Most Voted
Newest Oldest
0
Would love your thoughts, please comment.x
()
x