28172 sujets

CSS et mise en forme, CSS3

Salut

Est-il possible d’appliquer une transition à partir d'une hauteur 0 jusqu'à une hauteur variable ?

un exemple avec un div cliquable qui alterne la class appliquée à la cible :
<div onclick="	if (document.getElementById('bloc_cache').className != 'bloc_cache_end')
				{
					document.getElementById('bloc_cache').className = 'bloc_cache_end';
				} else {
					document.getElementById('bloc_cache').className = 'bloc_cache_start';
				}">
	bouton
</div>

<div id="bloc_cache" 
	 style="background: Grey; 
			overflow: hidden; ">
	<div style="background: Grey; ">
		test<br />
		test<br />
		test<br />
		test<br />
	</div>
</div>


et les class css appelées :
.bloc_cache_start {
	height: 0px; 
	-moz-transition: .5s ease;
}

.bloc_cache_end {
	-moz-transition: 1s ease;
	height: auto; 
}


Avec une hauteur définie ca marche mais comme c'est du contenu variable j'utilise un height auto, mais du coup, pas de transition Smiley murf

Et question subsidiaire, quelles sont les equivalent des transitions en JavaScript, j'ai trouvé très peu de doc en anglais et encore moins en francais... si vous avez un lien Smiley cligne

Merci
Modifié par epeedelorage (07 Apr 2011 - 18:08)
bonjour,

css et javascript ne peuvent interagir entre eux. javascript peut "tester" , modifier ou creer une regle.
Ton exemple ne peut fonctionner pour 2 raisons :
1) auto n'est pas une valeur.
2)css n'est pas l'ecoute des changement produits pas un script js ( Smiley smile pas sur que ce soit bien formulé lol )

.Ou tu en passe par 100% CSS et/ou support javascript.

un exemple CSS fonctionnel en usant des pseudo-class basé sur ton code:
<a href="#bloc_cache">bouton</a>
<div id="bloc_cache"  
     style="background: Grey;  
            overflow: hidden; " tabindex="0"> 
    <div style="background: Grey; "> 
        test<br /> 
        test<br /> 
        test<br /> 
        test<br /> 
    </div> 
</div>
et le css de base pour ff
#bloc_cache { 
    max-height: 1px;  
    -moz-transition: .5s ease;
overflow:hidden;
} 
 
#bloc_cache:target, #bloc_cache:focus , #bloc_cache:hover { 
    -moz-transition: 1s ease; 
    max-height: 500px;  
}
c'est possible grâce à la fonction JQuery ".height()", elle permet de connaitre la hauteur d'un bloc. tu peux l'utiliser de cette façon:


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

	<title>Test</title>

	<style type="text/css">
		body{width:635px; margin:auto;}

		a.bouton{display:block; width:100px; text-align:center; background:orange; margin:20px 0; height:30px; line-height:30px; color:black; text-decoration:none;}

		.bloc_cache{background:black; color:white; padding:10px;}
		.bloc_cache p{margin:0;}
	</style>
	<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>

	<script type="text/javascript">
		$(document).ready(function(){
			//definition de la hauteur du bloc
			var hauteur = $('div.bloc_cache').height();
			
			//on le masque en js (pratique car si l'utilisateur n'a pas de js, il le verra quand même
			$('div.bloc_cache').hide();
			
			//la fonction slideDown
			$('a[rel="slide_down"]').click(function(){ 
				$('div.bloc_cache').css('height', hauteur);
				$('div.bloc_cache').slideDown("slow");	
			});	
			//la fonction slideToogle pour déplier - replier
			$('a[rel="slide_toggle"]').click(function(){ 
				$('div.bloc_cache').css('height', hauteur);
				$('div.bloc_cache').slideToggle("slow");	
			});
		});
	</script>
</head>
<body>

