Bonjour tous le monde,

Je post dans cette rubrique (bien que ce ne soit pas si débutant que ça), car ça concerne plusieurs sections (XHTML et CSS et peut-être même un peu de PHP).

Je suis en train de refaire mon site web ( http://www.mrsoul.org/ ) et il y a un truc que je cherche à faire (proprement) depuis des années sans résultat (dont une partie que je n'ai jamais réussi à intégrer dans la précédente version).

Vu que les images sont souvent plus explicites que les mots, je vous ai fait un petite maquette pour compléter les explications.

Comme vous l'avez vu, c'est un site de photo.

Deux choses me posent problème (dans l'ordre).

1) J'aimerais que la mise en page soit calé sur la taille (largeur) de la photo, quelle soit en mode paysage ou portrait.

2) J'aimerais qu'un bloc avec background (png transparant) et image (précédent, suivant) se superpose à la photo, quand on passe sur la moitié gauche ou droite de la photo.

Ma principale contrainte (j'y tiens et c'est ce qui me pose le plus de problèmes), c'est que toutes les photos ont des tailles différentes, ceci dit, elles ont toujours une taille maximum en horizontal ou verticale.

Voilà la maquette :

http://www.mrsoul.org/maquette/Maquette_h.jpg

http://www.mrsoul.org/maquette/Maquette_v.jpg

Auriez vous une idée, une piste, une recommandation ?

Merci d'avance.
Modifié par MrSoul (29 May 2013 - 14:20)
Igor> J'ai corrigé (juste les liens), mais je n'ai pas trouvé de règle concernant la taille des images... ?
MrSoul a écrit :
Auriez vous une idée, une piste, une recommandation ?

Si tu peux obtenir, côté serveur (par exemple en PHP) les dimmensions en pixels de l'image que tu veux afficher, tu peux adapter les styles (notamment largeur et hauteur) de certains éléments de ta page. Tu fais une feuille de style pour l'essentiel des styles, et pour les quelques adaptations tu places cela, en PHP, dans un élément STYLE dans le HEAD de ta page.

Si tu ne peux pas obtenir cette info côté serveur, ça peut éventuellement se faire en JavaScript. Mais ça risque de ne pas être très fluide, car il faudra attendre le chargement complet de l'image pour avoir sa taille, et donc le dimensionnement de la page se fera en deux temps...

Sans utiliser ni des données existantes (côté serveur), ni JavaScript, il y a peut-être quelque chose à faire en HTML et CSS brut. Je ferais bien des essais, mais je n'ai pas vraiment le temps. À vue de nez, on s'intéressera:
- au positionnement absolu par rapport à un élément parent positionné en relatif;
- à l'utilisation d'un tableau (ou de display: table) pour créer un conteneur dont la largeur s'adaptera au contenu.
Modifié par Florent V. (23 Jul 2008 - 21:10)
C'est bien ce que je pensais.

Pour récupérer la taille d'une image en php, c'est plutôt simple:
<?php
list($width) = getimagesize($photo);
echo $width;
?>

Je pense que c'est la méthode la plus simple, le problème, c'est que ça dissémine le code PHP dans toute la page.

Concernant le javascript, il y en aura probablement pour la superposition ?

Pour les tableaux, je m'en suis séparé il y a quelques années, si ce n'est que du display, pourquoi pas, car j'aimerais vraiment que mon code sémantique reste propre.

Pour le positionnement absolu, pourquoi pas, surtout que je pense que c'est immanquable avec le javascript pour l'histoire des boutons qui se superposes.

