WordPress: menu con stile alterno per elementi pari e dispari

Tipicamente un menu di navigazione è organizzato come una serie di elementi (li) di un elenco puntato (ul). Anche WordPress adotta questa convenzione per l’elaborazione dei menu di navigazione.

Se uno volesse presentare il menu di WordPress con elementi a colori alterni potrebbe intervenire su più fronti:

  • definendo delle regole di stile CSS3, che ritengo  la soluzione più corretta, se tutti i browser consentissero di utilizzare le regole necessarie al nostro scopo,
  • alterando il DOM tramite Javascript, che per quanto possa garantire la compatibilità con tutti i browser non garantisce che funzioni su tutti i client (dove per esempio i Javascript sono disattivati). Inoltre la ritengo la soluzione meno indicata in quanto in Javascript dovrebbe risiedere la logica applicativa, non la logica “rappresentativa” dell’informazione,
  • ultima alternativa è implementare un piccolo script PHP per manipolare la presentazione del menu di navigazione.

Regole CSS3 per il pari e dispari.

Assumendo che il menu di navigazione di WordPress abbia come classe nav-menu, il discorso sarebbe facilmente affrontabile con le seguenti regole da applicare nel foglio di stile del tema:

.nav-menu li:nth-child(odd){

	background-color: red;
	color: black;
}

.nav-menu li:nth-child(even){
	background-color: yellow;
	color: black;
}

Però gli eventuali primi elementi dei sottomenu degli elementi dispari avrebbero lo stesso colore del contenitore, quindi, per risolvere il problema dovremmo implementare le regole nel seguente modo:

.nav-menu li:nth-child(odd),
.nav-menu li:nth-child(even) li:nth-child(even){

	background-color: red;
	color: black;
}

.nav-menu li:nth-child(even),
.nav-menu li:nth-child(even) li:nth-child(odd){
	background-color: yellow;
	color: black;
}

in modo da invertire la sequenza alernata nei sottomenu.

Effettivamente questa soluzione è semplice quanto immediata, leggera e non invasiva. Sarebbe da preferire a qualsiasi altra soluzione che segue in questo articolo, però non garantisce la retrocompatibilità con alcuni browser che come qualcuno direbbe “sono duri a morire!”

Alternativa Javascript

L’alternativa Javascript è quella meno raccomandata perchè seppur sia possibile assicurare la compatibilità crossbrowser, ha la conseguenza che Javascript potrebbe essere stato bloccato dagli amministratori di sistema per siti esterni alla rete aziendale oppure per volontà diretta dell’utente.

Assumendo comunque che Javascript sia abilitato e di essere in presenza di browser che non supportano le regole CSS3 proposte in precedenza dobbiamo valutare se utilizzare jQuery o intervenire direttamente sul DOM a livello più basso. Perchè se jQuery fosse già disponibile sulla pagina, forse potrebbe valerne la pena utilizzarlo. In alternativa sarebbe la soluzione meno indicata in assoluto perchè si tratterebbe di includere jQuery sulla pagina, con ovvi rallentamenti in fase di caricamento del sito. Per onor di cronaca seguono le due alternative con l’utilizzo di jQuery e di accesso diretto al DOM.

Elementi alterni con jQuery

$('.nav-menu li').each(function(){
    if(  $(this).is(':even') ) $(this).addClass('menu-item-even');
    else $(this).addClass('menu-item-odd');
});

Ovvero si verifica che l’elemento su cui è posizionato il ciclo  sia pari o dispari e viene applicata una classe menu-item-even oppure menu-item-odd.

Ovviamente anche in questo caso gli elementi dei sotto menu non avranno alternanza rispetto al genitore ma solo rispetto a se stessi quindi dovremmo applicare il codice CSS definito alla fine di questo articolo per assicurarci un’alternanza sia a livello di menu principale che di sottomenu.

Elementi alterni senza jQuery

var lis = document.getElementsByTagName('li'),
    lastParent = null,
    elementIndex = 0;

    for(var i = 0; i < lis.length; i++){
        var currentParent = lis[i].parentNode;
        if(/nav\-menu/.test( currentParent.className ) ){
            lastParent = currentParent;
            if(currentParent != lastParent){
                elementIndex = 1;
            } else {
               elementIndex += 1;
            }
            lis[i].className += " " + ((elementIndex%2)?'even':'odd');
            lis[i].className = lis[i].className.trim();
        }
    }

Come è possibile rendersi conto la complessità del codice per colorare gli elementi di primo livello di un menu di navigazione diventerebbe diventerebbe ulteriormente complesso in quanto non tutti i browser supportano il metodo del documento getElementsByClassName o il metodo querySelect con ovvie complicazioni per selezionare solo gli elementi li nella struttura di ul.nav-menu. Quindi se non strettamente necessaria questa soluzione, meglio optare per la prima (CSS3) oppure per la prossima (PHP).

Elementi alternati tramite wp_get_nav_menu_items

L’ultima soluzione è applicabile solo se si ha accesso al codice PHP del tema di WordPress e se si ha dimestichezza con un po’ di PHP. Tuttavia questa è la soluzione che garantisce la massima compatibilità con tutti i browser anche se Javascript risulta non attivo.

add_filter('wp_get_nav_menu_items', 'makeMenuItemsOddEven');
function makeMenuItemsOddEven($menuItems){
	$menuParentsId = array();

	foreach($menuItems as $index => $menuItem){
		$parentId = $menuItem->menu_item_parent;
		if(!isset($menuParentsId[$parentId])) {
			$menuParentsId[$parentId] = 1;
		}
		$menuParentsId[$parentId]+=1;
		$theClass= (( ($menuParentsId[$parentId] % 2) == 0 ) ? 'menu-item-even' : 'menu-item-odd');

		if( !in_array( $menuItem->classes,$theClass, true) ) $menuItems[$index]->classes[] = $theClass;
	}
	return $menuItems;
}

Inserendo questo codice PHP nel file functions.php del proprio tema si otterrà come risultato che ciascun elemento di un submenu avrà una classe even oppure odd.

A questo punto bisognerà intervenire sul foglio di stile prendendo spunto dal CSS presentato nella prima ipotesi e definire quattro regole così definite:

.menu-item-odd,
.menu-item-even .menu-item-even{

	background-color: red;
	color: black;
}

.menu-item-even,
.menu-item-even .menu-item-odd{
	background-color: yellow;
	color: black;
}

E voi, come risolvereste il problema?


Commenti

2 risposte a “WordPress: menu con stile alterno per elementi pari e dispari”

  1. Hey, ma sei un copione! :D Ho scritto un simile articolo sul mio sito per quanto riguarda le righe delle tabelle. Interessanti i metodi alternativi al css3.

    1. Ad essere sincero mi era sfuggito questo articolo, altrimenti lo avrei menzionato come già fatto altre volte ;)