<a href="#" class="bouton" rel="slide_down">slideDown</a>
<a href="#" class="bouton" rel="slide_toggle">slideToggle</a>
<div class="bloc_cache">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris laoreet congue dui. Vestibulum vel tortor nunc, nec sagittis leo. Sed dui justo, condimentum vel ultricies id, tincidunt vel felis. Sed a mattis ligula. Proin sit amet tortor quis risus fringilla volutpat. Nunc vitae felis ut mauris ornare adipiscing sit amet vitae nunc. Fusce euismod fringilla eros tincidunt dictum. Proin vestibulum tempus justo, eget eleifend urna viverra vehicula. Donec justo orci, scelerisque ut consectetur et, aliquet et tortor. Praesent non ante non turpis facilisis consectetur id quis velit. Vivamus quam tortor, adipiscing sit amet vehicula a, laoreet eu risus. Sed mauris orci, scelerisque eget auctor sed, egestas eget nulla. Curabitur vel tincidunt justo. Donec suscipit metus sed augue lacinia rhoncus. Fusce volutpat, turpis at luctus mattis, lorem est vestibulum massa, vitae fermentum massa nunc eu nunc. In semper, ante et auctor vestibulum, lectus dui tristique quam, et egestas est diam mollis tortor. Ut suscipit tristique urna, vel interdum risus ornare ultrices. Curabitur vitae nisl sapien. Donec sit amet nunc diam. </p>
</div>

</body>
</html>


je l'ai testé, ça marche Smiley cligne
Modifié par maeda974 (07 Apr 2011 - 17:49)
Merci gc-nomade Smiley jap , mais comme mon bouton et en fait un td cliquable, je ne peux pas utiliser les target (a moins que je me trompe ?).

Du coup j'ai résolu le truc en récupérant la hauteur du sous-div 'conteneur' et en l'attribuant au div parent. Du coup la hauteur n'est plus inconnu et css peut calculer la transition et étendre mon -moz-linear-gradient!

Bref, le code (en version maniaque Smiley ravi ) :

le .php :
<td class="button" 
	onclick="affiche_resultats_du_diag('<?= strtr($nom_diag, ' ', '_') ?>');" >
	<!-- ceci est le bouton declancheur -->
</td>

<!-- (...) -->

<div id="resultat_<?= strtr($nom_diag, ' ', '_') ?>" 
	 class="resultats" >
	<div id="conteneur_resultat_<?= strtr($nom_diag, ' ', '_') ?>">
		<!-- contenu variable généré -->
	</div>
</div>

le .js :
function affiche_resultats_du_diag(id_nom_diag)
{
	if (document.getElementById('resultat_'+id_nom_diag).offsetHeight == '0')
	{
		document.getElementById('resultat_'+id_nom_diag).style.height = document.getElementById('conteneur_resultat_'+id_nom_diag).offsetHeight+'px';
	} else {
		document.getElementById('resultat_'+id_nom_diag).style.height = '0px';
	}
	//suite des instructions...
}


et le .css :
.resultats {
	height: 0px; 
	overflow: hidden; 
	-moz-transition: height 1s ease;
}


Mais le className = 'bloc_cache_end' reste utilisable si on veut 2 timing de transition different !

Smiley murf
merci maeda974 Smiley jap , mais je lui préfère la transition cubic-bezier de css3 plus jolie, et qui en plus ne nécessite pas de librairies extérieures Smiley cligne
Bonjour,
j'ai écrit une fonction JavaScript qui je l'espère pourra en aider quelques-uns,
et qui aurait pu s'avérer utile dans ce cas.
Mon problème a été la -moz-transition en hauteur de **px à la valeur auto [et inversement]
de tous les items <li> d'une liste non ordonnée <ul>.
Au départ, on a une liste de ce type :
<ul>
	<li>
		Title 1
		<ul>
			<li>
				SubTilte 1<br>
				Text 1 blablabla
			</li>
			<li>
				SubTilte 2<br>
				Text 2 blablabla
			</li>
		</ul>
	</li>
	<li>
		Title 2
		<ul>
			<li>
				SubTilte 1<br>
				Text 1 blablabla
			</li>
			<li>
				SubTilte 2<br>
				Text 2 blablabla
			</li>
		</ul>
	</li>
</ul>