Merci pour les pistes, je vais voir de ce coté (ça fait tellement longtemps que je n'ai pas bosser du code...) Smiley cligne
MrSoul a écrit :
Je pense que c'est la méthode la plus simple, le problème, c'est que ça dissémine le code PHP dans toute la page.

Heu... je vois pas trop pourquoi.

En début de script (ou dans un script externe qui tu appelles en tout début de page), tu récupères les dimensions de ton image, et tu les stocke dans deux variables.
Ensuite, dans le HEAD, tu écris les quelques styles nécessaires.
Éventuellement, en générant le code HTML de ton image, tu peux aussi renseigner les attributs HTML height et width, pour un affichage plus rapide de la page.

Ça fait deux endroits, et trois si tu le souhaites. Et encore, tu pourrais placer tout le code PHP dans un fichier externe, à charge pour le script PHP de récupérer les infos et de générer le code de l'élément STYLE (attention, je parle d'un élément et pas de l'attribut HTML du même nom!). Et dans ta page tu te contente d'appeler ton script PHP externalisé, et peut-être d'exécuter une fonction de ce script s'il faut lui passer le chemin de l'image en paramètre.
Rien de bien méchant ici.

Si récupérer les dimensions de l'image ne met pas à mal le serveur et ne ralentit pas sensiblement l'affichage de la page, c'est la bonne solution.

MrSoul a écrit :
Concernant le javascript, il y en aura probablement pour la superposition ?

Ben non. Liens positionnés en absolu, et voilà. Tu peux faire apparaitre les intitulés «précédent» et «suivant» en utilisant les pseudo-classes :hover et :focus, par exemple. JavaScript sera utile uniquement si tu veux rajouter des effets plus poussés, comme des effets de fondu par exemple, ou de déplacement progressif.

MrSoul a écrit :
Pour les tableaux, je m'en suis séparé il y a quelques années, si ce n'est que du display, pourquoi pas, car j'aimerais vraiment que mon code sémantique reste propre.

Oui, enfin, la sémantique et la propreté du code... (Bon, je ne relance pas le sujet, on va pas en finir. Smiley lol )
Une idée m'est venu dans le RER (1 heure sans paysage, il ne reste qu'à penser).

Le plus simple ne serait pas une toute bête image-map ? (pour les coordonées, c'est tout simple, il suffit de les calculter à partir de la taille de l'image).

