Interactive FAQ Accordion
A modern and accessible FAQ accordion component with smooth animations, search functionality, and category filtering
Responsive Design
Yes
Dark Mode Support
No
lines
1189
Browser Compatibility
No
Live Preview
Interact with the component without leaving the page.
Interactive FAQ Accordion
A comprehensive FAQ accordion component featuring smooth animations, search functionality, category filtering, and full accessibility support. Perfect for help pages, support sections, and knowledge bases.
Features
- Smooth Animations: CSS-based accordion animations with easing
- Search Functionality: Real-time search through questions and answers
- Category Filtering: Organize FAQs by categories with filter buttons
- Accessibility: Full keyboard navigation and screen reader support
- Responsive Design: Mobile-first approach with touch-friendly interactions
- Auto-collapse: Option to close other items when opening a new one
- Highlight Search: Search terms are highlighted in results
- Loading States: Smooth loading animations for dynamic content
- Print Friendly: Optimized styles for printing
HTML
<section class="faq-section">
<div class="container">
<!-- Header -->
<div class="faq-header">
<h2 class="faq-title">Frequently Asked Questions</h2>
<p class="faq-subtitle">Find answers to common questions about our products and services</p>
</div>
<!-- Search and Filter Controls -->
<div class="faq-controls">
<!-- Search Bar -->
<div class="search-container">
<div class="search-input-wrapper">
<svg class="search-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor">
<circle cx="11" cy="11" r="8"></circle>
<path d="m21 21-4.35-4.35"></path>
</svg>
<input
type="text"
id="faqSearch"
class="search-input"
placeholder="Search questions..."
aria-label="Search FAQ questions"
>
<button class="search-clear" id="searchClear" aria-label="Clear search">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
</div>
</div>
<!-- Category Filter -->
<div class="filter-container">
<div class="filter-buttons" role="tablist" aria-label="FAQ Categories">
<button class="filter-btn active" data-category="all" role="tab" aria-selected="true">
All Questions
</button>
<button class="filter-btn" data-category="general" role="tab" aria-selected="false">
General
</button>
<button class="filter-btn" data-category="billing" role="tab" aria-selected="false">
Billing
</button>
<button class="filter-btn" data-category="technical" role="tab" aria-selected="false">
Technical
</button>
<button class="filter-btn" data-category="account" role="tab" aria-selected="false">
Account
</button>
</div>
</div>
</div>
<!-- FAQ Results Info -->
<div class="faq-results" id="faqResults">
<span class="results-count">Showing <strong>12</strong> questions</span>
</div>
<!-- FAQ Accordion -->
<div class="faq-accordion" id="faqAccordion">
<!-- General Questions -->
<div class="faq-item" data-category="general">
<button class="faq-question" aria-expanded="false" aria-controls="faq-1">
<span class="question-text">What is your company about?</span>
<span class="question-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<polyline points="6,9 12,15 18,9"></polyline>
</svg>
</span>
</button>
<div class="faq-answer" id="faq-1" aria-hidden="true">
<div class="answer-content">
<p>We are a technology company focused on creating innovative solutions that help businesses grow and succeed in the digital age. Our team of experts works tirelessly to develop cutting-edge products and services.</p>
<p>Founded in 2019, we have grown from a small startup to a leading provider of digital solutions, serving thousands of customers worldwide.</p>
</div>
</div>
</div>
<div class="faq-item" data-category="general">
<button class="faq-question" aria-expanded="false" aria-controls="faq-2">
<span class="question-text">How long have you been in business?</span>
<span class="question-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<polyline points="6,9 12,15 18,9"></polyline>
</svg>
</span>
</button>
<div class="faq-answer" id="faq-2" aria-hidden="true">
<div class="answer-content">
<p>We have been in business since 2019, which means we have over 5 years of experience in the industry. During this time, we have:</p>
<ul>
<li>Served over 10,000 customers</li>
<li>Launched 15+ successful products</li>
<li>Expanded to 25 countries</li>
<li>Built a team of 100+ professionals</li>
</ul>
</div>
</div>
</div>
<!-- Billing Questions -->
<div class="faq-item" data-category="billing">
<button class="faq-question" aria-expanded="false" aria-controls="faq-3">
<span class="question-text">What payment methods do you accept?</span>
<span class="question-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<polyline points="6,9 12,15 18,9"></polyline>
</svg>
</span>
</button>
<div class="faq-answer" id="faq-3" aria-hidden="true">
<div class="answer-content">
<p>We accept all major payment methods to make it convenient for our customers:</p>
<ul>
<li><strong>Credit Cards:</strong> Visa, MasterCard, American Express, Discover</li>
<li><strong>Digital Wallets:</strong> PayPal, Apple Pay, Google Pay</li>
<li><strong>Bank Transfers:</strong> ACH, Wire transfers</li>
<li><strong>Cryptocurrency:</strong> Bitcoin, Ethereum (for enterprise plans)</li>
</ul>
<p>All payments are processed securely using industry-standard encryption.</p>
</div>
</div>
</div>
<div class="faq-item" data-category="billing">
<button class="faq-question" aria-expanded="false" aria-controls="faq-4">
<span class="question-text">Can I get a refund?</span>
<span class="question-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<polyline points="6,9 12,15 18,9"></polyline>
</svg>
</span>
</button>
<div class="faq-answer" id="faq-4" aria-hidden="true">
<div class="answer-content">
<p>Yes, we offer a 30-day money-back guarantee for all our services. If you're not completely satisfied, you can request a full refund within 30 days of your purchase.</p>
<p><strong>Refund Process:</strong></p>
<ol>
<li>Contact our support team</li>
<li>Provide your order number</li>
<li>Explain the reason for refund</li>
<li>Receive confirmation within 24 hours</li>
<li>Refund processed within 5-7 business days</li>
</ol>
</div>
</div>
</div>
<!-- Technical Questions -->
<div class="faq-item" data-category="technical">
<button class="faq-question" aria-expanded="false" aria-controls="faq-5">
<span class="question-text">What are the system requirements?</span>
<span class="question-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<polyline points="6,9 12,15 18,9"></polyline>
</svg>
</span>
</button>
<div class="faq-answer" id="faq-5" aria-hidden="true">
<div class="answer-content">
<p>Our platform is designed to work on all modern devices and browsers:</p>
<div class="requirements-grid">
<div class="requirement-item">
<h4>Desktop Browsers</h4>
<ul>
<li>Chrome 80+</li>
<li>Firefox 75+</li>
<li>Safari 13+</li>
<li>Edge 80+</li>
</ul>
</div>
<div class="requirement-item">
<h4>Mobile Devices</h4>
<ul>
<li>iOS 13+ (Safari)</li>
<li>Android 8+ (Chrome)</li>
<li>Responsive design</li>
<li>Touch optimized</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<div class="faq-item" data-category="technical">
<button class="faq-question" aria-expanded="false" aria-controls="faq-6">
<span class="question-text">Do you provide API access?</span>
<span class="question-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<polyline points="6,9 12,15 18,9"></polyline>
</svg>
</span>
</button>
<div class="faq-answer" id="faq-6" aria-hidden="true">
<div class="answer-content">
<p>Yes, we provide comprehensive API access for developers and businesses who want to integrate our services:</p>
<ul>
<li><strong>REST API:</strong> Full CRUD operations with JSON responses</li>
<li><strong>GraphQL:</strong> Flexible queries for advanced use cases</li>
<li><strong>Webhooks:</strong> Real-time notifications for events</li>
<li><strong>SDKs:</strong> Available for Python, JavaScript, PHP, and more</li>
</ul>
<p>API documentation and interactive testing tools are available in our developer portal.</p>
</div>
</div>
</div>
<!-- Account Questions -->
<div class="faq-item" data-category="account">
<button class="faq-question" aria-expanded="false" aria-controls="faq-7">
<span class="question-text">How do I reset my password?</span>
<span class="question-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<polyline points="6,9 12,15 18,9"></polyline>
</svg>
</span>
</button>
<div class="faq-answer" id="faq-7" aria-hidden="true">
<div class="answer-content">
<p>You can reset your password easily through our secure password reset process:</p>
<ol>
<li>Go to the login page</li>
<li>Click "Forgot Password?"</li>
<li>Enter your email address</li>
<li>Check your email for reset instructions</li>
<li>Follow the link and create a new password</li>
</ol>
<p><strong>Security Note:</strong> Reset links expire after 1 hour for security purposes.</p>
</div>
</div>
</div>
<div class="faq-item" data-category="account">
<button class="faq-question" aria-expanded="false" aria-controls="faq-8">
<span class="question-text">Can I change my email address?</span>
<span class="question-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<polyline points="6,9 12,15 18,9"></polyline>
</svg>
</span>
</button>
<div class="faq-answer" id="faq-8" aria-hidden="true">
<div class="answer-content">
<p>Yes, you can change your email address from your account settings:</p>
<ol>
<li>Log in to your account</li>
<li>Go to Account Settings</li>
<li>Click on "Change Email"</li>
<li>Enter your new email address</li>
<li>Verify the new email through the confirmation link</li>
</ol>
<p>Your old email will remain active until you confirm the new one.</p>
</div>
</div>
</div>
<!-- More General Questions -->
<div class="faq-item" data-category="general">
<button class="faq-question" aria-expanded="false" aria-controls="faq-9">
<span class="question-text">Do you offer customer support?</span>
<span class="question-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<polyline points="6,9 12,15 18,9"></polyline>
</svg>
</span>
</button>
<div class="faq-answer" id="faq-9" aria-hidden="true">
<div class="answer-content">
<p>Absolutely! We provide comprehensive customer support through multiple channels:</p>
<ul>
<li><strong>24/7 Live Chat:</strong> Instant help from our support team</li>
<li><strong>Email Support:</strong> Detailed responses within 4 hours</li>
<li><strong>Phone Support:</strong> Direct line for urgent issues</li>
<li><strong>Knowledge Base:</strong> Self-service articles and tutorials</li>
<li><strong>Community Forum:</strong> Connect with other users</li>
</ul>
</div>
</div>
</div>
<div class="faq-item" data-category="technical">
<button class="faq-question" aria-expanded="false" aria-controls="faq-10">
<span class="question-text">Is my data secure?</span>
<span class="question-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<polyline points="6,9 12,15 18,9"></polyline>
</svg>
</span>
</button>
<div class="faq-answer" id="faq-10" aria-hidden="true">
<div class="answer-content">
<p>Data security is our top priority. We implement multiple layers of protection:</p>
<ul>
<li><strong>Encryption:</strong> AES-256 encryption for data at rest and in transit</li>
<li><strong>Compliance:</strong> SOC 2 Type II, GDPR, and HIPAA compliant</li>
<li><strong>Access Control:</strong> Multi-factor authentication and role-based permissions</li>
<li><strong>Monitoring:</strong> 24/7 security monitoring and threat detection</li>
<li><strong>Backups:</strong> Automated daily backups with 99.9% uptime guarantee</li>
</ul>
</div>
</div>
</div>
<div class="faq-item" data-category="billing">
<button class="faq-question" aria-expanded="false" aria-controls="faq-11">
<span class="question-text">Can I upgrade or downgrade my plan?</span>
<span class="question-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<polyline points="6,9 12,15 18,9"></polyline>
</svg>
</span>
</button>
<div class="faq-answer" id="faq-11" aria-hidden="true">
<div class="answer-content">
<p>Yes, you can change your plan at any time. Here's how it works:</p>
<div class="plan-changes">
<div class="change-type">
<h4>Upgrading</h4>
<ul>
<li>Immediate access to new features</li>
<li>Prorated billing for the current period</li>
<li>No service interruption</li>
</ul>
</div>
<div class="change-type">
<h4>Downgrading</h4>
<ul>
<li>Changes take effect at next billing cycle</li>
<li>Data export available before downgrade</li>
<li>Credit applied to future bills</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<div class="faq-item" data-category="account">
<button class="faq-question" aria-expanded="false" aria-controls="faq-12">
<span class="question-text">How do I delete my account?</span>
<span class="question-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<polyline points="6,9 12,15 18,9"></polyline>
</svg>
</span>
</button>
<div class="faq-answer" id="faq-12" aria-hidden="true">
<div class="answer-content">
<p>We're sorry to see you go! You can delete your account through the following process:</p>
<ol>
<li>Log in to your account</li>
<li>Go to Account Settings</li>
<li>Scroll to "Danger Zone"</li>
<li>Click "Delete Account"</li>
<li>Confirm deletion via email</li>
</ol>
<p><strong>Important:</strong> This action is irreversible. All your data will be permanently deleted within 30 days.</p>
</div>
</div>
</div>
</div>
<!-- No Results Message -->
<div class="no-results" id="noResults" style="display: none;">
<div class="no-results-content">
<svg class="no-results-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor">
<circle cx="11" cy="11" r="8"></circle>
<path d="m21 21-4.35-4.35"></path>
</svg>
<h3>No questions found</h3>
<p>Try adjusting your search terms or browse different categories.</p>
<button class="reset-search-btn" onclick="resetSearch()">Clear Search</button>
</div>
</div>
<!-- Contact Support -->
<div class="faq-footer">
<div class="support-cta">
<h3>Still have questions?</h3>
<p>Can't find what you're looking for? Our support team is here to help.</p>
<div class="support-buttons">
<a href="#" class="support-btn primary">Contact Support</a>
<a href="#" class="support-btn secondary">Live Chat</a>
</div>
</div>
</div>
</div>
</section>CSS
.faq-section {
padding: 80px 0;
background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
min-height: 100vh;
}
.container {
max-width: 1000px;
margin: 0 auto;
padding: 0 20px;
}
/* Header */
.faq-header {
text-align: center;
margin-bottom: 60px;
}
.faq-title {
font-size: 3rem;
font-weight: 700;
color: #1a202c;
margin-bottom: 16px;
background: linear-gradient(45deg, #4f46e5, #7c3aed);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.faq-subtitle {
font-size: 1.25rem;
color: #4a5568;
max-width: 600px;
margin: 0 auto;
line-height: 1.6;
}
/* Controls */
.faq-controls {
margin-bottom: 40px;
}
.search-container {
margin-bottom: 30px;
}
.search-input-wrapper {
position: relative;
max-width: 500px;
margin: 0 auto;
}
.search-icon {
position: absolute;
left: 16px;
top: 50%;
transform: translateY(-50%);
width: 20px;
height: 20px;
color: #9ca3af;
pointer-events: none;
}
.search-input {
width: 100%;
padding: 16px 50px 16px 50px;
border: 2px solid #e5e7eb;
border-radius: 12px;
font-size: 1rem;
background: white;
transition: all 0.2s ease;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.search-input:focus {
outline: none;
border-color: #4f46e5;
box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1);
}
.search-clear {
position: absolute;
right: 16px;
top: 50%;
transform: translateY(-50%);
background: none;
border: none;
width: 20px;
height: 20px;
color: #9ca3af;
cursor: pointer;
opacity: 0;
transition: opacity 0.2s ease;
}
.search-clear.visible {
opacity: 1;
}
.search-clear:hover {
color: #6b7280;
}
/* Filter Buttons */
.filter-container {
display: flex;
justify-content: center;
margin-bottom: 20px;
}
.filter-buttons {
display: flex;
gap: 8px;
background: white;
padding: 6px;
border-radius: 12px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
overflow-x: auto;
}
.filter-btn {
padding: 12px 20px;
border: none;
border-radius: 8px;
font-size: 0.875rem;
font-weight: 500;
cursor: pointer;
transition: all 0.2s ease;
white-space: nowrap;
color: #6b7280;
background: transparent;
}
.filter-btn:hover {
background: #f3f4f6;
color: #374151;
}
.filter-btn.active {
background: #4f46e5;
color: white;
box-shadow: 0 2px 4px rgba(79, 70, 229, 0.2);
}
/* Results Info */
.faq-results {
margin-bottom: 30px;
text-align: center;
}
.results-count {
color: #6b7280;
font-size: 0.875rem;
}
/* FAQ Accordion */
.faq-accordion {
space-y: 16px;
}
.faq-item {
background: white;
border-radius: 12px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
overflow: hidden;
transition: all 0.2s ease;
margin-bottom: 16px;
}
.faq-item:hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.faq-question {
width: 100%;
padding: 24px;
border: none;
background: none;
text-align: left;
cursor: pointer;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 1.125rem;
font-weight: 600;
color: #1a202c;
transition: all 0.2s ease;
}
.faq-question:hover {
background: #f8fafc;
}
.faq-question[aria-expanded="true"] {
background: #f0f9ff;
border-bottom: 1px solid #e0f2fe;
}
.question-text {
flex: 1;
margin-right: 16px;
}
.question-icon {
width: 24px;
height: 24px;
color: #6b7280;
transition: transform 0.2s ease;
flex-shrink: 0;
}
.faq-question[aria-expanded="true"] .question-icon {
transform: rotate(180deg);
color: #0ea5e9;
}
.faq-answer {
max-height: 0;
overflow: hidden;
transition: max-height 0.3s ease;
}
.faq-answer.open {
max-height: 1000px;
}
.answer-content {
padding: 0 24px 24px;
color: #4a5568;
line-height: 1.6;
}
.answer-content p {
margin-bottom: 16px;
}
.answer-content p:last-child {
margin-bottom: 0;
}
.answer-content ul,
.answer-content ol {
margin: 16px 0;
padding-left: 20px;
}
.answer-content li {
margin-bottom: 8px;
}
.answer-content strong {
color: #2d3748;
font-weight: 600;
}
/* Special Content Layouts */
.requirements-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
margin: 20px 0;
}
.requirement-item h4 {
color: #2d3748;
font-weight: 600;
margin-bottom: 12px;
font-size: 1rem;
}
.plan-changes {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
margin: 20px 0;
}
.change-type h4 {
color: #2d3748;
font-weight: 600;
margin-bottom: 12px;
font-size: 1rem;
}
/* Search Highlighting */
.highlight {
background: #fef3c7;
padding: 2px 4px;
border-radius: 3px;
font-weight: 600;
}
/* Hidden Items */
.faq-item.hidden {
display: none;
}
/* No Results */
.no-results {
text-align: center;
padding: 60px 20px;
}
.no-results-content {
max-width: 400px;
margin: 0 auto;
}
.no-results-icon {
width: 64px;
height: 64px;
color: #9ca3af;
margin: 0 auto 20px;
}
.no-results h3 {
font-size: 1.5rem;
font-weight: 600;
color: #374151;
margin-bottom: 12px;
}
.no-results p {
color: #6b7280;
margin-bottom: 24px;
}
.reset-search-btn {
background: #4f46e5;
color: white;
border: none;
padding: 12px 24px;
border-radius: 8px;
font-weight: 500;
cursor: pointer;
transition: background 0.2s ease;
}
.reset-search-btn:hover {
background: #4338ca;
}
/* Footer */
.faq-footer {
margin-top: 80px;
text-align: center;
}
.support-cta {
background: white;
padding: 40px;
border-radius: 16px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.support-cta h3 {
font-size: 1.5rem;
font-weight: 600;
color: #1a202c;
margin-bottom: 12px;
}
.support-cta p {
color: #6b7280;
margin-bottom: 24px;
}
.support-buttons {
display: flex;
gap: 12px;
justify-content: center;
flex-wrap: wrap;
}
.support-btn {
padding: 12px 24px;
border-radius: 8px;
font-weight: 500;
text-decoration: none;
transition: all 0.2s ease;
display: inline-block;
}
.support-btn.primary {
background: #4f46e5;
color: white;
}
.support-btn.primary:hover {
background: #4338ca;
transform: translateY(-1px);
}
.support-btn.secondary {
background: #f3f4f6;
color: #374151;
border: 1px solid #d1d5db;
}
.support-btn.secondary:hover {
background: #e5e7eb;
}
/* Responsive Design */
@media (max-width: 768px) {
.faq-title {
font-size: 2.25rem;
}
.faq-question {
padding: 20px;
font-size: 1rem;
}
.answer-content {
padding: 0 20px 20px;
}
.filter-buttons {
justify-content: flex-start;
}
.support-buttons {
flex-direction: column;
align-items: center;
}
.support-btn {
width: 100%;
max-width: 200px;
}
}
@media (max-width: 480px) {
.faq-section {
padding: 40px 0;
}
.faq-title {
font-size: 1.875rem;
}
.search-input {
padding: 14px 45px 14px 45px;
}
.faq-question {
padding: 16px;
}
.answer-content {
padding: 0 16px 16px;
}
}
/* Print Styles */
@media print {
.faq-controls,
.faq-footer {
display: none;
}
.faq-item {
break-inside: avoid;
box-shadow: none;
border: 1px solid #e5e7eb;
}
.faq-answer {
max-height: none !important;
}
.question-icon {
display: none;
}
}JavaScript
// FAQ Accordion Controller
class FAQController {
constructor() {
this.faqItems = document.querySelectorAll('.faq-item');
this.searchInput = document.getElementById('faqSearch');
this.searchClear = document.getElementById('searchClear');
this.filterButtons = document.querySelectorAll('.filter-btn');
this.resultsElement = document.getElementById('faqResults');
this.noResultsElement = document.getElementById('noResults');
this.accordion = document.getElementById('faqAccordion');
this.currentFilter = 'all';
this.searchTerm = '';
this.autoCollapse = true; // Set to false to allow multiple open items
this.init();
}
init() {
this.setupEventListeners();
this.updateResults();
this.setupKeyboardNavigation();
}
setupEventListeners() {
// Search functionality
this.searchInput.addEventListener('input', (e) => {
this.searchTerm = e.target.value.toLowerCase();
this.updateSearchClear();
this.filterFAQs();
});
this.searchClear.addEventListener('click', () => {
this.clearSearch();
});
// Filter buttons
this.filterButtons.forEach(button => {
button.addEventListener('click', (e) => {
this.setActiveFilter(e.target.dataset.category);
});
});
// FAQ accordion
this.faqItems.forEach((item, index) => {
const question = item.querySelector('.faq-question');
const answer = item.querySelector('.faq-answer');
question.addEventListener('click', () => {
this.toggleFAQ(item, index);
});
});
}
setupKeyboardNavigation() {
// Allow keyboard navigation through filter buttons
this.filterButtons.forEach((button, index) => {
button.addEventListener('keydown', (e) => {
if (e.key === 'ArrowLeft' && index > 0) {
this.filterButtons[index - 1].focus();
} else if (e.key === 'ArrowRight' && index < this.filterButtons.length - 1) {
this.filterButtons[index + 1].focus();
}
});
});
// Search input keyboard shortcuts
this.searchInput.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
this.clearSearch();
}
});
}
toggleFAQ(item, index) {
const question = item.querySelector('.faq-question');
const answer = item.querySelector('.faq-answer');
const isOpen = question.getAttribute('aria-expanded') === 'true';
if (this.autoCollapse && !isOpen) {
// Close all other FAQs
this.faqItems.forEach(otherItem => {
if (otherItem !== item) {
this.closeFAQ(otherItem);
}
});
}
if (isOpen) {
this.closeFAQ(item);
} else {
this.openFAQ(item);
}
// Analytics tracking (optional)
this.trackFAQInteraction(item, !isOpen);
}
openFAQ(item) {
const question = item.querySelector('.faq-question');
const answer = item.querySelector('.faq-answer');
question.setAttribute('aria-expanded', 'true');
answer.setAttribute('aria-hidden', 'false');
answer.classList.add('open');
// Smooth scroll to question if it's not fully visible
setTimeout(() => {
const rect = question.getBoundingClientRect();
if (rect.top < 100) {
question.scrollIntoView({
behavior: 'smooth',
block: 'start',
inline: 'nearest'
});
}
}, 300);
}
closeFAQ(item) {
const question = item.querySelector('.faq-question');
const answer = item.querySelector('.faq-answer');
question.setAttribute('aria-expanded', 'false');
answer.setAttribute('aria-hidden', 'true');
answer.classList.remove('open');
}
setActiveFilter(category) {
this.currentFilter = category;
// Update button states
this.filterButtons.forEach(button => {
const isActive = button.dataset.category === category;
button.classList.toggle('active', isActive);
button.setAttribute('aria-selected', isActive);
});
this.filterFAQs();
}
filterFAQs() {
let visibleCount = 0;
this.faqItems.forEach(item => {
const category = item.dataset.category;
const questionText = item.querySelector('.question-text').textContent.toLowerCase();
const answerText = item.querySelector('.answer-content').textContent.toLowerCase();
const matchesFilter = this.currentFilter === 'all' || category === this.currentFilter;
const matchesSearch = this.searchTerm === '' ||
questionText.includes(this.searchTerm) ||
answerText.includes(this.searchTerm);
const isVisible = matchesFilter && matchesSearch;
item.classList.toggle('hidden', !isVisible);
if (isVisible) {
visibleCount++;
this.highlightSearchTerms(item);
}
});
this.updateResults(visibleCount);
this.toggleNoResults(visibleCount === 0);
}
highlightSearchTerms(item) {
if (!this.searchTerm) return;
const questionText = item.querySelector('.question-text');
const answerContent = item.querySelector('.answer-content');
[questionText, answerContent].forEach(element => {
const originalText = element.textContent;
const regex = new RegExp(`(${this.escapeRegex(this.searchTerm)})`, 'gi');
const highlightedText = originalText.replace(regex, '<span class="highlight">$1</span>');
if (highlightedText !== originalText) {
element.innerHTML = highlightedText;
}
});
}
escapeRegex(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
updateResults(count = null) {
if (count === null) {
count = this.faqItems.length;
}
const countElement = this.resultsElement.querySelector('.results-count');
const questionText = count === 1 ? 'question' : 'questions';
countElement.innerHTML = `Showing <strong>${count}</strong> ${questionText}`;
}
toggleNoResults(show) {
this.noResultsElement.style.display = show ? 'block' : 'none';
this.accordion.style.display = show ? 'none' : 'block';
}
updateSearchClear() {
this.searchClear.classList.toggle('visible', this.searchInput.value.length > 0);
}
clearSearch() {
this.searchInput.value = '';
this.searchTerm = '';
this.updateSearchClear();
this.filterFAQs();
this.searchInput.focus();
}
trackFAQInteraction(item, isOpening) {
// Optional: Send analytics data
const questionText = item.querySelector('.question-text').textContent;
const category = item.dataset.category;
// Example: Google Analytics 4
if (typeof gtag !== 'undefined') {
gtag('event', 'faq_interaction', {
'event_category': 'FAQ',
'event_label': questionText,
'custom_parameter_1': category,
'custom_parameter_2': isOpening ? 'open' : 'close'
});
}
console.log(`FAQ ${isOpening ? 'opened' : 'closed'}: ${questionText}`);
}
// Public methods for external control
openFAQByIndex(index) {
if (this.faqItems[index]) {
this.openFAQ(this.faqItems[index]);
}
}
searchFAQs(term) {
this.searchInput.value = term;
this.searchTerm = term.toLowerCase();
this.updateSearchClear();
this.filterFAQs();
}
filterByCategory(category) {
const button = document.querySelector(`[data-category="${category}"]`);
if (button) {
this.setActiveFilter(category);
}
}
}
// Global functions for external use
function resetSearch() {
if (window.faqController) {
window.faqController.clearSearch();
window.faqController.setActiveFilter('all');
}
}
function openFAQ(index) {
if (window.faqController) {
window.faqController.openFAQByIndex(index);
}
}
function searchFAQs(term) {
if (window.faqController) {
window.faqController.searchFAQs(term);
}
}
// Initialize when DOM is loaded
document.addEventListener('DOMContentLoaded', () => {
window.faqController = new FAQController();
// Optional: Auto-open FAQ from URL hash
const hash = window.location.hash;
if (hash && hash.startsWith('#faq-')) {
const index = parseInt(hash.replace('#faq-', '')) - 1;
if (index >= 0) {
setTimeout(() => {
window.faqController.openFAQByIndex(index);
}, 100);
}
}
});
// Optional: Update URL hash when FAQ is opened
document.addEventListener('click', (e) => {
if (e.target.classList.contains('faq-question')) {
const faqItem = e.target.closest('.faq-item');
const index = Array.from(document.querySelectorAll('.faq-item')).indexOf(faqItem) + 1;
if (e.target.getAttribute('aria-expanded') === 'false') {
history.replaceState(null, null, `#faq-${index}`);
} else {
history.replaceState(null, null, window.location.pathname);
}
}
});Customization Options
Content
- Questions & Answers: Modify the FAQ items in the HTML
- Categories: Add or change category filters
- Support Links: Update contact and support URLs
- Branding: Customize colors and typography
Functionality
- Auto-collapse: Set
autoCollapsetofalseto allow multiple open items - Search Scope: Modify search to include/exclude certain content
- Analytics: Add tracking for FAQ interactions
- URL Routing: Enable deep linking to specific FAQs
Styling
- Color Scheme: Update CSS custom properties for consistent theming
- Animation Speed: Adjust transition durations
- Layout: Modify grid layouts for different screen sizes
- Icons: Replace SVG icons with your preferred icon set
Accessibility Features
- ARIA Labels: Proper labeling for screen readers
- Keyboard Navigation: Full keyboard support
- Focus Management: Logical tab order and focus indicators
- Screen Reader Support: Descriptive text and state announcements
- High Contrast: Sufficient color contrast ratios
Browser Compatibility
- ✅ Chrome 60+
- ✅ Firefox 55+
- ✅ Safari 12+
- ✅ Edge 79+
- ⚠️ IE 11 (with polyfills)
Performance Notes
- Efficient DOM manipulation with minimal reflows
- CSS-based animations for smooth 60fps performance
- Debounced search for optimal performance
- Lazy loading support for large FAQ lists
- Print-optimized styles
HTML
391
lines
CSS
476
lines
JavaScript
322
lines
<section class="faq-section">
<div class="container">
<!-- Header -->
<div class="faq-header">
<h2 class="faq-title">Frequently Asked Questions</h2>
<p class="faq-subtitle">Find answers to common questions about our products and services</p>
</div>
<!-- Search and Filter Controls -->
<div class="faq-controls">
<!-- Search Bar -->
<div class="search-container">
<div class="search-input-wrapper">
<svg class="search-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor">
<circle cx="11" cy="11" r="8"></circle>
<path d="m21 21-4.35-4.35"></path>
</svg>
<input
type="text"
id="faqSearch"
class="search-input"
placeholder="Search questions..."
aria-label="Search FAQ questions"
>
<button class="search-clear" id="searchClear" aria-label="Clear search">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
</div>
</div>
<!-- Category Filter -->
<div class="filter-container">
<div class="filter-buttons" role="tablist" aria-label="FAQ Categories">
<button class="filter-btn active" data-category="all" role="tab" aria-selected="true">
All Questions
</button>
<button class="filter-btn" data-category="general" role="tab" aria-selected="false">
General
</button>
<button class="filter-btn" data-category="billing" role="tab" aria-selected="false">
Billing
</button>
<button class="filter-btn" data-category="technical" role="tab" aria-selected="false">
Technical
</button>
<button class="filter-btn" data-category="account" role="tab" aria-selected="false">
Account
</button>
</div>
</div>
</div>
<!-- FAQ Results Info -->
<div class="faq-results" id="faqResults">
<span class="results-count">Showing <strong>12</strong> questions</span>
</div>
<!-- FAQ Accordion -->
<div class="faq-accordion" id="faqAccordion">
<!-- General Questions -->
<div class="faq-item" data-category="general">
<button class="faq-question" aria-expanded="false" aria-controls="faq-1">
<span class="question-text">What is your company about?</span>
<span class="question-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<polyline points="6,9 12,15 18,9"></polyline>
</svg>
</span>
</button>
<div class="faq-answer" id="faq-1" aria-hidden="true">
<div class="answer-content">
<p>We are a technology company focused on creating innovative solutions that help businesses grow and succeed in the digital age. Our team of experts works tirelessly to develop cutting-edge products and services.</p>
<p>Founded in 2019, we have grown from a small startup to a leading provider of digital solutions, serving thousands of customers worldwide.</p>
</div>
</div>
</div>
<div class="faq-item" data-category="general">
<button class="faq-question" aria-expanded="false" aria-controls="faq-2">
<span class="question-text">How long have you been in business?</span>
<span class="question-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<polyline points="6,9 12,15 18,9"></polyline>
</svg>
</span>
</button>
<div class="faq-answer" id="faq-2" aria-hidden="true">
<div class="answer-content">
<p>We have been in business since 2019, which means we have over 5 years of experience in the industry. During this time, we have:</p>
<ul>
<li>Served over 10,000 customers</li>
<li>Launched 15+ successful products</li>
<li>Expanded to 25 countries</li>
<li>Built a team of 100+ professionals</li>
</ul>
</div>
</div>
</div>
<!-- Billing Questions -->
<div class="faq-item" data-category="billing">
<button class="faq-question" aria-expanded="false" aria-controls="faq-3">
<span class="question-text">What payment methods do you accept?</span>
<span class="question-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<polyline points="6,9 12,15 18,9"></polyline>
</svg>
</span>
</button>
<div class="faq-answer" id="faq-3" aria-hidden="true">
<div class="answer-content">
<p>We accept all major payment methods to make it convenient for our customers:</p>
<ul>
<li><strong>Credit Cards:</strong> Visa, MasterCard, American Express, Discover</li>
<li><strong>Digital Wallets:</strong> PayPal, Apple Pay, Google Pay</li>
<li><strong>Bank Transfers:</strong> ACH, Wire transfers</li>
<li><strong>Cryptocurrency:</strong> Bitcoin, Ethereum (for enterprise plans)</li>
</ul>
<p>All payments are processed securely using industry-standard encryption.</p>
</div>
</div>
</div>
<div class="faq-item" data-category="billing">
<button class="faq-question" aria-expanded="false" aria-controls="faq-4">
<span class="question-text">Can I get a refund?</span>
<span class="question-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<polyline points="6,9 12,15 18,9"></polyline>
</svg>
</span>
</button>
<div class="faq-answer" id="faq-4" aria-hidden="true">
<div class="answer-content">
<p>Yes, we offer a 30-day money-back guarantee for all our services. If you're not completely satisfied, you can request a full refund within 30 days of your purchase.</p>
<p><strong>Refund Process:</strong></p>
<ol>
<li>Contact our support team</li>
<li>Provide your order number</li>
<li>Explain the reason for refund</li>
<li>Receive confirmation within 24 hours</li>
<li>Refund processed within 5-7 business days</li>
</ol>
</div>
</div>
</div>
<!-- Technical Questions -->
<div class="faq-item" data-category="technical">
<button class="faq-question" aria-expanded="false" aria-controls="faq-5">
<span class="question-text">What are the system requirements?</span>
<span class="question-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<polyline points="6,9 12,15 18,9"></polyline>
</svg>
</span>
</button>
<div class="faq-answer" id="faq-5" aria-hidden="true">
<div class="answer-content">
<p>Our platform is designed to work on all modern devices and browsers:</p>
<div class="requirements-grid">
<div class="requirement-item">
<h4>Desktop Browsers</h4>
<ul>
<li>Chrome 80+</li>
<li>Firefox 75+</li>
<li>Safari 13+</li>
<li>Edge 80+</li>
</ul>
</div>
<div class="requirement-item">
<h4>Mobile Devices</h4>
<ul>
<li>iOS 13+ (Safari)</li>
<li>Android 8+ (Chrome)</li>
<li>Responsive design</li>
<li>Touch optimized</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<div class="faq-item" data-category="technical">
<button class="faq-question" aria-expanded="false" aria-controls="faq-6">
<span class="question-text">Do you provide API access?</span>
<span class="question-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<polyline points="6,9 12,15 18,9"></polyline>
</svg>
</span>
</button>
<div class="faq-answer" id="faq-6" aria-hidden="true">
<div class="answer-content">
<p>Yes, we provide comprehensive API access for developers and businesses who want to integrate our services:</p>
<ul>
<li><strong>REST API:</strong> Full CRUD operations with JSON responses</li>
<li><strong>GraphQL:</strong> Flexible queries for advanced use cases</li>
<li><strong>Webhooks:</strong> Real-time notifications for events</li>
<li><strong>SDKs:</strong> Available for Python, JavaScript, PHP, and more</li>
</ul>
<p>API documentation and interactive testing tools are available in our developer portal.</p>
</div>
</div>
</div>
<!-- Account Questions -->
<div class="faq-item" data-category="account">
<button class="faq-question" aria-expanded="false" aria-controls="faq-7">
<span class="question-text">How do I reset my password?</span>
<span class="question-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<polyline points="6,9 12,15 18,9"></polyline>
</svg>
</span>
</button>
<div class="faq-answer" id="faq-7" aria-hidden="true">
<div class="answer-content">
<p>You can reset your password easily through our secure password reset process:</p>
<ol>
<li>Go to the login page</li>
<li>Click "Forgot Password?"</li>
<li>Enter your email address</li>
<li>Check your email for reset instructions</li>
<li>Follow the link and create a new password</li>
</ol>
<p><strong>Security Note:</strong> Reset links expire after 1 hour for security purposes.</p>
</div>
</div>
</div>
<div class="faq-item" data-category="account">
<button class="faq-question" aria-expanded="false" aria-controls="faq-8">
<span class="question-text">Can I change my email address?</span>
<span class="question-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<polyline points="6,9 12,15 18,9"></polyline>
</svg>
</span>
</button>
<div class="faq-answer" id="faq-8" aria-hidden="true">
<div class="answer-content">
<p>Yes, you can change your email address from your account settings:</p>
<ol>
<li>Log in to your account</li>
<li>Go to Account Settings</li>
<li>Click on "Change Email"</li>
<li>Enter your new email address</li>
<li>Verify the new email through the confirmation link</li>
</ol>
<p>Your old email will remain active until you confirm the new one.</p>
</div>
</div>
</div>
<!-- More General Questions -->
<div class="faq-item" data-category="general">
<button class="faq-question" aria-expanded="false" aria-controls="faq-9">
<span class="question-text">Do you offer customer support?</span>
<span class="question-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<polyline points="6,9 12,15 18,9"></polyline>
</svg>
</span>
</button>
<div class="faq-answer" id="faq-9" aria-hidden="true">
<div class="answer-content">
<p>Absolutely! We provide comprehensive customer support through multiple channels:</p>
<ul>
<li><strong>24/7 Live Chat:</strong> Instant help from our support team</li>
<li><strong>Email Support:</strong> Detailed responses within 4 hours</li>
<li><strong>Phone Support:</strong> Direct line for urgent issues</li>
<li><strong>Knowledge Base:</strong> Self-service articles and tutorials</li>
<li><strong>Community Forum:</strong> Connect with other users</li>
</ul>
</div>
</div>
</div>
<div class="faq-item" data-category="technical">
<button class="faq-question" aria-expanded="false" aria-controls="faq-10">
<span class="question-text">Is my data secure?</span>
<span class="question-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<polyline points="6,9 12,15 18,9"></polyline>
</svg>
</span>
</button>
<div class="faq-answer" id="faq-10" aria-hidden="true">
<div class="answer-content">
<p>Data security is our top priority. We implement multiple layers of protection:</p>
<ul>
<li><strong>Encryption:</strong> AES-256 encryption for data at rest and in transit</li>
<li><strong>Compliance:</strong> SOC 2 Type II, GDPR, and HIPAA compliant</li>
<li><strong>Access Control:</strong> Multi-factor authentication and role-based permissions</li>
<li><strong>Monitoring:</strong> 24/7 security monitoring and threat detection</li>
<li><strong>Backups:</strong> Automated daily backups with 99.9% uptime guarantee</li>
</ul>
</div>
</div>
</div>
<div class="faq-item" data-category="billing">
<button class="faq-question" aria-expanded="false" aria-controls="faq-11">
<span class="question-text">Can I upgrade or downgrade my plan?</span>
<span class="question-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<polyline points="6,9 12,15 18,9"></polyline>
</svg>
</span>
</button>
<div class="faq-answer" id="faq-11" aria-hidden="true">
<div class="answer-content">
<p>Yes, you can change your plan at any time. Here's how it works:</p>
<div class="plan-changes">
<div class="change-type">
<h4>Upgrading</h4>
<ul>
<li>Immediate access to new features</li>
<li>Prorated billing for the current period</li>
<li>No service interruption</li>
</ul>
</div>
<div class="change-type">
<h4>Downgrading</h4>
<ul>
<li>Changes take effect at next billing cycle</li>
<li>Data export available before downgrade</li>
<li>Credit applied to future bills</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<div class="faq-item" data-category="account">
<button class="faq-question" aria-expanded="false" aria-controls="faq-12">
<span class="question-text">How do I delete my account?</span>
<span class="question-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<polyline points="6,9 12,15 18,9"></polyline>
</svg>
</span>
</button>
<div class="faq-answer" id="faq-12" aria-hidden="true">
<div class="answer-content">
<p>We're sorry to see you go! You can delete your account through the following process:</p>
<ol>
<li>Log in to your account</li>
<li>Go to Account Settings</li>
<li>Scroll to "Danger Zone"</li>
<li>Click "Delete Account"</li>
<li>Confirm deletion via email</li>
</ol>
<p><strong>Important:</strong> This action is irreversible. All your data will be permanently deleted within 30 days.</p>
</div>
</div>
</div>
</div>
<!-- No Results Message -->
<div class="no-results" id="noResults" style="display: none;">
<div class="no-results-content">
<svg class="no-results-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor">
<circle cx="11" cy="11" r="8"></circle>
<path d="m21 21-4.35-4.35"></path>
</svg>
<h3>No questions found</h3>
<p>Try adjusting your search terms or browse different categories.</p>
<button class="reset-search-btn" onclick="resetSearch()">Clear Search</button>
</div>
</div>
<!-- Contact Support -->
<div class="faq-footer">
<div class="support-cta">
<h3>Still have questions?</h3>
<p>Can't find what you're looking for? Our support team is here to help.</p>
<div class="support-buttons">
<a href="#" class="support-btn primary">Contact Support</a>
<a href="#" class="support-btn secondary">Live Chat</a>
</div>
</div>
</div>
</div>
</section>