Table of Contents
Introduzione
La creazione di una galleria fotografica dinamica con capacità di filtraggio e selezione trasforma una raccolta di immagini statiche in un'esperienza coinvolgente e facile da usare. I visitatori possono trovare rapidamente immagini che corrispondono ai loro interessi, ad esempio filtrando per natura, città o persone, e riordinare i risultati per nome, data o valutazione senza un caricamento di pagina. Questo articolo fornisce un approccio completo e funzionale alla creazione di una galleria simile utilizzando il filtro Javascript, HTML e CSS efficiente.
Impostazione della struttura HTML
Ogni elemento immagine deve portare attributi personalizzati che descrivono la sua categoria, nome, data o qualsiasi altra proprietà che si intende filtrare o ordinare.
Segnale di base per filtri e controlli di selezione
Creare un contenitore per i pulsanti di filtro e un altro per i controlli di selezione. Utilizzare elementi con e attributi:
<div id="controls">
<div id="filter-buttons" role="group" aria-label="Filter photos by category">
<button data-filter="all" class="active">Show All</button>
<button data-filter="nature">Nature</button>
<button data-filter="city">City</button>
<button data-filter="people">People</button>
</div>
<div id="sort-options" role="group" aria-label="Sort photos">
<button data-sort="name">Sort by Name</button>
<button data-sort="date">Sort by Date</button>
<button data-sort="rating">Sort by Rating</button>
</div>
</div>
e ] migliora l'accessibilità per gli utenti di lettori di schermo. Il pulsante [[] è contrassegnato con una classe [] per indicare lo stato iniziale; lo stile con CSS.
Contenitore di Galleria immagine
All'interno di un , posizionare ogni foto nel suo elemento di involucro. Usa [, ], [, e attributi per filtrare e ordinare.
<div id="gallery" class="photo-grid">
<div class="photo" data-category="nature" data-name="Sunset Over the Hills" data-date="2023-06-15" data-rating="4.5">
<img src="images/sunset.jpg" alt="Sunset over rolling hills" loading="lazy">
<div class="photo-caption">Sunset Over the Hills</div>
</div>
<div class="photo" data-category="city" data-name="Downtown Skyline" data-date="2023-07-01" data-rating="4.2">
<img src="images/skyline.jpg" alt="Downtown skyline at dusk" loading="lazy">
<div class="photo-caption">Downtown Skyline</div>
</div>
<!-- more photos -->
</div>
L'attributo defers caricamento di immagini off-screen, migliorando le prestazioni iniziali del carico della pagina.
Utilizzo di attributi dati in modo efficace
[[LT:0]]Data attributi] (ad esempio, , []) non sono limitati alle API. Per la selezione numerica, memorizzare i numeri come stringhe; JavaScript li parse come necessario. Per più categorie, è possibile memorizzare un elenco separato dallo spazio come e dividerlo durante il filtraggio delle immagini.
Styling the Gallery con CSS
Un layout pulito e reattivo imposta la fase per le caratteristiche interattive. Utilizzare CSS Grid o Flexbox per la griglia di foto, e disegnare i pulsanti per indicare filtri attivi e lo stato di selezione.
Telaio per foto
.photo-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 1rem;
padding: 1rem 0;
}
.photo {
position: relative;
overflow: hidden;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.photo img {
width: 100%;
height: auto;
display: block;
transition: transform 0.3s ease;
}
.photo:hover img {
transform: scale(1.05);
}
Questa griglia garantisce l'adattamento delle immagini alle dimensioni dello schermo. L'effetto hover aggiunge una sottile interazione con lo zoom, rendendo la galleria più lucida.
Stato attivo per pulsanti
#filter-buttons button.active,
#sort-options button.active {
background-color: #007acc;
color: #fff;
border-color: #007acc;
}
button {
padding: 0.5rem 1rem;
border: 1px solid #ccc;
background: #fff;
cursor: pointer;
margin: 0.25rem;
border-radius: 4px;
transition: background 0.2s, color 0.2s;
}
button:hover {
background: #e6e6e6;
}
Applicando la classe al pulsante filtro/sort corrente fornisce feedback visivi. JavaScript gestirà l'aggiunta e la rimozione di questa classe.
Considerazioni responsive
Aumentare le dimensioni del tasto touch target di almeno 44px per 44px (consigliamento WCAG 2.1). Utilizzare le query dei media se necessario per passare da una griglia multi-colonna a una singola colonna su schermi molto piccoli.
Implementazione di JavaScript Filtering
Ora portiamo la galleria alla vita. L'idea principale: ascoltare i clic sui pulsanti del filtro, poi mostrare o nascondere elementi foto basati sul loro attributo .
Selezione di elementi DOM e inizializzazione
const filterButtons = document.querySelectorAll('#filter-buttons button');
const sortButtons = document.querySelectorAll('#sort-options button');
const gallery = document.getElementById('gallery');
let photos = Array.from(gallery.children);
let activeFilter = 'all';
let activeSort = 'name'; // default sort
L'archiviazione come array ci dà un facile accesso ai metodi di array come [ e ].
Filtraggio della logica
function filterPhotos(filter) {
activeFilter = filter;
photos.forEach(photo => {
const categories = photo.dataset.category; // may be a space-separated string
const shouldShow = filter === 'all' || categories.split(' ').includes(filter);
photo.style.display = shouldShow ? '' : 'none';
});
// After filtering, re-sort the visible photos
sortPhotos(activeSort);
}
Questa funzione supporta più categorie: se , quindi scegliendo “natura” o “paesaggio” mostrerà la foto. Nota:] restituisce il valore di (come una stringa).
Attaccare gli ascoltatori degli eventi per filtrare i pulsanti
filterButtons.forEach(button => {
button.addEventListener('click', () => {
const filter = button.dataset.filter;
// Update active class on filter buttons
filterButtons.forEach(btn => btn.classList.remove('active'));
button.classList.add('active');
// Apply filter
filterPhotos(filter);
});
});
Rimuovere la classe da tutti i pulsanti e aggiungerla a quella cliccata assicura la coerenza visiva. La funzione [ è chiamata con il valore del filtro selezionato.
Implementazione di JavaScript Sorting
La selezione riorganizza le foto visibili nel DOM in base ad un attributo scelto (ad esempio, nome, data, valutazione).
Funzione di selezione
function sortPhotos(sortBy) {
activeSort = sortBy;
// Get currently visible photos (display not 'none')
const visiblePhotos = photos.filter(photo => photo.style.display !== 'none');
visiblePhotos.sort((a, b) => {
let valA, valB;
switch (sortBy) {
case 'name':
valA = a.dataset.name.toLowerCase();
valB = b.dataset.name.toLowerCase();
return valA.localeCompare(valB);
case 'date':
valA = new Date(a.dataset.date);
valB = new Date(b.dataset.date);
return valA - valB;
case 'rating':
valA = parseFloat(a.dataset.rating);
valB = parseFloat(b.dataset.rating);
return valB - valA; // descending: highest first
default:
return 0;
}
});
// Re‑append sorted photos back to the gallery container
visiblePhotos.forEach(photo => gallery.appendChild(photo));
}
Per le stringhe, usiamo per un corretto ordinamento alfabetico. Le date sono confrontate come Oggetti Data, e le valutazioni sono ordinate in ordine descrescente (prima più popolare).
Ascolti di eventi per Pulsanti Ordinati
sortButtons.forEach(button => {
button.addEventListener('click', () => {
const sortBy = button.dataset.sort;
sortButtons.forEach(btn => btn.classList.remove('active'));
button.classList.add('active');
sortPhotos(sortBy);
});
});
Quando viene cliccato un pulsante di selezione, aggiorniamo la classe attiva e chiamiamo [] con la chiave di selezione desiderata. Perché già chiama dopo il filtraggio, la galleria rimane coerente.
Impostazione iniziale
// Set default active buttons
document.querySelector('#filter-buttons [data-filter="all"]').classList.add('active');
document.querySelector('#sort-options [data-sort="name"]').classList.add('active');
// Load and initially sort by name
filterPhotos('all');
Chiamare all'inizio assicura che la galleria sia popolata con tutte le immagini e ordinata per ordine predefinito (nome).
Filtro avanzato e ricerca
Un filtro di categoria semplice è utile, ma si può desiderare di combinare più filtri o aggiungere un input di ricerca di testo.
Filtri di categoria multipli (Checkbox)
Invece di pulsanti esclusivi, utilizzare caselle di controllo in modo che gli utenti possano selezionare più categorie:
<div id="filter-checkboxes">
<label><input type="checkbox" value="nature" checked> Nature</label>
<label><input type="checkbox" value="city" checked> City</label>
<label><input type="checkbox" value="people" checked> People</label>
</div>
Quindi modificare la logica di filtraggio per costruire un insieme di categorie attive:
function filterPhotosByCheckboxes() {
const checked = document.querySelectorAll('#filter-checkboxes input:checked');
const activeCategories = Array.from(checked).map(cb => cb.value);
photos.forEach(photo => {
const photoCategories = photo.dataset.category.split(' ');
const shouldShow = activeCategories.length === 0 ||
photoCategories.some(cat => activeCategories.includes(cat));
photo.style.display = shouldShow ? '' : 'none';
});
sortPhotos(activeSort);
}
Se non vengono verificate caselle di controllo, è possibile scegliere di mostrare tutte le immagini (come nel codice sopra) o mostrare nessuno—definire l'UX desiderato.
Input di ricerca di testo
Aggiungi un campo di input che cerca le didascalie o l'attributo :
<input type="text" id="search" placeholder="Search photos...">
const searchInput = document.getElementById('search');
searchInput.addEventListener('input', () => {
const query = searchInput.value.toLowerCase();
photos.forEach(photo => {
const name = photo.dataset.name.toLowerCase();
// Also search in caption if present
const caption = photo.querySelector('.photo-caption')?.innerText.toLowerCase() || '';
const matches = name.includes(query) || caption.includes(query);
// If a filter is active, also check category
const filter = activeFilter;
const catMatch = filter === 'all' || photo.dataset.category.split(' ').includes(filter);
photo.style.display = (matches && catMatch) ? '' : 'none';
});
sortPhotos(activeSort);
});
Combina la ricerca con i pulsanti di filtro per consentire ulteriori risultati restringimento. Nota che è necessario memorizzare lo stato filtro corrente per rispettarlo durante la ricerca.
Prestazioni e Accessibilità
Una galleria dinamica dovrebbe essere veloce e utilizzabile da tutti, comprese le persone che utilizzano tecnologie assistive.
Immagini di caricamento pigro
Abbiamo già usato che sgonfia il caricamento fino a quando l'immagine non è vicino al viewport. Per i browser più vecchi, è possibile implementare un failback JavaScript lazy-loading utilizzando il Intersezione Observer API]. Ciò assicura che anche se il caricamento pigro nativo non è supportato, immagini off-screen non sono caricate, riducendo la larghezza di banda e migliorando le prestazioni percepite.
Debouing Search Input
Se si attacca l'ascoltatore di ricerca , si accende su ogni tasto di tasti. Per grandi gallerie, si consideri debouncing il gestore (ad esempio, 200ms ritardo) per evitare manipolazioni DOM eccessive.
function debounce(func, delay) { let timeoutId; return function (...args) { clearTimeout(timeoutId); timeoutId = setTimeout(() => func.apply(this, args), delay); }; } searchInput.addEventListener('input', debounce(handleSearch, 200));Keyboard Navigation
Filter and sort buttons should be focusable and operable via keyboard. Using native
<button>elements already provides keyboard interaction (Enter/Space). Ensure that after filtering or sorting, focus is managed logically; for example, you could move focus to the first photo after a filter change via a focusable element. Also, consider addingaria-pressedattributes to filter buttons to indicate toggle state.Announcing Changes to Screen Readers
Use an ARIA live region to announce filter and sort results:
<div id="gallery-announce" aria-live="polite" class="sr-only"></div>Dopo ogni azione filtro/sort, aggiornare il testo di quell'elemento, ad esempio, "Mostrare 8 foto naturali ordinate per nome", che aiuta gli utenti che si affidano ai lettori di schermo a capire cosa è cambiato.
CSS per contenuti nascosti
Invece di usare da solo, considerare l'utilizzo di una classe CSS come [] che nasconde l'elemento e lo rimuove dall'albero di accessibilità:
.hidden { display: none !important; visibility: hidden; }Usando rimuove elementi dall'albero di accessibilità, che è appropriato. Basta assicurarsi che non si affidano solo a senza perché lascia l'elemento occupante spazio.
Conclusioni
Combinando HTML semantico pulito, CSS reattivo e JavaScript ben strutturato, è possibile costruire una galleria fotografica dinamica che è veloce, accessibile e piacevole da usare. Le tecniche coperte - filtraggio per categoria (comprese le categorie multiple), smistamento da vari attributi, aggiunta di ricerca di testo e ottimizzare le prestazioni - forniscono una solida base che può essere estesa con caratteristiche come l'impaginazione, lo scorrimento infinito, o l'integrazione con un backend API.
Per ulteriori informazioni, la documentazione MDN su Array.prototype.sort()[] spiega l’algoritmo di selezione, e il web.dev responsive design guide[]] offre ulteriori suggerimenti di layout.