Après, j'ai plus qu'à comprendre comment bien faire les superposition (tu n'aurais pas un article claire et en français ?)
Et bien, à ce niveau, ça marche du tonner, je vous donne donc mon petit bout de code.

J'ai plus qu'à comprendre comment je peux superposer les images en hover... C'est une autre histoire !

<?php
$photoid="20071030215444_0263";
list($width,$height) = getimagesize("./photos/".$photoid.".jpg");
echo $width." x ".$height;
?>

<map id="map">
	<area shape="rect" coords="0,0,<?php echo $width/2; ?>,<?php echo $height; ?>" href="./precedent.php" />
	<area shape="rect" coords="<?php echo $width/2; ?>,0,<?php echo $width; ?>,<?php echo $height; ?>" href="./suivant.php" />
</map>

<img src="./photos/<?php echo $photoid; ?>.jpg" alt="<?php echo $photoid; ?>" usemap="#map" style="width: <?php echo $width; ?>px; height: <?php echo $height; ?>px;" />
MrSoul a écrit :
Le plus simple ne serait pas une toute bête image-map ?

Pour les boutons? Je dirais que non.

Je ferais quelque chose du genre:
<div id="main-image">
	<a id="previous" href="...">Image précédente</a>
	<a id="next" href="...">Image suivante</a>
	<img alt="" src="..." />
</div><!-- #main-image -->

Et en CSS: div#main-image en position: relative, avec un height correspondant à la taille de l'image (pas indispensable sauf pour IE6), et les liens positionnés en absolu.

MrSoul a écrit :
Après, j'ai plus qu'à comprendre comment bien faire les superposition (tu n'aurais pas un article claire et en français ?)

Apprendre ou réviser le positionnement CSS en lisant les articles correspondants sur Alsacréations et Openweb, par exemple?
Modifié par Florent V. (29 Jul 2008 - 20:10)
Effectivement, pour de simple boutons de navigation, il est préférable d'utiliser de simples liens qu'un image-map.

Je suis parti révisé sur openweb, ça m'a fait du bien, ça fait bien un à deux ans que je n'avais pas codé, même si c'est comme le vélo, on oublis vite les idiotes subtilité (surtout que je faisais une horrible faute :mrgreen:).

Voilà ce que ça donne (la taille des image est calculé par PHP) :
http://www.mrsoul.org/maquette/maquette_horizontal.php
http://www.mrsoul.org/maquette/maquette_vertical.php

J'ai réussi à régler mes problèmes, contant Rémy, de plus, c'est valide xhtml 1.1 et encore sémantique :lol:... (Bon, ok, c'est mon petit plaisir).

Le seul problème, c'est que je suis sur mac désormais, et même si je peux valider le comportement de nombreux navigateur (FF[2/3], Safari, Opera), je ne peux plus le faire sur le vieux truc bleu asbeen (mais qui est encore utilisé à plus de 70%).

Va donc falloir que j'use de bootcamp pour finaliser (et que je trouve un hack pour le PNG24).

Je reprend donc mon flow de questions Smiley lol

Le hover comme je l'ai produit peut il poser problème sur certaines configuration ?

Sur la partie haute, j'ai donc un logo (h1 avec texte en indentation négative et background) et un menu (une liste en ligne).
Sauf que j'aimerais que le texte du titre (du logo disons) et du menu soit sur la même ligne de base (en gros, que le texte du menu soit aligné sur le bas du bloc contenant), de plus, que le menu soit ferré à droite, j'ai beau chercher, je ne trouve pas, le float du li pose problème.
Une piste ?

j'aurais d'autres questions, mais pas trop d'un coup Smiley cligne

En tout cas, merci beaucoup pour tes pistes Florent.
MrSoul a écrit :
Le seul problème, c'est que je suis sur mac désormais, et même si je peux valider le comportement de nombreux navigateur (FF[2/3], Safari, Opera), je ne peux plus le faire sur le vieux truc bleu asbeen (mais qui est encore utilisé à plus de 70%).

Va donc falloir que j'use de bootcamp pour finaliser (et que je trouve un hack pour le PNG24).

Oui, pas tellement d'autre solution que le dual boot, ou la virtualisation (VMWare Fusion par exemple).
Pour le PNG-24, pas tellement de solutions pour IE6. Tu peux utiliser le filtre DirectX AlphaImageLoader (décrit dans la FAQ), mais il y a un effet secondaire qui risque de te poser problème: les liens deviennent inactifs. Ça peut se corriger dans certains cas (à coup de position: relative, mais c'est assez tendu.
Heureusement, IE7 n'aura pas besoin de correctif (pour la transparence PNG).

Pour IE6, je tenterais éventuellement un PNG-8 avec un «fond» à pixels alternés: un pixel transparent, un pixel opaque. Genre passoire.
Via un commentaire conditionnel, tu peux changer les images de fond des liens précédent et suivant uniquement pour IE6.

MrSoul a écrit :
Le hover comme je l'ai produit peut il poser problème sur certaines configuration ?

À priori non (en dehors du problème d'IE6 pour la transparence PNG).
Ah si: il faut virer le prologue XML (qui ne sert à rien et fera buguer IE6, qui passera en mode Quirks). Et tant qu'à faire utiliser un Doctype XHTML 1.0 ou HTML 4.01, et pas XHTML 1.1 (qui devrait théoriquement être servi en "application/xhtml+xml", je ne détaille pas mais en gros mieux vaut utiliser XHTML 1.0).

MrSoul a écrit :
j'ai donc un logo (h1 avec texte en indentation négative et background) et un menu (une liste en ligne)

Tu pourrais tout simplement placer ton image dans le code HTML:
<h1><img src="images/logo.png" alt="R*my B*nelh*dj" /></h1>
(avec des vraies lettres à la place des étoiles Smiley cligne )

MrSoul a écrit :
Sauf que j'aimerais que le texte du titre (du logo disons) et du menu soit sur la même ligne de base (en gros, que le texte du menu soit aligné sur le bas du bloc contenant), de plus, que le menu soit ferré à droite, j'ai beau chercher, je ne trouve pas, le float du li pose problème.

Tu as plusieurs options.
Tu peux faire flotter le titre à gauche, et le menu à droite. Tu peux aussi positionner le titre à gauche en absolu, et le menu en bas à droite en absolu (avec un right: 0; bottom: 7px; par exemple, en supprimant les width et height inutiles). Pour les LI, ils n'ont pas à être flottants, ils peuvent simplement être en display: inline.
Je suis pas fan de virtualisation, j'ai pas trop envie d'installer un gros logiciel juste pour faire trois essaies sur IE, je préfère un petit coup de reboot Smiley cligne

Pour les filtres, je ferais un essaie, mais si effectivement ça pose problème, je tenterais ton astuce des commentaires conditionnels.

Concernant le prologue, il n'y a pas de soucis, j'utilise une bonne vieille astuce :
<?php 
if(stristr($_SERVER["HTTP_ACCEPT"],"application/xhtml+xml")){
	header("Content-Type: application/xhtml+xml; charset=utf-8");
	echo "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n
	<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n";
} else {
	header("Content-Type: text/html; charset=utf-8");
	echo "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n";
} 
?>

Et dans les metas :
<?php 
if(stristr($_SERVER["HTTP_ACCEPT"],"application/xhtml+xml")){
	echo "<meta http-equiv=\"Content-Type\" content=\"application/xhtml+xml; charset=utf-8\" />\n";
} else {
	echo "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n";
} 
?>


Concernant le h1, pourquoi mettre une image au lieu du texte ? (certes, il y a le texte alternatif...)

Pour le reste, j'ai tout corrigé, ça commence à prendre forme.
A vrais dire, il ne me reste plus qu'un problème à régler (après, tout le reste, je sais faire Smiley lol ).

Il s'avère que je suis totalement incompétent en javascript, c'est bien simple, j'y connais rien, donc là, j'ai vraiment besoin de votre aide.
Le petit lien "+ Plus d'infos" permet d'afficher ou masquer un petit block en dessous (avec plus d'infos quoi :lol:).

J'ai trouvé un bout de code ici même pour essayer, mais il pose deux problèmes, quand on clique dessus, bien qu'il ne recharge pas la page, il retourne tout en haut (et rajoute le dièse sur l'url), de plus, quand le bloque est masqué, il conserve toujours son espace.

La démo : http://www.mrsoul.org/maquette/maquette_horizontal.php

Pour le coup, ce n'est plus une piste que je demande, mais de l'aide Smiley lol
MrSoul a écrit :
Pour les filtres, je ferais un essaie, mais si effectivement ça pose problème, je tenterais ton astuce des commentaires conditionnels.

Bah pour utiliser les filtres DirectX pour le PNG, il faut utiliser un commentaire conditionnel pour cibler précisément IE6. (Pour ma part, je fais un commentaire conditionnel pour IE7 et inférieurs -- donc dans la pratique IE6 et IE7 -- qui appelle un fichier iefixes.css, dans lequel je distingue correctifs pour IE6 en utilisant le Star HTML Hack.)

MrSoul a écrit :
Concernant le prologue, il n'y a pas de soucis, j'utilise une bonne vieille astuce :
<?php 
if(stristr($_SERVER["HTTP_ACCEPT"],"application/xhtml+xml")){
	header("Content-Type: application/xhtml+xml; charset=utf-8");
	echo "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n
	<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n";
} else {
	header("Content-Type: text/html; charset=utf-8");
	echo "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n";
} 
?>

Wah, première fois que je vois ce mécanisme bien utilisé (sur ce forum). Smiley lol

MrSoul a écrit :
Concernant le h1, pourquoi mettre une image au lieu du texte ? (certes, il y a le texte alternatif...)

Parce que c'est plus accessible (la technique du text-indent négatif, comme d'autres techniques de remplacement d'images, n'est pas réellement accessible, même si pas trop mal).

Pour ton script JS, je serais tenté de te répondre d'apprendre les bases de JS. Smiley cligne (Vu qu'à la base la finalité de ce forum est d'accompagner les membres dans leur apprentissage, pas de leur fournir des solutions sur-mesure.)

Mais comme c'est assez simple, allons-y. Je modifierais le script ainsi:

// Ajout d'une classe "hasJS" sur l'élément HTML
document.documentElement.className+=" hasJS";

// Fonction afficher/masquer
function toggle(element_id) {
	node = document.getElementById(element_id);
	if (node.style.visibility=="visible") {
		// Contenu caché, le montrer
		node.style.display = "none";
	} else {
		// Contenu visible, le cacher
		node.style.display = "block";
	}
}

Les modifications:
1. une ligne de JS pour ajouter une classe "hasJS" sur l'élément HTML. Dans notre code CSS, on va pouvoir écrire:
#infos {
	/* Styles normaux, pas de display:none ou de visibility:hidden */
	/* D'ailleurs j'ai pas compris pourquoi ce bloc était positionné
	   en absolu, mais passons. */
}
.hasJS #infos {display: none;}
Ainsi, sans JS, les infos seront affichées.
(Dans l'idéal, le lien «+ d'infos» devrait être généré en JavaScript, mais ça n'est pas bien gênant.)
2. j'ai modifié la fonction toggle pour utiliser display: none|block plutôt que visibility: hidden|visible.

Ensuite, côté HTML, on modifie le lien ainsi:
<a href="#infos" onclick="toggle('infos'); return false;">+ Plus d'infos</a>
Bon, hébé, je pense que jai compris ce bout de code, ceci dit, je ne comprend absolument pas pourquoi il ne fonctionne pas correctement, en effet, le deuxième clique ne masque pas le bloc...

http://www.mrsoul.org/maquette/maquette_horizontal.php

Ha vui, et petite chose, quel est l'élément qui ne change pas l'URL, le return false ?

Si t'as quelques liens pour apprendre le javascript, ça m'intéresse, mais attention, à ce niveau, je suis un gros noobz (j'ai quelques bases en PHP si ça aide).

Sinon, petit hors sujet, je suis passé sur ton site, je trouve la ligne éditorial très intéressante, le titre (et sont explication) sont très bien pensé !
Modifié par MrSoul (31 Jul 2008 - 19:39)
MrSoul a écrit :
Bon, hébé, je pense que jai compris ce bout de code

Ah ben non, sinon tu aurais repéré l'énorme erreur que j'avais commise. Smiley cligne

Code corrigé (mais pas testé):
// Ajout d'une classe "hasJS" sur l'élément HTML
document.documentElement.className+=" hasJS";

// Fonction afficher/masquer
function toggle(element_id) {
	node = document.getElementById(element_id);
	if (node.style.display=="none") {
		// Contenu caché, le montrer
		node.style.display = "block";
	} else {
		// Contenu visible, le cacher
		node.style.display = "none";
	}
}


Pour apprendre JavaScript, pour ma part j'ai commencé par un bouquin nommé DOM Scripting: Web Design with JavaScript and the Document Object Model. Cf. http://www.domscripting.com/book/
J'ai enchainé sur l'utilisation occasionnelle de la bibliothèque jQuery.

(J'ai aussi retrouvé ce sujet du forum, je ne pensais pas qu'il était si vieux...)
Modifié par Florent V. (31 Jul 2008 - 23:50)
Houuuu s'te honte Smiley lol

Certes, je n'avais pas tout compris, mais ça m'a permis d'avancer un peu plus dans la compréhension de la chose.

Ca marche, c'est formidable, merci beaucoup Florent !

Maintenant, j'attaque la petite phase facile, optimiser un poil le css, en faire une feuille de style indépendante, importer le contenue, l'import des champs IPTC.

La dernière étape est une toute autre paire de manche, je vais devoir me développer un moteur de blog photo, déjà parce que rien ne m'a réellement convaincu, et ensuite parce que les solutions qui s'en approche (principalement pixel post) nécessite de trop grosse modifications pour que ça fonctionne avec ma maquette...

Je posterais les diverses étapes de création Smiley cligne

Encore merci Florent !
Je fais remonter un peu le sujet, si je ne trouve pas de solution, je devrais revoir entièrement cette idée et vu que c'est un peu le fil conducteur, ça me pose problème Smiley cligne

Toujours sur le même lien.
Hello,

Pas de lien direct, mais un peu d'optimisation. Sur la page d'exemple, tu génères le code suivant:
div#content {width: 900px;}
			div#header {width: 900px;}
			div#header ul {width: 685px;}
			[b]div#photo {width: 900px;}[/b]
			div#photo a#precedente {width: 450px; height: 589px;}
			div#photo a#suivante {width: 450px; height: 589px; left: 450px;}
			[b]div#footer {width: 900px;}[/b]
			div#footer p#info {width: 685px;}
			[b]div#footer div#infos {width: 900px;}[/b]

Sauf erreur de ma part, les lignes en gras sont inutiles. Les éléments de type bloc prennent automatiquement la largeur de leur conteneur, à moins qu'ils ne soient flottants ou positionnés en absolu (ou en fixed).
La largeur pour div#photo est peut-être nécessaire pour établir le layout et avoir un positionnement absolu correct des enfants dans Internet Explorer, mais dans ce cas un simple width: 100% dans la feuille de styles suffira amplement.

Tu pourrais encore simplifier, de la manière suivante:
/* Dans la feuille de styles, en plus des styles existants */
#header ul {
	width: 75%;
}
#photo {
	position: relative;
	width: 100%;
}
#precedente {
	position: absolute;
	top: 0;
	left: 0;
	height: 100%;
	width: 50%;
}
#suivante {
	position: absolute;
	top: 0;
	right: 0;
	height: 100%;
	width: 50%;
}
#info {
	width: 75%;
}

