27822 sujets

CSS et mise en forme, CSS3

Modérateur
Hello,

Pour la première partie de l'animation, avec bootstrap, tu peux utiliser un simple collapse. Voici un example qui fait ce que tu montres (clique "open" et ensuite "cancel").

Pour la partie du # d'items à ajouter, ça me parait un peu plus touchy :
- il faut créer le nouvel item à la volée, l'animer et supprimer l'ancien
- et surtout d'un point de vue utilisateur, si je veux 100 items, j'espère pouvoir rentrer une valeur et pas devoir cliquer 99x sur le plus…

On est d'accord c'est plus que réalisable mais ça dépendra de ton niveau et ton investissement dans le projet. N'hésite pas à poster ton code si tu bloques Smiley smile
Pour créer un gif animé, il te faut faire (1) une capture d’une série d’images, puis (2) créer avec cette série un gif animé.
Une fois que tu as créé ton gif animé, que tu utilises boostrap ou un autre framework, le problème sera le même. C’est (3) une insertion d’une image classique.
Quel point te pose problème?
Modérateur
Bonjour,

Je dois dire que j'ai un peu de mal à voir l'intérêt de bootstrap ici alors qu'il y a 1 ligne de css à faire pour réaliser chacun des effets demandés, et 3 très petites fonctions javascript à écrire pour gérer les boutons.

