28172 sujets

CSS et mise en forme, CSS3

Bonjour à tous !

Je voudrais tout d'abord informer la communauté que j'ai déjà effectué des recherches sur le forum, ainsi qu'un peu partout sur le net, mais je n'ai rien trouvé correspondant réellement à mon problème.

Les solutions que j'ai pu rencontré ci et là ne répondaient pas entièrement à mon problème, du coup j'ai décidé d'ouvrir un petit "Topic" en espérant que les pros de la communauté sauront m'aider.

J'ai volontairement simplifié mon problème, afin de faciliter les explications que j'aurais à vous faire.

J'aimerais donc tout simplement avoir un conteneur scrollable qui prend toute la hauteur de son conteneur parent MOINS une taille fixe en pixel.

Pour illustrer :
upload/1834-objectifCss.png

Le bandeau rouge correspond à une entête de hauteur fixe 100px, et le conteneur gris correspond au corps de la page. Ce dernier doit occuper toute la place restante en hauteur et être scrollable (Mais uniquement LUI (le conteneur gris), pas la totalité de la page...)

Merci d'avance !
Excellent comme question.

Je verrais 2 possibilités, crée 1 div englobant un autre.

<div id="wrapper" style:"background-color:red;paddind-top:100px:padding-bottom:100px;">
      <div style="background-color:grey;overflow:auto;height:100%">

      </div>
</div>


ou de 3 créer 3 div successivement. Pour forcer le div du bas, j'utiliserais une position absolute pour sortir du flux avec un bottom à 0.

<div style:"background-color:red;height:100px;"></div>
<div style="background-color:grey;overflow:auto;">blablable contenu de ma page</div>
<div style:"background-color:red;height:100px;position:0px;"></div>


EDIT : après relecture de mon post,
Dans la première proposition, je me dis que le div faisant office de "wrapper" risque de ne pas prendre toute la hauteur de page. Peut etre en essayant de lui donner comme hauteur 100% pour qu'il occupe toute la haute de son parent : la page. Cependant, j'ai quelques doutes que cela fonctionnne. Smiley bawling

Par contre, je pense que la 2ème solution peut fonctionner.

Désolé, je ne peux pas tester pour le moment.

Bon courage.
Modifié par alexx (07 Apr 2010 - 14:25)
Salut !

Je te remercie pour ta(tes) réponse(s) !

(Je m'aperçois que la miniature générée, a provoqué un quiproquo, mais rien de grave, ca n'a pas tellement d'incidence. En réalité il n'a pas de footer. (La miniature a fait apparaitre un deuxième bandeau rouge en bas, alors qu'il n'existe pas))

J'ai bien essayé tes deux exemples et j'arrive aux mêmes résultats que j'ai pu obtenir précédemment, à savoir que la hauteur totale du tout fait 100% + 100px (et donc fait scroller mon navigateur et pas uniquement le cadre gris)


Concernant ton deuxième exemple, j'imagine que tu as zappé un height: 100% pour le deuxième div ?

Merci de ta participation !
Bon...j'ai fini par utiliser la solution avec le JavaScript...

Mais la solution sans, m'intéresse toujours, donc si quelqu'un passe par là...

Voilà ma solution :


<html>
<head>
<style>
*
	{
	padding: 0;
	margin: 0;
	border: 0;
	}
	
html, body
	{
	height: 100%;
	overflow: hidden;
	}
	
#header
	{
	height: 100px;
	background: red;
	}
	
#glob
	{
	height: 100%;
	overflow: auto;
	background: gray;
	margin: 20px;
	border: 5px solid pink;
	}
</style>
</head>
<body>
<div id="header"></div>
<div id="glob">
	<p>truc</p>
	<p>truc</p>
	<p>truc</p>
	<p>truc</p>
	<p>truc</p>
	<p>truc</p>
	<p>truc</p>
	<p>truc</p>
	<p>truc</p>
	<p>truc</p>
	<p>truc</p>
	<p>truc</p>
	<p>truc</p>
	<p>truc</p>
	<p>truc</p>
	<p>truc</p>
	<p>truc</p>
	<p>truc</p>
	<p>truc</p>
	<p>truc</p>
	<p>truc</p>
	<p>truc</p>
	<p>truc</p>
	<p>truc</p>
	<p>truc</p>
	<p>truc</p>
	<p>truc</p>
	<p>truc</p>
	<p>truc</p>
	<p>truc</p>
	<p>truc</p>
	<p>truc</p>
	<p>truc</p>
	<p>truc</p>
	<p>truc</p>
	<p>truc</p>
	<p>truc</p>
	<p>truc</p>
	<p>truc</p>
	<p>truc</p>
</div>
<script>