Comme il a été dit dans ce sujet, on crée des <div> pour calculer la hauteur des textes, ce qui nous permettra de contourner le problème du height:auto.
Cependant, redéfinir en JavaScript la hauteur d'un item ne suffit pas à redéfinir celle de ses parents. Il a donc fallut construire une fonction qui parcours tout l'arbre.
Donc on appelle la fonction JavaScript au clic sur les titres, et on définit le <ul> racine.
<ul id="racine">
	<li>
		<div>
		<a href="#" onclick="return show_hide(this);">Title 1</a><br>
		<ul>
			<li>
				<div>
				<a href="#" onclick="return show_hide(this);">SubTilte 1</a><br>
				Text 1 ...

Ensuite on a le css qui va bien :
li {
  /*
  height:24px;
  c'est la hauteur des <li> au chargement de la page
  on écrit rien si la valeur de départ est "auto"
  */
  overflow:hidden;
  -moz-transition-property:height;
  -moz-transition-duration:0.4s;
}

Puis le JavaScript :
li_MinHeight = 24; //ici on définie la hauteur de départ des <li>, ou d'arrivée suivant l'utilisation que vous faites du script
function show_hide(object,firstLoop,heightAdjust){
	if(typeof(firstLoop) == "undefined")
		firstLoop = true; //valeur par défaut de firstLoop 
	if(typeof(firstLoop) == "undefined")
		heightAdjust = 0; //valeur par défaut de heightAdjust
	var racine = document.getElementById('racine');
	var ok = object.parentNode != racine;
	if(object.tagName == 'LI'){ //si l'élément est un <li> on va devoir redéfinir sa hauteur
		if(object.style.height == "")
			object.style.height = object.offsetHeight;
		if(firstLoop && object.offsetHeight>li_MinHeight)
			var height = li_MinHeight;
		else
			var height = object.getElementsByTagName('div')[0].offsetHeight;
		if(firstLoop){
			heightAdjust = height-object.offsetHeight;
			object.style.height = height;
			firstLoop = false;
		}else{
			object.style.height = object.offsetHeight+heightAdjust;
		}
	}
	if(ok)
		show_hide(object.parentNode,firstLoop,heightAdjust);
	return false;
}

Le plus rapide serait de lire le code source de ma page de test !
Modifié par thepiouf (01 May 2011 - 14:19)
Excusez-moi mais je vois pas bien où est la solution s'il faut utiliser du javascript pour pouvoir utiliser les transitions CSS3 !!!
@gc-nomade : dans ton exemple si on désactive le JS y a plus de sous-menu du tout... Je pense qu'il serait plus judicieux de faire un menu déroulant animé en JS avec un fallback CSS qui n'utilise pas les transitions. Comme ça si le navigateur supporte le JS il a un joli menu animé et si le JS est désactivé le menu fonctionne toujours mais sans l'animation... Smiley ravi
Bonsoir gaby22. en effet un menu déroulant se devrait d’être interactif via js, ne pas dépendre uniquement de réglé CSS et ne pas être cantonné a ne inter-agir qu'au survol de la souris. Il n'y a pas de solution universelle.

Le JavaScript peut modifié les styles et tester ceux qui sont appliqués ou applicables, mais l'inverse n'est pas possible.

Il n'y a pas de solution universelle, et l'exemple que j'ai proposé répond principalement 'a la question css transition avec height.
Height:auto ne renvoie aucune valeur et l'effet de transition va passer d'un état a un autre sans palier, d'ou mon exemple avec un max-height. Solution rigide qui va dérouler tout les sous-menu à la même vitesse, quelque soit leur contenu/hauteur, au risque d'en guillotiner certains.

JavaScript peut permettre de connaitre la hauteur total d'un élément et de renvoyer cette valeur dans une règle CSS, la c'est déjà moins rigide que le max-height arbitraire.

Pour ce qui est de tout les autres aspects "d’accessibilité" ou de menu efficient, il faut effectivement un fall-back au cas ou CSS et JS ne sont pas ou peu disponible au visiteur.

C'est au par coup qu'il faut choisir les styles que tu vas injecter via les feuilles de styles et ceux que tu vas injecter via js.

Si tu admet que le JavaScript est nécessaire a un menu déroulant, il ira de soi que l'aspect transition ou déroulant sera gérer via JS (en tout ou partie), ... une fois que le menu a une base fonctionnelle plutôt qu'avant.

cordialement,
GC