28117 sujets

CSS et mise en forme, CSS3

Pages :
Bonjour à tous en ce beau mercredi férié.

J'ai commencé un menu dépliant en CSS sauce Javascript.

Les titres de menus font office de "liens de pliage/dépliage", et tout marche à merveille à la souris. Le hic est que lors de la navigation au clavier, les titres des menus n'étant pas des liens <a>, mais de simples <divs> avec comportement javascript et cursor:pointer, ils ne sont pas pris en compte lors de l'appui de la touche tabulation et il est donc impossible de plier/déplier quoique se soit.
PS : oui, je vais remplacer les divs de titres menu par des balises <h>.

Que faire ? Merci Smiley smile

Précision 1: Le but de ce menu est de plier/minimiser automatiquement au chargement de la page les menus auxquels le visiteur n'a pas accès suivant son statut de connection (admin ou visiteur). Cette fonctionnalité n'est pas encore programmée.
Je signale que j'ai délaissé les <li> pour structurer mon menu à cause de trop de problèmes d'affichage entre navigateurs.
Modifié par Ralfman68 (13 Nov 2007 - 20:34)
Salut.

Pourquoi tu n'utilises pas simplement un lien à la place des divs, pour déclencher le déroulement du menu ?
Je n'utilise pas <a> car ce ne sont pas des vrais liens, mais juste une fonctionnalité de la page.
Mais tout compte fait, tu as raison, je crois que c'est encore la meilleure solution de mettre des vrais liens "à vide" avec comportement javascript asocié.
Merci.
Modérateur
Salut,

Tu peux générer les liens via JS afin que l'utilisateur qui ne dispose pas de ce langage ne se retrouve pas avec des liens inutiles...

Personnellement, je procède ainsi :

-> http://koalnet.com/divers/menu-alsa-vertical/

XHTML

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
					  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr">
	<head>
		<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
		<title>Menu vertical Alsacréations (version alpha 0.000001) - koala64</title>
		<link rel="stylesheet" type="text/css" href="styleMenu.css" media="screen, projection" />
		<script type="text/javascript">//<![CDATA[

// Fonction qui doit être chargée en entête de page xhtml et
// qui élimine l'apparition subite des listes du menu
// au chargement de la page
var CacheRapide = function()
{
	document.write('<'+'style type="text/css">');
	document.write('@media screen, projection {');
	document.write('ul li ul { display: none; }');
	document.write('}');
	document.write('<'+'/style>');
}
CacheRapide();

		//]]></script>
		<script type="text/javascript" src="scriptMenu.js"></script>
	</head>
<body>

<!--

.oO° Navigation clavier °Oo.
Fx et IE -> shift+tab : lien précédent / tab : lien suivant
Opera -> a : lien précédent / q : lien suivant

-->

<div id="page">
	<ul id="menus">
		<li>menu1
			<ul>
				<li><a href="#">lien1</a></li>
				<li><a href="#">lien2</a></li>
				<li><a href="#">lien3</a></li>
				<li><a href="#">lien4</a></li>
			</ul>
		</li>
		<li>menu2
			<ul>
				<li><a href="#">lien1</a></li>
				<li><a href="#">lien2</a></li>
				<li><a href="#">lien3</a></li>
			</ul>
		</li>
		<li>menu3
			<ul>
				<li><a href="#">lien1</a></li>
				<li><a href="#">lien2</a></li>
				<li><a href="#">lien3</a></li>
				<li><a href="#">lien4</a></li>
				<li><a href="#">lien5</a></li>
			</ul>
		</li>
		<li>menu4
			<ul>
				<li><a href="#">lien1</a></li>
				<li><a href="#">lien2</a></li>
				<li><a href="#">lien3</a></li>
				<li><a href="#">lien4</a></li>
			</ul>
		</li>
	</ul>
</div>
</body></html>

CSS

/*
	Menu vertical Alsacréations (version alpha 0.000001) - koala64
*/

body
{
	font-family: Verdana, Arial, Helvetica, sans-serif;
	font-size: 100%;
}
#page
{
	position: relative;
	width: 100%;
	padding: 0;
	margin: 0;
}
#menus
{
	padding: 0;
	margin: 0;
}
#menus *
{
	padding: 0;
	margin: 0;
	list-style-type: none;
}
#menus li
{
	display: list-item;
	width: 120px;
	border: 1px solid #000;
	margin-right: 2px;
	margin-bottom: 10px;
	font-size: .9em;
	line-height: 1.3em;
	text-align: center;
	background-color: #EEE;
}
#menus li ul
{
	border-top: 1px solid #000;
}
#menus li ul li
{
	clear: both;
	width: 120px;
	border: 0;
	margin: 0;
	background-color: #EEE;
	text-align: left;
}
#menus li a
{
	text-decoration: none;
	color: #000;
	background-color: #CCC;
	display: block;
	cursor: pointer;
}
#menus li ul a
{
	width: 120px;
	height: 1.6em;
	line-height: 1.6em;
	text-indent: 10px;
	background-color: #EEE;
	cursor: pointer;
}
#menus li ul a:hover
{
	background-color: #58F;
}