/* Dans la page, généré via PHP */
#content {width: 900px;}
#photo {height: 589px;}
(À tester...)


Pour revenir au problème: pour Opera, il semblerait que ce soit le survol des liens qui n'est pas pris en compte car les liens ne sont que des zones vides: pas de contenu (en dehors de la boite via un text-indent, pas de couleur ou d'image de fond. Si je place une bordure sur les liens, le survol marche sur la bordure mais pas au centre.

Une parade possible (et compatible avec Firefox et Opera... à voir pour IE et Safari) est de ne pas passer par une image de fond inexistante, mais d'utiliser opacity: 0; et opacity: 1;. Je pensais qu'on aurait le même problème que pour le fond inexistant, mais en fait non. (J'ai également testé avec visibility: hidden et visibility: visible, et ça ne marche pas).

Cela peut donner:
a#precedente {
	position: absolute;
	top: 0;
	left: 0;
	text-align: left;
	text-indent: -9000px;
	background: red;
	opacity: 0;
	filter: alpha(opacity=0);
}
a#precedente:hover, a#precedente:focus, a#precedente:active {
	opacity: 1;
	filter: alpha(opacity=100);
}
(La propriété filter; non standard, est propre à IE et permet d'obtenir le même résultat. Elle devrait marcher pour ces éléments dotés du layout car positionnés en absolu.)
Modifié par Florent V. (16 Aug 2008 - 19:15)
Encore une fois merci.

J'ai suivis des conseil d'optimisation (en général, c'est ce que je fais en dernier quand la feuille de style touche à sa fin).

Pour le header et le footer, en fait, il est calculé de cette façon : <?php echo ($width-215); ?>, donc pas possible d'utiliser les pourcentages (ça fait bien 75% avec 900px, mais dans le cas d'image moins large, ça ne marche plus).

Sinon, j'ai tenté ta parade à base d'opacité et de filtre, ça rend les liens fonctionnels dans Opera (pas testé sous IE), mais rend invisible l'image de fond sur tous navigateurs...

Pour voir le résultat : http://www.mrsoul.org/maquette/