var glob = document.getElementById("glob");
setInterval(function()
	{
	glob.style.height = (document.body.offsetHeight - 150)+"px";
	}, 750);


</script>
</body>
</html>

Modifié par fieldset (08 Apr 2010 - 10:14)
Moi aussi de temps en temps,je fais appel pour déterminer largeur ou je ne sais quoi en JS lorsque je ne sais comment faire en CSS Smiley smile

Que se passe t-il si tu redimensionne ta fenetre de ton navigateur ? Smiley smile
En fait, utilise un évenement qui va déclencher en cas de redimensionnement de la fenetre.

Sinon essaie plutot de mettre ton JS dans le header de ta page.
Ben apparemment là, il n'y aurait pas de solution miracle en CSS. On ne peut (d'après ma connaissance) soustraire une hauteur en pixel fixe à une hauteur définie en pourcentage, donc la solution ultime consiste à utiliser JavaScript.

Ce n'est pas un gros problème, puisque de toute façon mon application (ce n'est pas un "site web") web nécessite d'avoir le JavaScript pour pouvoir l'utiliser.

Concernant le redimensionnement de la fenêtre, ce n'est pas un problème, si tu regardes dans mon code JavaScript, j'appèle via l'évènement setInterval une fonction qui redimensionne automatiquement mon DIV. (Que la fenêtre soit redimensionnée ou non d'ailleurs, mais niveau utilisation processeur c'est très très faible).

