3.2.4 - Következetes azonosítás
Röviden a szabványpontról
A WCAG 2.2 Success Criterion 3.2.4 (Consistent Identification) megköveteli, hogy azok a felhasználói felület komponensek, amelyeket több weboldal között ismételten használnak, konzisztensen legyenek azonosítva. Ez azt jelenti, hogy az ugyanazon funkciót betöltő komponensek, mint a gombok, linkek, ikonok és egyéni vezérlők, minden előfordulási helyükön ugyanazokkal a címkékkel, nevekkel vagy leírásokkal kell rendelkezniük.
Cél: Csökkenteni a felhasználók zavarát és hibáit azzal, hogy kiszámítható és egységes felhasználói élményt biztosítunk. A konzisztens azonosítás segíti a felhasználókat abban, hogy megjegyezzék és helyesen használják az ismétlődő komponenseket.
Mire vonatkozik: Minden olyan webes tartalomra, ahol felhasználói felület komponenseket újra használnak, beleértve a látható címkéket és a nem látható címkéket, mint az alt szöveg vagy aria-label attribútumok.
Kiket érint
Elsődleges felhasználók: Kognitív fogyatékossággal élő emberek, gyengénlátók, képernyőolvasó felhasználók és kizárólag billentyűzetes felhasználók támaszkodnak a konzisztens címkézésre, hogy megértsék és előre jelezzék, hogyan lépjenek kapcsolatba a webhellyel.
Másodlagos előnyök: A konzisztens azonosítás javítja a használhatóságot mindenki számára azzal, hogy intuitívabbá teszi a navigációt és csökkenti a kognitív terhelést.
Tesztelés
- Manuális átvizsgálás: Navigálj különböző oldalakon és ellenőrizd, hogy az azonos funkciójú felhasználói felület komponensek azonos címkékkel és hozzáférhető nevekkel rendelkeznek
- Képernyőolvasó tesztelés: Használj képernyőolvasót annak ellenőrzésére, hogy az ismétlődő vezérlők hozzáférhető nevei (pl. aria-label, alt attribútumok) konzisztensek
- Automatizált eszközök: Használj akadálymentességi tesztelő eszközöket (mint az axe DevTools) az ismétlődő komponensek inkonzisztens címkézésének azonosítására
- Kód áttekintés: Vizsgáld meg a forráskódot, hogy megbizonyosodj arról, hogy az ismétlődő elemek ugyanazt a címkeszöveget vagy ARIA attribútumokat használják
- Felhasználói tesztelés: Figyelj meg fogyatékossággal élő felhasználókat, hogy lásd, okoznak-e zavarokat vagy hibákat az inkonzisztens címkék
Jó gyakorlatok
1. Konzisztens gomb címkék minden oldalon
<!-- ŰRLAP OLDAL -->
<form class="kapcsolat-form">
<div class="form-group">
<label for="nev">Teljes név:</label>
<input type="text" id="nev" name="nev" required>
</div>
<div class="form-group">
<label for="email">E-mail cím:</label>
<input type="email" id="email" name="email" required>
</div>
<div class="form-group">
<label for="uzenet">Üzenet:</label>
<textarea id="uzenet" name="uzenet" rows="5" required></textarea>
</div>
<!-- KONZISZTENS gomb címke minden űrlapnál -->
<button type="submit" aria-label="Űrlap elküldése">Küldés</button>
<button type="reset" aria-label="Űrlap visszaállítása">Törlés</button>
</form>
<!-- REGISZTRÁCIÓS OLDAL - UGYANAZOK a gomb címkék -->
<form class="regisztracio-form">
<div class="form-group">
<label for="reg-felhasznalonev">Felhasználónév:</label>
<input type="text" id="reg-felhasznalonev" name="felhasznalonev" required>
</div>
<div class="form-group">
<label for="reg-email">E-mail cím:</label>
<input type="email" id="reg-email" name="email" required>
</div>
<div class="form-group">
<label for="reg-jelszo">Jelszó:</label>
<input type="password" id="reg-jelszo" name="jelszo" required>
</div>
<!-- PONTOSAN UGYANAZOK a gomb címkék -->
<button type="submit" aria-label="Űrlap elküldése">Küldés</button>
<button type="reset" aria-label="Űrlap visszaállítása">Törlés</button>
</form>
<!-- HÍRLEVÉL FELIRATKOZÁS - KONZISZTENS címkék -->
<form class="hirlevel-form">
<div class="form-group">
<label for="hirlevel-email">E-mail címe a hírlevélhez:</label>
<input type="email" id="hirlevel-email" name="email" required>
</div>
<div class="checkbox-group">
<input type="checkbox" id="adatkezeles" name="adatkezeles" required>
<label for="adatkezeles">Elfogadom az adatkezelési tájékoztatót</label>
</div>
<!-- UGYANAZOK a gomb címkék, még itt is -->
<button type="submit" aria-label="Űrlap elküldése">Küldés</button>
<button type="reset" aria-label="Űrlap visszaállítása">Törlés</button>
</form>
<!-- TERMÉK ÉRTÉKELÉS FORM -->
<form class="ertekeles-form">
<div class="form-group">
<label for="termek-ertekeles">Termék értékelése:</label>
<select id="termek-ertekeles" name="ertekeles" required>
<option value="">Válasszon értékelést</option>
<option value="5">5 csillag - Kiváló</option>
<option value="4">4 csillag - Jó</option>
<option value="3">3 csillag - Elfogadható</option>
<option value="2">2 csillag - Gyenge</option>
<option value="1">1 csillag - Rossz</option>
</select>
</div>
<div class="form-group">
<label for="ertekeles-szoveg">Részletes vélemény:</label>
<textarea id="ertekeles-szoveg" name="velemeny" rows="4"></textarea>
</div>
<!-- KONZISZTENCIA: még itt is ugyanazok a címkék -->
<button type="submit" aria-label="Űrlap elküldése">Küldés</button>
<button type="reset" aria-label="Űrlap visszaállítása">Törlés</button>
</form>
<style>
.form-group {
margin-bottom: 1rem;
}
.form-group label {
display: block;
font-weight: bold;
margin-bottom: 0.5rem;
}
.form-group input, .form-group select, .form-group textarea {
width: 100%;
padding: 0.5rem;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 1rem;
}
.checkbox-group {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 1rem;
}
.checkbox-group input[type="checkbox"] {
width: auto;
}
button[type="submit"] {
background: #28a745;
color: white;
border: none;
padding: 0.75rem 1.5rem;
border-radius: 4px;
cursor: pointer;
margin-right: 0.5rem;
}
button[type="reset"] {
background: #6c757d;
color: white;
border: none;
padding: 0.75rem 1.5rem;
border-radius: 4px;
cursor: pointer;
}
button:hover, button:focus {
opacity: 0.9;
outline: 2px solid #007bff;
outline-offset: 2px;
}
</style>
Magyarázat: Minden űrlapon ugyanazt a „Küldés” és „Törlés” gombot használjuk ugyanazzal az aria-label attribútummal, így a felhasználók mindig tudják, mit várhatnak ezektől a gombaktól.
2. Konzisztens ikon címkézés navigációban
<!-- FŐOLDAL NAVIGÁCIÓ -->
<nav role="navigation" aria-label="Főnavigáció">
<ul class="main-nav">
<li>
<a href="/fooldal" aria-label="Főoldalra ugrás">
<svg class="nav-icon" aria-hidden="true">
<use href="#home-icon"></use>
</svg>
<span>Főoldal</span>
</a>
</li>
<li>
<a href="/termekek" aria-label="Termékek oldalra ugrás">
<svg class="nav-icon" aria-hidden="true">
<use href="#products-icon"></use>
</svg>
<span>Termékek</span>
</a>
</li>
<li>
<a href="/kosar" aria-label="Bevásárlókosár megtekintése">
<svg class="nav-icon" aria-hidden="true">
<use href="#cart-icon"></use>
</svg>
<span>Kosár</span>
<span class="cart-count" aria-label="3 termék a kosárban">3</span>
</a>
</li>
</ul>
</nav>
<!-- TERMÉKEK OLDAL - UGYANAZOK az ikon címkék -->
<nav role="navigation" aria-label="Főnavigáció">
<ul class="main-nav">
<li>
<!-- PONTOSAN UGYANAZ az aria-label -->
<a href="/fooldal" aria-label="Főoldalra ugrás">
<svg class="nav-icon" aria-hidden="true">
<use href="#home-icon"></use>
</svg>
<span>Főoldal</span>
</a>
</li>
<li>
<!-- PONTOSAN UGYANAZ az aria-label -->
<a href="/termekek" aria-current="page" aria-label="Termékek oldalra ugrás">
<svg class="nav-icon" aria-hidden="true">
<use href="#products-icon"></use>
</svg>
<span>Termékek</span>
</a>
</li>
<li>
<!-- PONTOSAN UGYANAZ az aria-label struktúra -->
<a href="/kosar" aria-label="Bevásárlókosár megtekintése">
<svg class="nav-icon" aria-hidden="true">
<use href="#cart-icon"></use>
</svg>
<span>Kosár</span>
<span class="cart-count" aria-label="5 termék a kosárban">5</span>
</a>
</li>
</ul>
</nav>
<!-- MŰVELETI GOMBOK minden oldalon ugyanúgy -->
<div class="action-buttons">
<!-- Szerkesztés gomb - mindig ugyanaz a címke -->
<button class="edit-btn" aria-label="Tartalom szerkesztése">
<svg aria-hidden="true">
<use href="#edit-icon"></use>
</svg>
<span class="btn-text">Szerkesztés</span>
</button>
<!-- Törlés gomb - mindig ugyanaz a címke -->
<button class="delete-btn" aria-label="Tartalom törlése" data-confirm="true">
<svg aria-hidden="true">
<use href="#delete-icon"></use>
</svg>
<span class="btn-text">Törlés</span>
</button>
<!-- Megosztás gomb - mindig ugyanaz a címke -->
<button class="share-btn" aria-label="Tartalom megosztása">
<svg aria-hidden="true">
<use href="#share-icon"></use>
</svg>
<span class="btn-text">Megosztás</span>
</button>
<!-- Nyomtatás gomb - mindig ugyanaz a címke -->
<button class="print-btn" aria-label="Oldal nyomtatása" onclick="window.print()">
<svg aria-hidden="true">
<use href="#print-icon"></use>
</svg>
<span class="btn-text">Nyomtatás</span>
</button>
<!-- Bezárás gomb - mindig ugyanaz a címke -->
<button class="close-btn" aria-label="Ablak bezárása">
<svg aria-hidden="true">
<use href="#close-icon"></use>
</svg>
<span class="btn-text">Bezárás</span>
</button>
</div>
<!-- SVG ikonok definíciói -->
<svg style="display: none;">
<defs>
<symbol id="home-icon" viewBox="0 0 24 24">
<path d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"/>
</symbol>
<symbol id="products-icon" viewBox="0 0 24 24">
<path d="M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4"/>
</symbol>
<symbol id="cart-icon" viewBox="0 0 24 24">
<path d="M3 3h2l.4 2M7 13h10l4-8H5.4m0 0L7 13m0 0l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17M17 13v4a2 2 0 01-2 2H9a2 2 0 01-2-2v-4m8 0V9a2 2 0 00-2-2H9a2 2 0 00-2 2v4.01"/>
</symbol>
<symbol id="edit-icon" viewBox="0 0 24 24">
<path d="M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7"/>
<path d="M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z"/>
</symbol>
<symbol id="delete-icon" viewBox="0 0 24 24">
<path d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/>
</symbol>
<symbol id="share-icon" viewBox="0 0 24 24">
<path d="M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 105.367-2.684 3 3 0 00-5.367 2.684zm0 9.316a3 3 0 105.368 2.684 3 3 0 00-5.368-2.684z"/>
</symbol>
<symbol id="print-icon" viewBox="0 0 24 24">
<path d="M17 17h2a2 2 0 002-2v-4a2 2 0 00-2-2H5a2 2 0 00-2 2v4a2 2 0 002 2h2m2 4h6a2 2 0 002-2v-4a2 2 0 00-2-2H9a2 2 0 00-2 2v4a2 2 0 002 2zm8-12V5a2 2 0 00-2-2H9a2 2 0 00-2 2v4h10z"/>
</symbol>
<symbol id="close-icon" viewBox="0 0 24 24">
<path d="M6 18L18 6M6 6l12 12"/>
</symbol>
</defs>
</svg>
<style>
.main-nav {
list-style: none;
display: flex;
gap: 1rem;
padding: 0;
margin: 0;
}
.main-nav a {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.5rem 1rem;
text-decoration: none;
color: #495057;
border-radius: 4px;
transition: all 0.2s ease;
}
.main-nav a:hover, .main-nav a:focus {
background: #e9ecef;
color: #007bff;
}
.main-nav a[aria-current="page"] {
background: #007bff;
color: white;
}
.nav-icon {
width: 20px;
height: 20px;
fill: currentColor;
stroke: currentColor;
stroke-width: 2;
}
.cart-count {
background: #dc3545;
color: white;
border-radius: 50%;
padding: 0.2rem 0.5rem;
font-size: 0.8em;
font-weight: bold;
min-width: 1.2em;
text-align: center;
}
.action-buttons {
display: flex;
gap: 0.5rem;
margin: 1rem 0;
flex-wrap: wrap;
}
.action-buttons button {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.5rem 1rem;
border: 1px solid #dee2e6;
background: white;
color: #495057;
border-radius: 4px;
cursor: pointer;
transition: all 0.2s ease;
}
.action-buttons button:hover, .action-buttons button:focus {
background: #f8f9fa;
border-color: #007bff;
outline: 2px solid #007bff;
outline-offset: 2px;
}
.edit-btn:hover, .edit-btn:focus {
background: #d4edda;
border-color: #28a745;
color: #155724;
}
.delete-btn:hover, .delete-btn:focus {
background: #f8d7da;
border-color: #dc3545;
color: #721c24;
}
.share-btn:hover, .share-btn:focus {
background: #d1ecf1;
border-color: #17a2b8;
color: #0c5460;
}
.print-btn:hover, .print-btn:focus {
background: #fff3cd;
border-color: #ffc107;
color: #856404;
}
.close-btn:hover, .close-btn:focus {
background: #e2e3e5;
border-color: #6c757d;
color: #383d41;
}
.action-buttons svg {
width: 16px;
height: 16px;
fill: none;
stroke: currentColor;
stroke-width: 2;
}
.btn-text {
font-size: 0.9em;
}
@media (max-width: 768px) {
.main-nav {
flex-direction: column;
}
.action-buttons {
justify-content: center;
}
.action-buttons button {
flex: 1;
justify-content: center;
min-width: 120px;
}
}
</style>
Magyarázat: Minden ikon és gomb ugyanazzal az aria-label értékkel van ellátva minden oldal navigációjában, biztosítva, hogy a felhasználók mindig tudják, mit tesznek az egyes elemek.
3. Konzisztens link szövegek és képek alt szövegei
<!-- FŐOLDAL - Navigációs linkek -->
<nav role="navigation" aria-label="Oldal navigáció">
<ul class="page-nav">
<li><a href="/fooldal">Főoldal</a></li>
<li><a href="/rolunk">Rólunk</a></li>
<li><a href="/szolgaltatasok">Szolgáltatások</a></li>
<li><a href="/portfolio">Portfólió</a></li>
<li><a href="/blog">Blog</a></li>
<li><a href="/kapcsolat">Kapcsolat</a></li>
</ul>
</nav>
<!-- SZOLGÁLTATÁSOK OLDAL - PONTOSAN UGYANAZOK a link szövegek -->
<nav role="navigation" aria-label="Oldal navigáció">
<ul class="page-nav">
<li><a href="/fooldal">Főoldal</a></li> <!-- Ugyanaz a szöveg -->
<li><a href="/rolunk">Rólunk</a></li> <!-- Ugyanaz a szöveg -->
<li><a href="/szolgaltatasok" aria-current="page">Szolgáltatások</a></li>
<li><a href="/portfolio">Portfólió</a></li> <!-- Ugyanaz a szöveg -->
<li><a href="/blog">Blog</a></li> <!-- Ugyanaz a szöveg -->
<li><a href="/kapcsolat">Kapcsolat</a></li> <!-- Ugyanaz a szöveg -->
</ul>
</nav>
<!-- KONZISZTENS képek alt szövegekkel minden oldalon -->
<div class="company-info">
<h2>Csapatunk</h2>
<div class="team-member">
<!-- KONZISZTENS alt szöveg minden oldalon -->
<img src="ceo-foto.jpg" alt="Kovács János ügyvezető portréfotója">
<h3>Kovács János</h3>
<p>Ügyvezető</p>
</div>
<div class="team-member">
<!-- KONZISZTENS alt szöveg minden oldalon -->
<img src="cto-foto.jpg" alt="Nagy Mária műszaki igazgató portréfotója">
<h3>Nagy Mária</h3>
<p>Műszaki igazgató</p>
</div>
</div>
<!-- MŰVELETI GOMBOK képekkel - KONZISZTENS alt szövegek -->
<div class="document-actions">
<h3>Dokumentum műveletek</h3>
<!-- Minden oldalon UGYANEZ az alt szöveg a letöltés gombra -->
<button type="button" class="action-btn" onclick="downloadPDF()">
<img src="download-icon.png" alt="PDF letöltése" role="presentation">
<span>PDF letöltése</span>
</button>
<!-- Minden oldalon UGYANEZ az alt szöveg a nyomtatás gombra -->
<button type="button" class="action-btn" onclick="window.print()">
<img src="print-icon.png" alt="Oldal nyomtatása" role="presentation">
<span>Nyomtatás</span>
</button>
<!-- Minden oldalon UGYANEZ az alt szöveg az email gombra -->
<a href="mailto:info@vallalat.hu" class="action-btn">
<img src="email-icon.png" alt="E-mail küldése" role="presentation">
<span>E-mail küldése</span>
</a>
<!-- Minden oldalon UGYANEZ az alt szöveg a megosztás gombra -->
<button type="button" class="action-btn" onclick="shareContent()">
<img src="share-icon.png" alt="Tartalom megosztása" role="presentation">
<span>Megosztás</span>
</button>
</div>
<!-- TERMÉK OLDALAK - Konzisztens értékelési rendszer -->
<div class="product-rating">
<h4>Termék értékelése</h4>
<!-- MINDEN termék oldalon ugyanezek az alt szövegek -->
<div class="star-rating" role="img" aria-label="5 csillagból 4 csillag értékelés">
<img src="star-filled.png" alt="Kitöltött csillag" class="star">
<img src="star-filled.png" alt="Kitöltött csillag" class="star">
<img src="star-filled.png" alt="Kitöltött csillag" class="star">
<img src="star-filled.png" alt="Kitöltött csillag" class="star">
<img src="star-empty.png" alt="Üres csillag" class="star">
</div>
<p>4.2/5 (127 értékelés)</p>
</div>
<!-- SOCIAL MEDIA linkek - KONZISZTENS alt szövegek -->
<div class="social-media" role="navigation" aria-label="Közösségi média linkek">
<h4>Kövessen minket:</h4>
<!-- MINDEN oldalon ugyanezek az alt szövegek -->
<a href="https://facebook.com/vallalat" target="_blank" rel="noopener">
<img src="facebook-icon.png" alt="Facebook oldal megnyitása új ablakban" class="social-icon">
<span class="visually-hidden">Facebook</span>
</a>
<a href="https://instagram.com/vallalat" target="_blank" rel="noopener">
<img src="instagram-icon.png" alt="Instagram profil megnyitása új ablakban" class="social-icon">
<span class="visually-hidden">Instagram</span>
</a>
<a href="https://linkedin.com/company/vallalat" target="_blank" rel="noopener">
<img src="linkedin-icon.png" alt="LinkedIn profil megnyitása új ablakban" class="social-icon">
<span class="visually-hidden">LinkedIn</span>
</a>
<a href="https://youtube.com/vallalat" target="_blank" rel="noopener">
<img src="youtube-icon.png" alt="YouTube csatorna megnyitása új ablakban" class="social-icon">
<span class="visually-hidden">YouTube</span>
</a>
</div>
<!-- BREADCRUMB navigáció - konzisztens linkek -->
<nav aria-label="Breadcrumb navigáció" class="breadcrumb">
<ol>
<li><a href="/fooldal">Főoldal</a></li> <!-- Konzisztens link szöveg -->
<li><a href="/termekek">Termékek</a></li> <!-- Konzisztens link szöveg -->
<li><a href="/kategoria/elektronika">Elektronika</a></li>
<li aria-current="page">Smartphone</li>
</ol>
</nav>
<script>
// Konzisztens funkcionalitás minden oldalon
function downloadPDF() {
console.log('PDF letöltése megkezdve...');
// PDF letöltési logika
}
function shareContent() {
if (navigator.share) {
navigator.share({
title: document.title,
text: 'Tekintse meg ezt a tartalmat!',
url: window.location.href
});
} else {
// Fallback megosztási módszerek
const url = encodeURIComponent(window.location.href);
const text = encodeURIComponent('Tekintse meg ezt a tartalmat!');
const shareWindow = window.open(
`https://www.facebook.com/sharer/sharer.php?u=${url}"e=${text}`,
'shareWindow',
'width=600,height=400'
);
}
}
</script>
<style>
.page-nav {
list-style: none;
display: flex;
gap: 1rem;
padding: 0;
margin: 0;
flex-wrap: wrap;
}
.page-nav a {
text-decoration: none;
padding: 0.5rem 1rem;
background: #f8f9fa;
color: #495057;
border-radius: 4px;
transition: all 0.2s ease;
}
.page-nav a:hover, .page-nav a:focus {
background: #e9ecef;
color: #007bff;
}
.page-nav a[aria-current="page"] {
background: #007bff;
color: white;
}
.company-info {
margin: 2rem 0;
}
.team-member {
display: flex;
align-items: center;
gap: 1rem;
margin: 1rem 0;
padding: 1rem;
border: 1px solid #dee2e6;
border-radius: 8px;
}
.team-member img {
width: 80px;
height: 80px;
border-radius: 50%;
object-fit: cover;
}
.document-actions {
margin: 2rem 0;
padding: 1rem;
background: #f8f9fa;
border-radius: 8px;
}
.action-btn {
display: inline-flex;
align-items: center;
gap: 0.5rem;
padding: 0.5rem 1rem;
margin: 0.25rem;
background: white;
color: #495057;
text-decoration: none;
border: 1px solid #dee2e6;
border-radius: 4px;
cursor: pointer;
transition: all 0.2s ease;
}
.action-btn:hover, .action-btn:focus {
background: #e9ecef;
border-color: #007bff;
color: #007bff;
}
.action-btn img {
width: 16px;
height: 16px;
}
.product-rating {
margin: 1rem 0;
padding: 1rem;
border: 1px solid #dee2e6;
border-radius: 8px;
}
.star-rating {
display: flex;
gap: 0.25rem;
margin: 0.5rem 0;
}
.star {
width: 20px;
height: 20px;
}
.social-media {
margin: 2rem 0;
padding: 1rem;
background: #f8f9fa;
border-radius: 8px;
}
.social-media a {
display: inline-block;
margin: 0.25rem;
padding: 0.5rem;
border-radius: 4px;
transition: background-color 0.2s ease;
}
.social-media a:hover, .social-media a:focus {
background: #e9ecef;
}
.social-icon {
width: 32px;
height: 32px;
}
.breadcrumb ol {
list-style: none;
display: flex;
gap: 0.5rem;
padding: 0;
margin: 1rem 0;
flex-wrap: wrap;
}
.breadcrumb li::after {
content: " > ";
margin-left: 0.5rem;
color: #6c757d;
}
.breadcrumb li:last-child::after {
content: "";
}
.breadcrumb a {
color: #007bff;
text-decoration: none;
}
.breadcrumb a:hover, .breadcrumb a:focus {
text-decoration: underline;
}
.breadcrumb li[aria-current="page"] {
color: #6c757d;
font-weight: bold;
}
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
@media (max-width: 768px) {
.page-nav {
flex-direction: column;
}
.team-member {
flex-direction: column;
text-align: center;
}
.document-actions {
text-align: center;
}
.action-btn {
display: flex;
justify-content: center;
margin: 0.5rem 0;
}
}
</style>
Magyarázat: Minden oldal ugyanazokat a link szövegeket és alt attribútumokat használja ugyanazokra a funkciókra, így a felhasználók mindig tudják, mit várhatnak.
4. Globális komponensek konzisztens címkézéssel
<!-- GLOBÁLIS KOMPONENS TÁRHÁZ -->
<script>
// Konzisztens címkék központi konfigurációja
const ConsistentLabels = {
// Gombok
buttons: {
submit: "Űrlap elküldése",
reset: "Űrlap visszaállítása",
save: "Mentés",
cancel: "Mégse",
delete: "Törlés",
edit: "Szerkesztés",
close: "Bezárás",
print: "Nyomtatás",
share: "Megosztás",
download: "Letöltés",
upload: "Feltöltés",
search: "Keresés",
filter: "Szűrés",
sort: "Rendezés",
refresh: "Frissítés",
back: "Vissza",
next: "Következő",
previous: "Előző",
play: "Lejátszás",
pause: "Szünet",
stop: "Megállítás"
},
// Linkek
links: {
home: "Főoldal",
about: "Rólunk",
services: "Szolgáltatások",
products: "Termékek",
portfolio: "Portfólió",
blog: "Blog",
contact: "Kapcsolat",
login: "Bejelentkezés",
logout: "Kijelentkezés",
register: "Regisztráció",
profile: "Profil",
settings: "Beállítások",
help: "Súgó",
faq: "Gyakori kérdések",
terms: "Felhasználási feltételek",
privacy: "Adatvédelmi nyilatkozat"
},
// Ikonok
icons: {
menu: "Menü megnyitása",
menuClose: "Menü bezárása",
search: "Keresés megnyitása",
cart: "Bevásárlókosár megtekintése",
user: "Felhasználói profil",
notification: "Értesítések megtekintése",
settings: "Beállítások megnyitása",
help: "Súgó megnyitása"
},
// Képek
images: {
logo: "Weboldal logója",
avatar: "Felhasználói profilkép",
product: "Termék képe",
thumbnail: "Előnézeti kép"
}
};
// Konzisztens komponens generátor
class ConsistentComponents {
// Konzisztens gomb létrehozása
static createButton(type, additionalClasses = '', onclick = null) {
const label = ConsistentLabels.buttons[type];
if (!label) {
console.error(`Ismeretlen gomb típus: ${type}`);
return null;
}
const button = document.createElement('button');
button.type = type === 'submit' ? 'submit' : 'button';
button.className = `btn btn-${type} ${additionalClasses}`.trim();
button.setAttribute('aria-label', label);
button.textContent = this.getButtonText(type);
if (onclick) {
button.addEventListener('click', onclick);
}
return button;
}
// Konzisztens link létrehozása
static createLink(type, href = '#', additionalClasses = '') {
const text = ConsistentLabels.links[type];
if (!text) {
console.error(`Ismeretlen link típus: ${type}`);
return null;
}
const link = document.createElement('a');
link.href = href;
link.className = `link link-${type} ${additionalClasses}`.trim();
link.textContent = text;
return link;
}
// Konzisztens ikon gomb létrehozása
static createIconButton(iconType, additionalClasses = '', onclick = null) {
const label = ConsistentLabels.icons[iconType];
if (!label) {
console.error(`Ismeretlen ikon típus: ${iconType}`);
return null;
}
const button = document.createElement('button');
button.type = 'button';
button.className = `icon-btn icon-btn-${iconType} ${additionalClasses}`.trim();
button.setAttribute('aria-label', label);
// SVG ikon hozzáadása
const svg = this.createSVGIcon(iconType);
if (svg) {
button.appendChild(svg);
}
if (onclick) {
button.addEventListener('click', onclick);
}
return button;
}
// SVG ikon létrehozása
static createSVGIcon(iconType) {
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
svg.setAttribute('aria-hidden', 'true');
svg.setAttribute('width', '24');
svg.setAttribute('height', '24');
svg.setAttribute('viewBox', '0 0 24 24');
svg.setAttribute('fill', 'none');
svg.setAttribute('stroke', 'currentColor');
svg.setAttribute('stroke-width', '2');
const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
// Egyszerű SVG útvonalak
const iconPaths = {
menu: 'M3 12h18M3 6h18M3 18h18',
menuClose: 'M18 6L6 18M6 6l12 12',
search: 'M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z',
cart: 'M3 3h2l.4 2M7 13h10l4-8H5.4m0 0L7 13m0 0l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17',
user: 'M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2M12 11a4 4 0 100-8 4 4 0 000 8z',
notification: 'M18 8A6 6 0 006 8c0 7-3 9-3 9h18s-3-2-3-9M13.73 21a2 2 0 01-3.46 0',
settings: 'M12 15a3 3 0 100-6 3 3 0 000 6zM19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 010 2.83 2 2 0 01-2.83 0l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 01-2 2 2 2 0 01-2-2v-.09A1.65 1.65 0 009 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 01-2.83 0 2 2 0 010-2.83l.06-.06a1.65 1.65 0 00.33-1.82 1.65 1.65 0 00-1.51-1H3a2 2 0 01-2-2 2 2 0 012-2h.09A1.65 1.65 0 004.6 9a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 010-2.83 2 2 0 012.83 0l.06.06a1.65 1.65 0 001.82.33H9a1.65 1.65 0 001-1.51V3a2 2 0 012-2 2 2 0 012 2v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 012.83 0 2 2 0 010 2.83l-.06.06a1.65 1.65 0 00-.33 1.82V9a1.65 1.65 0 001.51 1H21a2 2 0 012 2 2 2 0 01-2 2h-.09a1.65 1.65 0 00-1.51 1z',
help: 'M9.09 9a3 3 0 015.83 1c0 2-3 3-3 3M12 17h.01'
};
if (iconPaths[iconType]) {
path.setAttribute('d', iconPaths[iconType]);
svg.appendChild(path);
}
return svg;
}
// Gomb szöveg meghatározása
static getButtonText(type) {
const buttonTexts = {
submit: "Küldés",
reset: "Törlés",
save: "Mentés",
cancel: "Mégse",
delete: "Törlés",
edit: "Szerkesztés",
close: "Bezárás",
print: "Nyomtatás",
share: "Megosztás",
download: "Letöltés",
upload: "Feltöltés",
search: "Keresés",
filter: "Szűrés",
sort: "Rendezés",
refresh: "Frissítés",
back: "Vissza",
next: "Következő",
previous: "Előző",
play: "Lejátszás",
pause: "Szünet",
stop: "Megállítás"
};
return buttonTexts[type] || type;
}
// Konzisztens navigáció létrehozása
static createNavigation(navType, items, currentPath = '') {
const nav = document.createElement('nav');
nav.setAttribute('role', 'navigation');
nav.setAttribute('aria-label', this.getNavLabel(navType));
nav.className = `navigation navigation-${navType}`;
const ul = document.createElement('ul');
ul.className = 'nav-list';
items.forEach(item => {
const li = document.createElement('li');
li.className = 'nav-item';
const link = document.createElement('a');
link.href = item.href;
link.textContent = ConsistentLabels.links[item.type] || item.text;
link.className = 'nav-link';
if (item.href === currentPath) {
link.setAttribute('aria-current', 'page');
link.className += ' nav-link-current';
}
li.appendChild(link);
ul.appendChild(li);
});
nav.appendChild(ul);
return nav;
}
// Navigáció címke meghatározása
static getNavLabel(navType) {
const navLabels = {
main: "Főnavigáció",
user: "Felhasználói navigáció",
footer: "Lábléc navigáció",
breadcrumb: "Breadcrumb navigáció",
secondary: "Másodlagos navigáció"
};
return navLabels[navType] || "Navigáció";
}
}
// Használati példák
document.addEventListener('DOMContentLoaded', function() {
// Konzisztens gombok létrehozása
const formContainer = document.getElementById('form-actions');
if (formContainer) {
const submitBtn = ConsistentComponents.createButton('submit', 'btn-primary');
const resetBtn = ConsistentComponents.createButton('reset', 'btn-secondary');
formContainer.appendChild(submitBtn);
formContainer.appendChild(resetBtn);
}
// Konzisztens ikon gombok létrehozása
const toolbarContainer = document.getElementById('toolbar');
if (toolbarContainer) {
const menuBtn = ConsistentComponents.createIconButton('menu', 'mobile-only', () => {
console.log('Menü megnyitva');
});
const searchBtn = ConsistentComponents.createIconButton('search', '', () => {
console.log('Keresés megnyitva');
});
const cartBtn = ConsistentComponents.createIconButton('cart', '', () => {
console.log('Kosár megnyitva');
});
toolbarContainer.appendChild(menuBtn);
toolbarContainer.appendChild(searchBtn);
toolbarContainer.appendChild(cartBtn);
}
// Konzisztens navigáció létrehozása
const navContainer = document.getElementById('main-navigation');
if (navContainer) {
const navItems = [
{ type: 'home', href: '/fooldal' },
{ type: 'products', href: '/termekek' },
{ type: 'about', href: '/rolunk' },
{ type: 'contact', href: '/kapcsolat' }
];
const navigation = ConsistentComponents.createNavigation('main', navItems, window.location.pathname);
navContainer.appendChild(navigation);
}
});
</script>
<!-- HTML struktúra a komponensekhez -->
<div class="page-layout">
<header>
<div class="logo">
<img src="logo.png" alt="Weboldal logója">
</div>
<div id="toolbar" class="toolbar"></div>
<div id="main-navigation"></div>
</header>
<main>
<h1>Konzisztens komponensek</h1>
<form>
<div class="form-group">
<label for="example-input">Példa mező:</label>
<input type="text" id="example-input" name="example">
</div>
<div id="form-actions" class="form-actions"></div>
</form>
</main>
</div>
<style>
/* Konzisztens stílusok */
.btn {
padding: 0.5rem 1rem;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 1rem;
transition: all 0.2s ease;
margin: 0.25rem;
}
.btn-primary {
background: #007bff;
color: white;
}
.btn-secondary {
background: #6c757d;
color: white;
}
.btn:hover, .btn:focus {
opacity: 0.9;
outline: 2px solid #007bff;
outline-offset: 2px;
}
.icon-btn {
background: none;
border: 1px solid #dee2e6;
border-radius: 4px;
padding: 0.5rem;
cursor: pointer;
transition: all 0.2s ease;
margin: 0.25rem;
}
.icon-btn:hover, .icon-btn:focus {
background: #f8f9fa;
border-color: #007bff;
outline: 2px solid #007bff;
outline-offset: 2px;
}
.icon-btn svg {
display: block;
width: 24px;
height: 24px;
}
.toolbar {
display: flex;
gap: 0.5rem;
align-items: center;
}
.navigation {
margin: 1rem 0;
}
.nav-list {
list-style: none;
display: flex;
gap: 1rem;
padding: 0;
margin: 0;
flex-wrap: wrap;
}
.nav-link {
text-decoration: none;
padding: 0.5rem 1rem;
color: #495057;
background: #f8f9fa;
border-radius: 4px;
transition: all 0.2s ease;
}
.nav-link:hover, .nav-link:focus {
background: #e9ecef;
color: #007bff;
}
.nav-link-current {
background: #007bff;
color: white;
}
.form-group {
margin: 1rem 0;
}
.form-group label {
display: block;
font-weight: bold;
margin-bottom: 0.5rem;
}
.form-group input {
width: 100%;
padding: 0.5rem;
border: 1px solid #ccc;
border-radius: 4px;
}
.form-actions {
margin-top: 1rem;
}
@media (max-width: 768px) {
.mobile-only {
display: block;
}
.nav-list {
flex-direction: column;
}
.toolbar {
justify-content: space-between;
width: 100%;
}
}
@media (min-width: 769px) {
.mobile-only {
display: none;
}
}
</style>
Magyarázat: Egy központi komponens rendszer biztosítja, hogy minden oldal ugyanazokat a címkéket és aria-label értékeket használja az azonos funkciójú elemekhez.
Rossz gyakorlatok
Különböző címkék ugyanahhoz a funkcióhoz
<!-- FŐOLDAL - "Mentés" gomb -->
<button type="submit" aria-label="Mentés">Mentés</button>
<!-- PROFIL OLDAL - HIBÁS: "Tárolás" gomb ugyanahhoz a funkcióhoz -->
<button type="submit" aria-label="Tárolás">Tárolás</button>
<!-- BEÁLLÍTÁSOK OLDAL - HIBÁS: "Elmentés" gomb -->
<button type="submit" aria-label="Elmentés">Elmentés</button>
<!-- ŰRLAP OLDAL - HIBÁS: "Küldés" gomb mentéshez -->
<button type="submit" aria-label="Küldés">Küldés</button>
Probléma: A felhasználók összezavarodnak, mert nem tudják, hogy ezek a gombok mind ugyanazt a mentési funkciót látják el.
Hiányzó vagy inkonzisztens ARIA címkék ikonokon
<!-- FŐOLDAL - megfelelő aria-label -->
<button aria-label="Menü megnyitása">
<svg><!-- hamburger ikon --></svg>
</button>
<!-- TERMÉKEK OLDAL - HIBÁS: hiányzó aria-label -->
<button>
<svg><!-- hamburger ikon --></svg>
</button>
<!-- KAPCSOLAT OLDAL - HIBÁS: különböző aria-label -->
<button aria-label="Navigáció kinyitása">
<svg><!-- hamburger ikon --></svg>
</button>
<!-- BLOG OLDAL - HIBÁS: ismét más aria-label -->
<button aria-label="Menüsáv megjelenítése">
<svg><!-- hamburger ikon --></svg>
</button>
Probléma: A képernyőolvasó felhasználók nem tudják megjegyezni, hogyan hivatkoznak ugyanarra a funkcióra különböző oldalakon.
Bizonytalan vagy különböző link szövegek ugyanahhoz a célhoz
<!-- FŐOLDAL navigáció -->
<nav>
<a href="/kapcsolat">Kapcsolat</a>
<a href="/rolunk">Rólunk</a>
</nav>
<!-- SZOLGÁLTATÁSOK OLDAL - HIBÁS: különböző szövegek -->
<nav>
<a href="/kapcsolat">Vegye fel velünk a kapcsolatot</a> <!-- Túl hosszú és más -->
<a href="/rolunk">Cégünkről</a> <!-- Más szöveg -->
</nav>
<!-- TERMÉKEK OLDAL - HIBÁS: ismét más szövegek -->
<nav>
<a href="/kapcsolat">Írjon nekünk</a> <!-- Más szöveg -->
<a href="/rolunk">Bemutatkozás</a> <!-- Más szöveg -->
</nav>
<!-- BLOG OLDAL - HIBÁS: rövidítések -->
<nav>
<a href="/kapcsolat">Kontakt</a> <!-- Rövidítés -->
<a href="/rolunk">Info</a> <!-- Félreérthető rövidítés -->
</nav>
Probléma: A felhasználók nem tudják megjegyezni, melyik link vezet hova, mert minden oldalon más-más szöveggel találkoznak.
Inkonzisztens képleírások ugyanazon funkciókhoz
<!-- FŐOLDAL - PDF letöltés gomb -->
<button>
<img src="download-icon.png" alt="PDF letöltése">
<span>Letöltés</span>
</button>
<!-- DOKUMENTÁCIÓ OLDAL - HIBÁS: más alt szöveg -->
<button>
<img src="download-icon.png" alt="Fájl mentése"> <!-- Más leírás -->
<span>Letöltés</span>
</button>
<!-- TERMÉKEK OLDAL - HIBÁS: ismét más alt szöveg -->
<button>
<img src="download-icon.png" alt="Dokumentum letöltése"> <!-- Más leírás -->
<span>Letöltés</span>
</button>
<!-- HÍREK OLDAL - HIBÁS: hiányzó alt szöveg -->
<button>
<img src="download-icon.png" alt=""> <!-- Üres alt -->
<span>Letöltés</span>
</button>
Probléma: A képernyőolvasók különböző leírásokat mondanak ugyanarra az ikonra, ami zavart okoz.
Dinamikus tartalom inkonzisztens címkézéssel
<script>
// HIBÁS: véletlenszerű címkék generálása
function createActionButton(action, context) {
const button = document.createElement('button');
// HIBÁS: kontextus alapján változó címkék
let label;
switch(context) {
case 'product':
if (action === 'delete') {
label = 'Termék eltávolítása'; // Más címke
}
break;
case 'user':
if (action === 'delete') {
label = 'Felhasználó törlése'; // Más címke
}
break;
case 'post':
if (action === 'delete') {
label = 'Bejegyzés törlése'; // Más címke
}
break;
default:
if (action === 'delete') {
label = 'Elem törlése'; // Még egy más címke
}
}
button.setAttribute('aria-label', label);
button.textContent = 'Törlés';
return button;
}
// HIBÁS: időpont alapú címkék
function createTimeBasedButton() {
const hour = new Date().getHours();
const button = document.createElement('button');
if (hour < 12) {
button.setAttribute('aria-label', 'Reggeli mentés'); // HIBÁS
} else if (hour < 18) {
button.setAttribute('aria-label', 'Délutáni mentés'); // HIBÁS
} else {
button.setAttribute('aria-label', 'Esti mentés'); // HIBÁS
}
button.textContent = 'Mentés';
return button;
}
// HIBÁS: felhasználói jogosultság alapú címkék
function createRoleBasedButton(userRole) {
const button = document.createElement('button');
switch(userRole) {
case 'admin':
button.setAttribute('aria-label', 'Admin szerkesztés'); // HIBÁS
break;
case 'editor':
button.setAttribute('aria-label', 'Szerkesztői módosítás'); // HIBÁS
break;
case 'user':
button.setAttribute('aria-label', 'Felhasználói szerkesztés'); // HIBÁS
break;
default:
button.setAttribute('aria-label', 'Egyszerű szerkesztés'); // HIBÁS
}
button.textContent = 'Szerkesztés';
return button;
}
// HIBÁS: nyelvi beállítás figyelmen kívül hagyása
function createMultiLanguageButton(language) {
const button = document.createElement('button');
// HIBÁS: kevert nyelvű címkék
switch(language) {
case 'en':
button.setAttribute('aria-label', 'Save document'); // Angol
button.textContent = 'Mentés'; // Magyar szöveg
break;
case 'de':
button.setAttribute('aria-label', 'Dokument speichern'); // Német
button.textContent = 'Mentés'; // Magyar szöveg
break;
default:
button.setAttribute('aria-label', 'Documento salvato'); // Olasz?!
button.textContent = 'Mentés'; // Magyar szöveg
}
return button;
}
</script>
Probléma: A dinamikusan generált elemek inkonzisztens címkézése miatt a felhasználók nem tudják megjegyezni és kiszámítani a felület viselkedését.
Üres vagy jelentéktelen címkék
<!-- HIBÁS: üres aria-label -->
<button aria-label="">
<svg><!-- ikon --></svg>
</button>
<!-- HIBÁS: jelentéktelen aria-label -->
<button aria-label="gomb">
<svg><!-- ikon --></svg>
</button>
<!-- HIBÁS: generikus alt szöveg -->
<img src="action-icon.png" alt="ikon">
<!-- HIBÁS: fájlnév mint alt szöveg -->
<img src="save_icon_24px.png" alt="save_icon_24px.png">
<!-- HIBÁS: technikai információ alt szövegben -->
<img src="print-btn.jpg" alt="24x24 pixel print button image">
<!-- HIBÁS: ugyanaz a címke minden gombra -->
<button aria-label="művelet">Mentés</button>
<button aria-label="művelet">Törlés</button>
<button aria-label="művelet">Szerkesztés</button>
<!-- HIBÁS: nem informatív link szövegek -->
<a href="/dokumentacio">kattintson ide</a>
<a href="/letoltes">tovább</a>
<a href="/info">bővebben</a>
<a href="/regisztracio">itt</a>
Probléma: Az üres, generikus vagy jelentéktelen címkék nem adnak hasznos információt a felhasználóknak arról, hogy az adott elem mit csinál.
Források
Iratkozz fel hírlevelünkre!
Amennyiben szeretnél első kézből értesülni az új bejegyzésekről, iratkozz fel hírlevelünkre!