/* Classes nécessaires au code Javascript */
.Cache
{
	display: none;
}
.Montre
{
	display: list-item;
}

Javascript

/*
	Menu vertical Alsacréations (version alpha 0.000001) - koala64
*/

var oO =
{
	// Test de passage d'un argument
	_Test: 
		function()
		{
			var iI = arguments.length - 1;
			for(iI; iI >= 0; iI--) if(!arguments[iI]) return false;
			return true;
		},

	// Ajout d'une action sur un événement
	_Connect:
		function(oElem, sEvType, fn, bCapture)
		{
			oElem.addEventListener ?
				oElem.addEventListener(sEvType, fn, bCapture):
				oElem.attachEvent ?
					oElem.attachEvent('on' + sEvType, fn):
					oElem['on' + sEvType] = fn;
		},

	// Affichage des menus
	_Montre:
		function()
		{
			oO._Cache();
			var oList = this.parentNode.getElementsByTagName('ul')[0];
			oList.className = 'Montre';
			this.onclick = oO._Cache;
			return false;
		},
	
	// Masquage des menus
	_Cache:
		function()
		{
			var oMenus = document.getElementById('menus'),
				oUl = oMenus.getElementsByTagName('ul'),
				iI = oUl.length - 1;
			for(iI; iI >= 0; iI--) oUl[iI].className = 'Cache';
			this.onclick = oO._Montre;
			return false;
		},
	
	// Initialisation du menu
	_Menu:
		function()
		{
			oO._Cache();
			var oMenus = document.getElementById('menus'),
				oItem = oMenus.getElementsByTagName('li'),
				iI = oItem.length - 1;
			for(iI; iI >= 0; iI--)
			{
				if(oItem[iI].parentNode.getAttribute('id') == 'menus')
				{
					var oA = document.createElement('a'),
						sTxtLi = oItem[iI].firstChild.nodeValue,
						oTxtA = document.createTextNode(sTxtLi);
					oA.setAttribute('href', '#');
					oA.appendChild(oTxtA);
					oItem[iI].replaceChild(oA, oItem[iI].firstChild);
					oA.onclick = oO._Montre;
				}
			}
		}
};
// Test des méthodes du script et lancement si c'est bon...
oO._Test(document.getElementById, document.getElementsByTagName, document.createElement, document.createTextNode) ?
	oO._Connect(window, 'load', oO._Menu, false):
	false;

Modifié par koala64 (01 Nov 2006 - 11:25)
J'utilise la même solution que toi, koala64.

Le seul inconvénient que je trouve à cette méthode est le comportement lorsque l'utilisateur force l'ouverture du lien dans une nouvelle fenêtre.

N'y aurait-il pas moyen de faire un peu comme Ralfman68 en simulant des liens tout en restant accessible ? Il me semble avoir lu quelque part que l'utilisation de tabindex pouvait être une solution.
Modérateur
mmh... dans ce cas, je verrais plus l'utilisation de cookies pour passer un argument afin que l'ouverture du menu se déroule bien, y compris si ça passe dans une nouvelle fenêtre... à voir... Smiley murf

Cela dit, si tu retrouves un lien concernant les tabindex, ça m'intéresse mais je ne vois pas vraiment à quoi ça va servir...

Une autre chose qu'on peut changer, c'est les onclick en passant par la méthode oO._Connect et en annulant la propagation afin qu'on ne monopolise pas le click sur le lien juste pour l'ouverture/fermeture du menu. Autant avec des mouseover/mouseout/focus/blur, c'est galère, autant là, ça ne devrait pas trop poser de problème... Je n'ai pas encore eu le temps de m'y pencher... Smiley smile
Merci pour ta réponse. Smiley smile

C'est vrai que si l'on peut trouver une utilité au lien en dehors de Javascript (par exemple, pour une catégorie de menu déroulant, un lien vers une page décrivant cette catégorie), autant mettre une url valide dans le href, puisque l'ouverture du lien dans une nouvelle fenêtre ne provoquera pas l'évènement onclick et ouvrira l'url en question.

Mais parfois, quand le lien a été généré par Javascript, on ne peut vraiment pas mettre d'url cohérente et on est obligé d'utiliser "#", ce qui ne décrit pas du tout l'utilité du lien (dans la barre de statut, et pour les screenreaders j'imagine).

Pour ce qui est du tabindex, j'essaierai de retrouver ça. Il me semble que le fait de mettre un tabindex sur un élément qui n'est pas un lien permet de le rendre sélectionnable au clavier, mais je n'en suis pas du tout sûr.
Modérateur
oui, tiens, c'est intéressant mais vu qu'on annule le retour du lien en mettant des return false au sein des méthodes d'ouverture et de fermeture, ça ne doit pas changer grand chose non ? Le lecteur d'écran, il comprend ça (?) Smiley rolleyes Cela dit, je vais regarder quand même... Smiley murf
Modifié par koala64 (01 Nov 2006 - 17:18)
Modérateur
mmh... bon, je viens de faire un test...

Voici le code :
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
                      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr">
	<head>
		<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
		<title>Exemple</title>
		<script type="text/javascript">//<![CDATA[

window.onload = init;

