Modern filterable chips with close buttons for categories and tags
<head>
.<!-- Font Awesome Icons; Make sure to add it in the <head> tag -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<div class="filter-chips-container">
<div class="filter-chips-wrapper">
<div class="filter-chip active">
<span class="filter-chip-icon"><i class="fas fa-code"></i></span>
<span class="filter-chip-text">JavaScript</span>
<button class="filter-chip-close"><i class="fas fa-times"></i></button>
</div>
<div class="filter-chip">
<span class="filter-chip-icon"><i class="fas fa-paint-brush"></i></span>
<span class="filter-chip-text">CSS</span>
<button class="filter-chip-close"><i class="fas fa-times"></i></button>
</div>
<div class="filter-chip">
<span class="filter-chip-icon"><i class="fas fa-table"></i></span>
<span class="filter-chip-text">Frameworks</span>
<button class="filter-chip-close"><i class="fas fa-times"></i></button>
</div>
<div class="filter-chip">
<span class="filter-chip-icon"><i class="fas fa-mobile-alt"></i></span>
<span class="filter-chip-text">Responsive</span>
<button class="filter-chip-close"><i class="fas fa-times"></i></button>
</div>
</div>
<div class="filter-chip-input-wrapper">
<div class="filter-chip-input">
<span class="filter-chip-input-icon"><i class="fas fa-plus"></i></span>
<input type="text" placeholder="Add filter...">
</div>
</div>
</div>
.filter-chips-container {
width: 100%;
max-width: 600px;
display: flex;
flex-direction: column;
gap: 12px;
}
.filter-chips-wrapper {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.filter-chip {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 4px 8px 4px 4px;
border-radius: 16px;
font-size: 14px;
background-color: #f1f2f4;
color: #333;
transition: all 0.2s ease;
cursor: pointer;
user-select: none;
max-width: 150px;
}
.filter-chip:hover {
background-color: #e5e7eb;
}
.filter-chip.active {
background-color: #e1f5fe;
color: #0277bd;
}
.filter-chip-icon {
display: flex;
align-items: center;
justify-content: center;
width: 22px;
height: 22px;
border-radius: 50%;
background-color: rgba(0, 0, 0, 0.075);
font-size: 12px;
}
.filter-chip.active .filter-chip-icon {
background-color: #0277bd;
color: white;
}
.filter-chip-text {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-weight: 500;
}
.filter-chip-close {
display: flex;
align-items: center;
justify-content: center;
width: 16px;
height: 16px;
border-radius: 50%;
background: none;
border: none;
cursor: pointer;
opacity: 0.5;
transition: opacity 0.2s ease;
font-size: 10px;
color: inherit;
}
.filter-chip-close:hover {
opacity: 1;
background-color: rgba(0, 0, 0, 0.05);
}
.filter-chip-input-wrapper {
margin-top: 8px;
}
.filter-chip-input {
display: flex;
align-items: center;
gap: 8px;
padding: 6px 12px;
border: 1px dashed #d1d5db;
border-radius: 20px;
background-color: rgba(0, 0, 0, 0.02);
transition: all 0.2s ease;
}
.filter-chip-input:focus-within {
border-color: #0277bd;
background-color: white;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}
.filter-chip-input-icon {
color: #9ca3af;
font-size: 12px;
}
.filter-chip-input input {
flex: 1;
border: none;
background: none;
outline: none;
font-size: 14px;
color: #333;
}
.filter-chip-input input::placeholder {
color: #9ca3af;
}
/* Dark mode styles */
@media (prefers-color-scheme: dark) {
.filter-chip {
background-color: #2a2a2a;
color: #f1f2f4;
}
.filter-chip:hover {
background-color: #3a3a3a;
}
.filter-chip.active {
background-color: #103d52;
color: #80deea;
}
.filter-chip-icon {
background-color: rgba(255, 255, 255, 0.1);
}
.filter-chip.active .filter-chip-icon {
background-color: #0277bd;
color: white;
}
.filter-chip-close:hover {
background-color: rgba(255, 255, 255, 0.1);
}
.filter-chip-input {
border-color: #3a3a3a;
background-color: rgba(255, 255, 255, 0.02);
}
.filter-chip-input:focus-within {
border-color: #0277bd;
background-color: #2a2a2a;
}
.filter-chip-input input {
color: #f1f2f4;
}
.filter-chip-input input::placeholder {
color: #9ca3af;
}
}
document.addEventListener('DOMContentLoaded', function() {
const chipContainer = document.querySelector('.filter-chips-wrapper');
const chipInput = document.querySelector('.filter-chip-input input');
// Toggle active state on chip click
chipContainer.addEventListener('click', function(e) {
const chip = e.target.closest('.filter-chip');
if (chip && !e.target.closest('.filter-chip-close')) {
chip.classList.toggle('active');
}
});
// Remove chip when close button is clicked
chipContainer.addEventListener('click', function(e) {
const closeBtn = e.target.closest('.filter-chip-close');
if (closeBtn) {
const chip = closeBtn.closest('.filter-chip');
chip.addEventListener('animationend', () => {
chip.remove();
});
chip.classList.add('removing');
chip.style.animation = 'chipRemove 0.3s forwards';
}
});
// Add new chip when enter is pressed in input
chipInput.addEventListener('keyup', function(e) {
if (e.key === 'Enter' && this.value.trim() !== '') {
const newChip = document.createElement('div');
newChip.className = 'filter-chip';
newChip.innerHTML = `
${this.value.trim()}
`;
chipContainer.appendChild(newChip);
this.value = '';
// Add entrance animation
newChip.style.animation = 'chipAdd 0.3s forwards';
}
});
});
// Add these animations to your CSS
document.head.insertAdjacentHTML('beforeend', `
`);