Evidemment, y a pas mal de css à faire pour mettre en place les éléments (c'est ça qui est le plus long en fait), mais ce n'est pas clair qu'on mettrait moins de temps avec une approche totalement "bootstrapienne" !

<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body
{
	margin:0;
	padding:0;
}
#contenu
{
	width:16rem;
	height:4rem;
	margin:0 auto;
	background:#eea595;
	box-shadow:0 0.5rem 0.25rem #eaeaea;
}
form
{
	font-family:arial,sans-serif;
	position:absolute;
	left:calc(50% - 8rem);
	top:2.5rem;
	width:16rem;
	height:5rem;
	margin:0;
	padding:0;
	overflow:hidden;
}
fieldset
{
	border:0;
	margin:0;
	padding:0;
	position:absolute;
	display:block;
	left:0;
	right:0;
	height:5rem;
	transition:top 0.5s ease;
}
fieldset:first-of-type
{
	top:0;
}
fieldset:last-of-type
{
	top:-5rem;
}
[type="submit"],button
{
	display:block;
	box-sizing:content-box;
	font-size:1rem;
	font-family:arial,sans-serif;
	position:absolute;
	font-weight:bold;
	text-align:center;
	padding:0;
	margin:0;
}
[type="submit"]:focus,button:focus
{
	outline:0;
}
[type="submit"]:hover,button:hover
{
	cursor:pointer;
}
[id="moins"],
[id="plus"]
{
	background:transparent;
	border:0;
	width:1.75rem;
	height:1.75rem;
	top:0.5875rem;
}
[id="moins"]
{
	left:20%;
}
[id="plus"]
{
	right:20%;
}
[id="fois"]
{
	background:transparent;
	border:0;
	height:1.25rem;
	width:1.25rem;
	top:3.75rem;
	left:calc(50% - 0.625rem);
}
svg
{
	width:100%;
	height:100%;
}
[id="moins"] svg,
[id="plus"] svg
{
	fill:#fff;
	stroke:#fe9566;
}
[id="fois"] svg
{
	fill:#fe9566;
	stroke:#fff;
}
[type="submit"]
{
	height:3rem;
	line-height:3rem;
	text-transform:uppercase;
	width:calc(100% - 2rem);
	margin:0;
	top:0;
	left:1rem;
	border:0.125rem solid #fe9566;
	border-radius:1.5rem;
	color:#fe9566;
	background:#fff;
	box-shadow:0 0.25rem 0.125rem #e0e0e0;
}
#num
{
	position:absolute;
	top:0;
	left:calc(50% - 1.5rem);
	width:3rem;
	height:3rem;
	line-height:3rem;
	border-radius:1.5rem;
	background:#fe9566;
	color:#fff;
	border:0;
	box-shadow:0 0.25rem 0.125rem #e0e0e0;
	overflow:hidden;
}
#innum
{
	position:absolute;
	top:0;
	transition:top 0.25s ease;
}
#innum span
{
	display:block;
	width:3rem;
	height:3rem;
	line-height:3rem;
	text-align:center;
	font-size:1.5rem;
	font-weight:bold;
}
</style>
<script>
var num=1;
function doReserve()
{
	document.querySelector('fieldset:first-of-type').style.top="5rem";
	document.querySelector('fieldset:last-of-type').style.top="0";
}
function doLess()
{
	num--;
	if(num<1) num=1;
	document.querySelector('[id="innum"]').style.top=(-(num-1)*3)+"rem";
	document.querySelector('[name="num"]').value=num+"";
}
function doMore()
{
	num++;
	if(!document.querySelector('[id="innum"] span:nth-of-type('+num+')'))
	{
		let e;
		e=document.createElement("span");
		e.innerHTML=num+"";
		document.querySelector('[id="innum"]').appendChild(e);
	}
	document.querySelector('[id="innum"]').style.top=(-(num-1)*3)+"rem";
	document.querySelector('[name="num"]').value=num+"";
}
</script>
</head>
<body>
<div id="contenu">
<form>
<fieldset>
<button type="button" id="moins" onclick="doLess();">
<svg viewbox="0 0 28 28" stroke-width="2">
<circle cx="14" cy="14" r="13"/>
<line x1="10" y1="14" x2="18" y2="14"/>
</svg>
</button>
<div id="num">
<div id="innum">
<span>1</span>
</div>
</div>
<button type="button" id="plus" onclick="doMore();">
<svg viewbox="0 0 28 28" stroke-width="2">
<circle cx="14" cy="14" r="13"/>
<line x1="9" y1="14" x2="19" y2="14"/>
<line x1="14" y1="9" x2="14" y2="19"/>
</svg>
</button>
<button type="button" id="fois" onclick="doReserve();">
<svg viewbox="0 0 28 28" stroke-width="2">
<circle cx="14" cy="14" r="13"/>
<line x1="9" y1="9" x2="19" y2="19"/>
<line x1="9" y1="19" x2="19" y2="9"/>
</svg>
</button>
</fieldset>
<fieldset>
<input type="hidden" name="num" value="1">
<input type="submit" value="Je réserve">
</fieldset>
</form>
</div>
</body>
</html>


EDIT: un jsfiddle pour tester à https://jsfiddle.net/5mh8ns3k/
Amicalement,
Modifié par parsimonhi (05 Oct 2020 - 23:58)
Modérateur
Bonjour,

Et voici un code bootstrapien.

Je ne sais pas s'il y a un truc pire dans la vie d'un développeur que de transformer un code en javascript+css pur relativement concis qui marche plutôt bien en un code bootstrapien (un peu) plus long, (beaucoup) plus lent, et (pas moins) compliqué. Smiley lol Smiley lol Smiley lol

Il reste pas mal de css (en particulier pour spécifier les couleurs). C'est sans doute "améliorable" s'il y a des variables bootstrap pour le thème du site qui ont ces couleurs comme valeur.

Faut d'indication concernant les tailles de tout ça, je les ai aussi laissées en dur dans le css. C'est facilement modifiable.

J'ai laissé le contenu des boutons en svg : j'aime beaucoup le svg.

J'ai gardé les animations (des transitions css en fait) qui se déclenchent sur un changement de la propriété css "top" (comme c'était déjà le cas pour le code en javascript+css purs que j'avais donné dans ma réponse précédente). Je n'ai pas trouvé plus simple. Mais si ça se trouve, il y a un truc tout fait qui gère tout ça (les animations et les actions des boutons) et qui a déjà été téléchargé 10 millions de fois Smiley cligne .

Eventuellement, il faudra adapter en fonction du contexte. En particulier, ça dépend si tout est contenu dans une balise <form> avec un bouton "submit" pour l'action de réserver comme je l'ai fait, ou bien si l'action de réserver est gérée autrement, ce qui peut donc changer la manière de faire apparaitre et éventuellement disparaitre le bouton "Je réserve"; dans la variante que j'ai choisi, après avoir cliqué sur "Je réserve", on exécute l'action d'un formulaire et donc on change de page; du coup, je n'ai pas animé la disparition de ce bouton. Si par contre on ne change pas de page, alors il faudra peut-être considérer la piste indiquée par yordi et voir du côté des dialogues modaux bootstrap.

Enfin, comme j'ai transformé du javascript+css pur en bootstrap+jquery, il reste probablement des trucs qui pourraient gagner à être bootstrapisés !

<!DOCTYPE html>
<html lang="fr">
<head>
  <title>Exemple Bootstrap</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
<style>
.container.my-container
{
	width:16rem;
	height:4rem;
	background:#eea595;
	box-shadow:0 0.5rem 0.25rem #eaeaea;
	padding:2.5rem 0 0 0;
}
form
{
	height:5rem;
}
fieldset
{
	height:5rem;
	transition:top 0.5s ease;
}
fieldset:first-of-type
{
	top:0;
}
fieldset:last-of-type
{
	top:-10rem;
}
.my-btn-circle1.btn
{
	width:1.75rem;
	height:1.75rem;
	border:0;
    border-radius:0.875rem;
    padding:0;
}
.my-btn-circle1.btn:first-of-type
{
	left:10%;
}
.my-btn-circle1.btn:last-of-type
{
	right:10%;
}
.my-btn-circle1.btn svg
{
	fill:#fff;
	stroke:#fe9566;
}
.my-btn-circle2.btn
{
	height:1.25rem;
	width:1.25rem;
    border-radius:0.625rem;
    padding:0;
}
.my-btn-circle2.btn svg
{
	fill:#fe9566;
	stroke:#fff;
}
.my-btn-reserve.btn
{
	height:3rem;
	width:14rem;
	border:0.125rem solid #fe9566;
	border-radius:1.5rem;
	color:#fe9566;
	background:#fff;
	box-shadow:0 0.25rem 0.125rem #e0e0e0;
}
.my-num
{
	width:3rem;
	height:3rem;
	border-radius:1.5rem;
	background:#fe9566;
	color:#fff;
	box-shadow:0 0.25rem 0.125rem #e0e0e0;
}
.my-num>div
{
	top:0;
	transition:top 0.25s ease;
}
.my-num>div>div
{
	width:3rem;
	height:3rem;
	line-height:3rem;
	font-size:1.5rem;
}
</style>
</head>
<body>

<div class="container my-container">

<form class="overflow-hidden">
  <fieldset class="position-relative">
    <div class="d-flex justify-content-around align-items-center">
      <button type="button" class="btn my-btn-circle1 position-relative">
          <svg viewbox="0 0 28 28" stroke-width="2">
            <circle cx="14" cy="14" r="13"/>
            <line x1="10" y1="14" x2="18" y2="14"/>
          </svg>
      </button>
      <div class="my-num overflow-hidden">
        <div class="position-relative font-weight-bold text-center">
          <div>1</div>
        </div>
      </div>
      <button type="button" class="btn my-btn-circle1 position-relative">
        <svg viewbox="0 0 28 28" stroke-width="2">
          <circle cx="14" cy="14" r="13"/>
            <line x1="9" y1="14" x2="19" y2="14"/>
            <line x1="14" y1="9" x2="14" y2="19"/>
        </svg>
      </button>
    </div>
    <div class="d-flex justify-content-around align-items-center">
      <button type="button" class="btn my-btn-circle2">
        <svg viewbox="0 0 28 28" stroke-width="2">
          <circle cx="14" cy="14" r="13"/>
          <line x1="9" y1="9" x2="19" y2="19"/>
          <line x1="9" y1="19" x2="19" y2="9"/>
        </svg>
      </button>
    </div>
  </fieldset>
  <fieldset class="position-relative text-center">
    <input type="hidden" name="num" value="1">
    <button type="submit" class="btn my-btn-reserve text-uppercase">
      Je réserve
    </button>
  </fieldset>
</form>

</div>
<script>
$(function(){

$('.my-btn-circle2').on('click', function (e) {
	$('fieldset:last-of-type').css({top: "-5rem"});
	$('fieldset:first-of-type').css({top: "5rem"});
});

$('.my-btn-circle1:first-of-type').on('click', function (e) {
	var num=$('[name="num"]').val()-1;
	if(num<1) num=1;
	$('.my-num>div').css({top: -(num-1)*3)+"rem"});
	$('[name="num"]').val(num);
});

$('.my-btn-circle1:last-of-type').on('click', function (e) {
	var num=$('[name="num"]').val()-(-1);
	if(!$('.my-num>div>div:nth-of-type('+num+')').length)
		$('.my-num>div').append("<div>"+num+"</div>");
	$('.my-num>div').css({top: -(num-1)*3)+"rem"});
	$('[name="num"]').val(num);
});

});
</script>
</body>
</html>

Amicalement,
Modifié par parsimonhi (06 Oct 2020 - 13:14)