Language switcher
A language switcher component, typically used as a header widget.
The language switcher shows a link that opes a popup with a selection of languages or domains a user can choose from. It is usually found close to the site main navigation areas. The component is not tied to header styles.
The component is divided in 2 parts: the toggle button and the panel.
Toggle button location
The language switcher toggle button can be placed anywhere in the code, but the usual places are the header widgets area and the header burger menu widgets area.
When placed on the burger menu, the toggle will expand to match the burger menu navigation links.
The toggle content may be the currently selected language, but for accessibility purposes it is good to add more text explaining what it does: "Open language selection popup".
You can do that with sr-only
text or with aria-label
on the button. Bear in mind that aria-label
replaces any current label the button has, so make sure to also include the currently selected language
in it.
<div class="flix-language-switcher">
<button class="flix-language-switcher__toggle" type="button">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/gb.svg" alt="United Kingdom"/>
English
<span class="flix-sr-only">Open language selection</span>
</button>
</div>
Popup content
Inside the popup element make sure to include:
- The close button must be the first interactive element of the popup body (important for the plugin tab trap);
- The close button must have an accessible aria-label;
- Each
section
for the domains should be connected with their respective title usingaria-labelledby
; - Each language must have a proper
lang
attribute, given they are going to be written in their own language, this enables screen readers to choose the correct speech; - Identify the country of a given language with the flag by using the
alt
attribute, this way users can identify different domains that have the same language (e.g.: English US and English UK); - The links can be switched to buttons by just changing the HTML element;
Display Options
It is possible to have multiple sections (flix-language-switcher-popup__region
elements) within the popup.
This is specifically useful if you want to categorise countries/languages by continent or other groups.
You can switch between the "row" based and "column" based order of items within the region with a flix-language-switcher-popup__region--columns
CSS class name.
The items are ordered in rows by default.
Users tend to prefer the column based sorting if many items are presented in the list. However, as a best practice we recommend splitting longer lists into smaller categories when possible so the items are easier to find.
Bellow examples illustrate both options.
Column based sorting
<div class="flix-language-switcher">
<button aria-expanded="false" type="button" class="flix-language-switcher__toggle" data-popup="language-selection-popup-column-layout" data-firstfocusable="close-button-column-layout" data-lastfocusable="last-focusable-item-column-layout">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/de.svg" alt="United Kingdom"/>
Deutsch
<span class="flix-sr-only">Open language selection</span>
</button>
</div>
<div id="language-selection-popup-column-layout" class="flix-language-switcher-popup" aria-label="Language selection" hidden="">
<div class="flix-language-switcher-popup__body">
<button id="close-button-column-layout" type="button" aria-label="Close language selection" class="flix-language-switcher-popup__close flix-btn flix-btn--square flix-btn--md flix-btn--link"></button>
<section aria-labelledby="europe-domains" class="flix-language-switcher-popup__region flix-language-switcher-popup__region--columns">
<ul class="flix-language-switcher-popup__list">
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="bg">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/bg.svg" alt="Bulgaria"/>
Български
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="de" aria-current="true">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/de.svg" alt="Germany"/>
Deutsch
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="de-ch">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/ch.svg" alt="Switzerland"/>
Deutsch
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="de-at">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/at.svg" alt="Austria"/>
Deutsch
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="en-gb">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/gb.svg" alt="England"/>
English
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="es">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/es.svg" alt="Spain"/>
Español
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="fr">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/fr.svg" alt="France"/>
Français
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="fr-ch">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/ch.svg" alt="Switzerland"/>
Français
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="fr-be">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/be.svg" alt="Belgium"/>
Français
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="it">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/it.svg" alt="Italy"/>
Italiano
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="it-ch">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/ch.svg" alt="Switzerland"/>
Italiano
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="mk">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/mk.svg" alt="Macedonia"/>
Македонски
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="pl">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/pl.svg" alt="Poland"/>
Polski
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="pt-pt">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/pt.svg" alt="Portugal"/>
Português
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="rs">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/rs.svg" alt="Serbia"/>
Srpski
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="fi">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/fi.svg" alt="Finland"/>
Suomi
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="se">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/se.svg" alt="Sweden"/>
Svenska
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" id="last-focusable-item-column-layout" lang="ua">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/ua.svg" alt="Ukraine"/>
Укpaїнcькa
</a>
</li>
</ul>
</section>
</div>
<div class="flix-overlay"></div>
</div>
Row based sorting
<div class="flix-language-switcher">
<button aria-expanded="false" type="button" class="flix-language-switcher__toggle" data-popup="language-selection-popup-row-layout" data-firstfocusable="close-button-row-layout" data-lastfocusable="last-focusable-item-row-layout">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/gb.svg" alt="United Kingdom"/>
English
<span class="flix-sr-only">Open language selection</span>
</button>
</div>
<div id="language-selection-popup-row-layout" class="flix-language-switcher-popup" aria-label="Language selection" hidden="">
<div class="flix-language-switcher-popup__body">
<button id="close-button-row-layout" type="button" aria-label="Close language selection" class="flix-language-switcher-popup__close flix-btn flix-btn--square flix-btn--md flix-btn--link"></button>
<section aria-labelledby="europe-domains" class="flix-language-switcher-popup__region">
<ul class="flix-language-switcher-popup__list">
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="bg">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/bg.svg" alt="Bulgaria"/>
Български
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="de">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/de.svg" alt="Germany"/>
Deutsch
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="de-ch">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/ch.svg" alt="Switzerland"/>
Deutsch
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="de-at">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/at.svg" alt="Austria"/>
Deutsch
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="en-gb" aria-current="true">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/gb.svg" alt="England"/>
English
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="es">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/es.svg" alt="Spain"/>
Español
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="fr">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/fr.svg" alt="France"/>
Français
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="fr-ch">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/ch.svg" alt="Switzerland"/>
Français
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="fr-be">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/be.svg" alt="Belgium"/>
Français
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="it">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/it.svg" alt="Italy"/>
Italiano
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="it-ch">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/ch.svg" alt="Switzerland"/>
Italiano
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="mk">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/mk.svg" alt="Macedonia"/>
Македонски
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="pl">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/pl.svg" alt="Poland"/>
Polski
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="pt-pt">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/pt.svg" alt="Portugal"/>
Português
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="rs">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/rs.svg" alt="Serbia"/>
Srpski
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="fi">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/fi.svg" alt="Finland"/>
Suomi
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="se">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/se.svg" alt="Sweden"/>
Svenska
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" id="last-focusable-item-row-layout" lang="ua">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/ua.svg" alt="Ukraine"/>
Укpaїнcькa
</a>
</li>
</ul>
</section>
</div>
<div class="flix-overlay"></div>
</div>
Column based sorting with multiple categories
<div class="flix-language-switcher">
<button aria-expanded="false" type="button" class="flix-language-switcher__toggle" data-popup="language-selection-popup-1" data-firstfocusable="close-button" data-lastfocusable="last-focusable-item">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/eu.svg" alt="United Kingdom"/>
English
<span class="flix-sr-only">Open language selection</span>
</button>
</div>
<div id="language-selection-popup-1" class="flix-language-switcher-popup" aria-label="Language selection" hidden="">
<div class="flix-language-switcher-popup__body">
<button id="close-button" type="button" aria-label="Close language selection" class="flix-language-switcher-popup__close flix-btn flix-btn--square flix-btn--md flix-btn--link"></button>
<section aria-labelledby="suggested-domains" class="flix-language-switcher-popup__region flix-language-switcher-popup__region--columns">
<h2 class="flix-h4 flix-h4--section-header" id="suggested-domains">Suggested domains</h2>
<ul class="flix-language-switcher-popup__list">
<li class="flix-language-switcher-popup__item">
<button type="button" class="flix-language-switcher-popup__link">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/de.svg" alt="Germany"/>
Deutsch
</button>
</li>
<li class="flix-language-switcher-popup__item">
<button type="button" class="flix-language-switcher-popup__link" aria-current="true">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/eu.svg" alt="European Union"/>
English
</button>
</li>
</ul>
</section>
<section aria-labelledby="europe-domains" class="flix-language-switcher-popup__region flix-language-switcher-popup__region--columns">
<h2 class="flix-h4 flix-h4--section-header" id="europe-domains">Europe</h2>
<ul class="flix-language-switcher-popup__list">
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="de">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/de.svg" alt="Germany"/>
Deutsch
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="de-ch">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/ch.svg" alt="Switzerland"/>
Deutsch
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="de-at">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/at.svg" alt="Austria"/>
Deutsch
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="en-gb">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/gb.svg" alt="England"/>
English
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="es">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/es.svg" alt="Spain"/>
Español
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="fr">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/fr.svg" alt="France"/>
Français
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="fr-ch">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/ch.svg" alt="Switzerland"/>
Français
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="fr-be">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/be.svg" alt="Belgium"/>
Français
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="it">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/it.svg" alt="Italy"/>
Italiano
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="it-ch">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/ch.svg" alt="Switzerland"/>
Italiano
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="pl">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/pl.svg" alt="Poland"/>
Polski
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="pt-pt">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/pt.svg" alt="Portugal"/>
Português
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="rs">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/rs.svg" alt="Serbia"/>
Srpski
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="fi">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/fi.svg" alt="Finland"/>
Suomi
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="se">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/se.svg" alt="Sweden"/>
Svenska
</a>
</li>
</ul>
<ul class="flix-language-switcher-popup__list">
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="ua">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/ua.svg" alt="Ukraine"/>
Укpaїнcькa
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="mk">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/mk.svg" alt="Macedonia"/>
Македонски
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="bg">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/bg.svg" alt="Bulgaria"/>
Български
</a>
</li>
</ul>
</section>
<section aria-labelledby="america-domains" class="flix-language-switcher-popup__region flix-language-switcher-popup__region--columns">
<h2 class="flix-h4 flix-h4--section-header" id="america-domains">North & South America</h2>
<ul class="flix-language-switcher-popup__list">
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="en-us">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/us.svg" alt="United States"/>
English
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="es-us">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/us.svg" alt="United States"/>
Español
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="zh-us">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/us.svg" alt="United States"/>
中文
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="en-ca">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/ca.svg" alt="Canada"/>
English
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" href="#" lang="fr-ca">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/ca.svg" alt="Canada"/>
Français
</a>
</li>
<li class="flix-language-switcher-popup__item">
<a class="flix-language-switcher-popup__link" id="last-focusable-item" href="#" lang="pt-br">
<img class="flix-language-switcher__flag" src="https://honeycomb-assets.hive.flixbus.com/honeycomb-flags-static/2.0.0/svg/br.svg" alt="Brasil"/>
Português
</a>
</li>
</ul>
</section>
</div>
<div class="flix-overlay"></div>
</div>
Using the popup plugin
Using the popup plugin is easy and will handle most of the javascript hard work for you:
- Include the plugin from our CDN at the end of your page:
<script src="https://honeycomb.flixbus.com/dist/{VERSION_TAG}/js/popup.js"></script>
- Initialize the plugin:
document.addEventListener("DOMContentLoaded", function() { popup.init(); });
Building the language switcher popup:
- Add an id to the
flix-language-switcher-popup
element and initialize it with thehidden
attribute, so it's closed; - Use the popup id and connect it to the toggle using
data-popup="{THE_POPUP_ID}"
; - In order for the plugin to work you need to tell it what are the first and last focusable elements of the popup body:
- Give each of them an id;
- Pass them to the toggle using
data-firstFocusable="{THE_ELEMENT_ID}"
anddata-lastFocusable="{THE_ELEMENT_ID}"
; - It is recommended that the close button be the first focusable element of the popup body;
- Accessibility guidelines dictates that all dialogs must have a label:
- You can either give the popup and
aria-label
; - Or you can associate the popup title with and
id
andaria-labelledby
;
- The plugin will take care of the following:
- Adding the right
role
andaria-modal
values to the popup element; - Toggling the
hidden
attribute to show and hide the popup; - Adding ESC key press support for closing the popup with the keyboard;
- Creating a tab trap that doesn't allow the user to tab away from the popup (cycles tabs from the first and the last focusable items);
- Adding the close button click handler if a close button is present;
Feel free to inspect the examples above if your need more details on how it works.
Making it work without the plugin
- to identify the language switcher popup as a dialog landmark, add the following attributes popup element:
role="dialog"
aria-modal="true"
;
- To show and hide the popup, toggle the
hidden
attribute from the popup element; - When opening the popup:
- Remove the
hidden
attribute; - Set focus to the
__close
button, which must be the first focusable element; - Create a tab trap that cycles the tab order between the first and last focusable element;
- When closing the popup:
- Users must be able to close the popup by pressing the
__close
button as well as pressing the ESC key on the keyboard; - Add the
hidden
attribute; - Set focus back to the
__toggle
button, where the interaction started;