function init()
{
	var objAnchor = document.getElementById('linklike');

	objAnchor.onclick = function(event){return changeLocation(event, fnAlert());};
	objAnchor.onkeypress = function(event){return changeLocation(event, fnAlert());};
}

function fnAlert()
{
	alert ('coucou!');
}

function changeLocation(objEvent, func)
{
	var iKeyCode;

	if (objEvent && objEvent.type == 'keypress')
	{
		if (objEvent.keyCode)
			iKeyCode = objEvent.keyCode;
		else if (objEvent.which)
			iKeyCode = objEvent.which;

		if (iKeyCode != 13 && iKeyCode != 32)
			return true;
	}

	return func;
}

		//]]></script>
	</head>	
	<body>
		<p id="linklike" tabindex="1">View the results of the survey.</p>
		<p>Opera ? [rale]</p>
	</body>
</html>


Sous Firefox, pas de problème...
Sous IE, le tabindex ne fonctionne pas mais on accède quand même au focus au bout d'un moment...
Sous Opera, le seul moyen que j'ai trouvé, c'est de faire Echap+d deux fois puis Entrée, ce qui me donne deux fois l'alerte "coucou !". (J'adoooore Opera ! Smiley biggol )

et surtout... tabindex sur un paragraphe, c'est invalide et ça modifie l'ordre de navigation naturel, ce qui n'est pas forcémment souhaitable...

Conclusion : Crois-tu que ça vaut réellement la peine de continuer dans cette voie ? D'après ce test, je préfère conserver la génération d'un lien dont je bloque la transmission d'url car, jusqu'à preuve du contraire, je ne pense pas que cela pose problème, y compris pour les screenreaders...
Modifié par koala64 (01 Nov 2006 - 18:20)
Je préfère aussi les liens sans url. C'est plus simple, et à priori ça ne posera pas de probleme.
Pour fignoler je pourrai changer le texte de la barre de status "à la Hussarde" (javascript) lors du survol des liens vides.
koala64 a écrit :
Conclusion : Crois-tu que ça vaut réellement la peine de continuer dans cette voie ?
Non, en effet...

Merci d'avoir fait ce test en tout cas !

En fait, la seule chose qui me gêne, comme je le disais, est le cas où l'utilisateur ouvre le lien dans une nouvelle fenêtre, mais en général ça a peu de chance d'arriver s'il est clair pour lui que la fonctionnalité du lien se situe sur la page courante (comme dans le cas du menu déroulant).

Bon allez, une dernière question chiante pour la route. Que pensez-vous de l'utilisation de "javascript:;" plutôt que de "#" comme cible du lien ? Ca a au moins le mérite de rendre l'objectif du lien clair.
Modifié par Eldebaran (01 Nov 2006 - 18:38)
Les possibilités que je vois sont :

- Si possible un lien offrant à peu près la même fonctionnalité que Javascript (par exemple, pour une ouverture de popup, l'url de la page correspondante)
- "" (vide)
- "about:blank"
- "#"
- Un nom décrivant le but du lien (comme dans l'exemple de koala64)
- "javascript:;"
- Une page très courte dans laquelle on explique que le lien cliqué n'est pas pertinent en dehors de la page d'origine
koala64 a écrit :
<edit>... d'où l'importance de générer le lien via JS !</edit>
Certes. Smiley smile
Modifié par Eldebaran (01 Nov 2006 - 18:58)
Ce que je reproche à ta solution, koala64, c'est que l'adresse est interprétée comme une adresse relative et aboutit donc à une erreur 404 ou à une page qui n'a rien à voir.

Je pense que le "title" est plus adapté pour décrire le but du lien.
Modérateur
@Eldebaran :

Je n'arriverais jamais à une erreur 404 puisque c'est moi qui génère ce lien et que je le contrôle pleinement. Il ne me sert que pour l'affichage du menu et ne peut être interprété autrement, y compris lorsqu'on désactive le JS vu que dans ce cas, le lien n'existe tout simplement pas. Je précise qu'il va de paire avec le return false;

@Ralfman68 :

euh... non ! Smiley ravi

Je peux aussi ajouter mon grain de sel concernant la liste des problèmes...

-> Superposition des liens du menu au contenu de la page en cas de désactivation des couleurs

-> Monopolisation du onclick sur le titre du menu...

... par exemple... Smiley langue
Modifié par koala64 (01 Nov 2006 - 19:03)
Ca abouti à une erreur 404 ? Que veux tu dire ? L'erreur 404 ne sera jamais affichée... A moins de passer la page au link-checker personne ne verra rien, non ?
koala64 a écrit :
@Eldebaran :

Je n'arriverais jamais à une erreur 404 puisque c'est moi qui génère ce lien et que je le contrôle pleinement. Il ne me sert que pour l'affichage du menu et ne peut être interprété autrement, y compris lorsqu'on désactive le JS vu que dans ce cas, le lien n'existe tout simplement pas.
Euh...

Ben si, si comme dans le cas dont je parle depuis quelques posts, tu ouvres le lien dans une nouvelle fenêtre (bouton du milieu de ta souris avec Firefox). Smiley cligne
Pages :