Pour l'évènement onResize, j'ai déjà voulu l'utiliser, mais il me semble qu'il n'est pas supporté par tous les browser, je vais faire mes tests encore aujourd'hui. Mais un autre point c'est que si j'utilise cet évènement, ma fonction de redimensionnement va être appelée à chaque changement de taille de la fenêtre (et là ca risque d'être carrément dément en utilisation de temps processeur Smiley smile )

Plusieurs raisons pour lesquelles j'ai placé mon code javascript à la fin Smiley smile :

* La première, c'est parce que c'est juste un exemple basique (je n'ai pas non plus de dtd, etc)

* La seconde, c'est que si je mets mon code javascript dans les balises Head, je ne pourrais pas avoir de pointeur sur un élément DOM dans le body, puisque celui-ci sera chargé après ma fonction javascript. (Alors après on peut toujours utiliser l'évènement "ready" de jquery sur le "document" pour executer la fonction de redimensionnement uniquement quand la page entière est chargée...mais je me répète ce morceau de code est là pour illustrer ma solution, rien de plus Smiley smile

En tout cas je te remercie encore de ta participation.

(Si les magiciens du CSS passent par là, j'attends toujours une réponse qu'elle soit positive ou négative afin de savoir si oui ou non ce que je demande est réalisable sans javascript...)

EDIT:

Bon alors je viens de comparer le temps d'utilisation processeur entre la méthode qui consiste à utiliser setIntertval et l'évènement onresize, et bon...c'est kiff kiff niveau utilisation du processeur. D'autre part je ne solicite pas le processeur lorsqu'il n'y a pas de redimensionnement, je vais donc utiliser l'évènement onresize plutôt que mon setintervale Smiley smile
(Me reste plus qu'à tester sous les différents navigateurs).

EDIT2:

Fonctionne sur :

IE8: OK
IE7: OK
IE6: OK
IE5.5 : OK
FF : OK
Opera : OK
Chrome : OK
Safari : OK

Le morceau de code javascript qui remplace l'ancien :


<script>
var glob = document.getElementById("glob");
/**
 * Adapte dynamiquement la hauteur d'un élément en fonction de la hauteur de son parent.
 * @param element Element dom sur lequel s'applique le redimensionnement
 * @param hauteur Hauteur (en pourcentage) que vous désirez
 * @param marge Marge à soustraire en pixels
 */
function adapterTaille(element, hauteur, marge)
	{
	element.style.height = ((document.body.offsetHeight - marge) * hauteur / 100)+"px";
	}

window.onresize = function()
	{
	adapterTaille(glob, 100, 150);
	};
	
window.onload = function()
	{
	adapterTaille(glob, 100, 150);
	};
</script>

Modifié par fieldset (08 Apr 2010 - 12:10)
Pour ceux que ca intéresse, voilà une solution complète et plus complexe qui permet de montrer les avantages de la solution précédente :

Voilà un aperçu du rendu : upload/1834-resultat.png

Fonctionne sur :

IE8: OK
IE7: OK
IE6: OK
IE5.5 : OK
FF : OK
Opera : OK
Chrome : OK
Safari : OK

Et le code qui va bien :


<html>
	<head>
		<style type="text/css">
			*
				{
				padding: 0;
				margin: 0;
				border: 0;
				}

			html, body
				{
				height: 100%;
				overflow: auto;
				}

			#header
				{
				height: 100px;
				background: red;
				}

			#container
				{
				height: 0;
				overflow: auto;

				background: cyan;
				}

			#glob1, #glob2
				{
				height: 0;
				overflow: auto;

				background: gray;
				margin: 10px;
				}
		</style>
		<script type="text/javascript">
			function Adapter(){};

			Adapter.elements = new Array();

			Adapter.add = function(element, hauteur, marge)
				{
				Adapter.elements[Adapter.elements.length] = new Array(element, hauteur, marge);
				}

			Adapter.adaptAll = function()
				{
				var length = Adapter.elements.length;
				for(var i = 0; i < length; i++)
					Adapter.elements[i][0].style.height = ((Adapter.elements[i][0].parentNode.offsetHeight - Adapter.elements[i][2]) * Adapter.elements[i][1] / 100)+"px";
				}

			window.onresize = function()
				{
				Adapter.adaptAll();
				};

			window.onload = function()
				{
				Adapter.adaptAll();
				};
		</script>
	</head>
	<body>
		<div id="header"></div>
		<div id="container">
			<div id="glob1">
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
			</div>
			<div id="glob2">
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
				<p>truc</p>
			</div>
		</div>
		<script type="text/javascript">
			Adapter.add(document.getElementById("container"), 100, 100);
			Adapter.add(document.getElementById("glob1"), 50, 30);
			Adapter.add(document.getElementById("glob2"), 50, 30);
		</script>
	</body>
</html>
[/i][/i][/i][/i]
Modifié par fieldset (08 Apr 2010 - 14:03)
fieldset a écrit :
Ben apparemment là, il n'y aurait pas de solution miracle en CSS. On ne peut (d'après ma connaissance) soustraire une hauteur en pixel fixe à une hauteur définie en pourcentage, donc la solution ultime consiste à utiliser JavaScript.

Il n'y a pas de solution miracle mais il y a des solutions tout court.

En CSS 2.1, on pourra utiliser le positionnement absolu:
#content {
  position: absolute;
  top: 250px; bottom: 0; /* width non nécessaire */
  left: 0; right: 0; /* height non nécessaire */
  overflow: auto;
}

Implémenté par tous les navigateurs modernes. À vérifier pour IE7.
En CSS3, on pourra aussi utiliser le Flexible Box Model.
Implémenté par Firefox, Safari, Chrome.

La solution du positionnement absolu me semble bonne. À tester dans IE7. Si ce dernier pose problème, on pourra sans doute utiliser la solution JavaScript uniquement pour ce dernier (script appelé via un commentaire conditionnel visant précisément IE 7, ou IE7 et inférieurs).

Quelques remarques:
- J'ai une haine profonde pour ce type de mise en page qui bouffe une grande partie du viewport pour afficher un en-tête dont je me contrefiche dans 99% des cas une fois que je l'ai vu une première fois. Smiley biggol
- Le positionnement fixe est une autre solution (CSS 2.1, compatible IE7), mais qui se comporte un peu différemment.
- J'ai vu passer un exemple de code HTML sans Doctype. Soit la personne qui l'a posté souhaite se faire bannir du forum, soit c'est une erreur d'inattention. On va parier sur l'erreur d'inattention. Smiley smile
- Il faudrait faire des styles pour les petits écrans (via des media queries), notamment pour les smartphones, qui annulent cette mise en page si jamais l'écran fait moins de 600px de haut ou quelque chose du genre.
fieldset a écrit :
IE6: OK
IE5.5 : OK

Que l'on teste sur IE6, ça me peine mais je comprends.
Mais que l'on teste sur IE 5.5, là, c'est limite criminel!
@florent :

Merci beaucoup pour tes explications, je m'en vais tester ça de suite.

Je ne l'ai peut-être pas précisé, mais il s'agit d'une application intranet / extranet, plutôt orientée utilitaire, d'où l'intérêt de ce header qui regroupe un certain nombre de boutons d'actions (ce n'est pas un bête header avec une image décorative).

Malheureusement certains postes qui se connecteront à ce portail utilisent encore IE5.5. Je fonctionnerais donc en mode dégradé, mais fonctionnel malgré tout.

@pfoofen :

Parce que si je fonctionne ainsi, la scrollbar se retrouvera également à côté de l'entête qui sera fixe. Ce qui ne correspond absolument pas aux règles ergonomiques demandées pour l'application. (Mais j'y avait effectivement pensé, même si c'était pas très chouette visuellement).


@tous :

JavaScript étant indispensable pour l'application (niveau fonctionnel et ergonomique), je peux donc me permettre d'utiliser JS pour régler le problème rencontré. Toutefois je vais tester la solution de Florent.