28172 sujets

CSS et mise en forme, CSS3

Bonjour,

J'aurais aimé avoir quelques conseils pour aligner correctement mes formulaires de façon efficace et responsive.

Je crois que j'ai presque trouvé ce que je voulais avec display:table, à un détail près...

Exigeances/notes:
1 - Je pourrais faire beaucoup plus simple en donnant une taille aux labels. Mais justement je voudrais ne pas devoir spécifier de taille nulle part, afin que ça se passe le plus facilement possible quelque soit la taille de l'écran. D'où une tentative avec display:table.
2 - Les flottants, je voudrais éviter; enfin disons plutôt que je ne les maîtrise que moyennement et j'obtiens parfois des choses inattendues et inexpliquables quand je'ssaie de les utiliser; bref c'est pas bullet-proof dans toutes les situations.
3 - J'aimerais conserver un code HTML aussi simple que possible, en évitant au maximum de multiplier les <div> et autres éléments sémantiquement inutiles. De nouveau pour que ça passe comme sur des roulettes avec les mobiles.
4 - Niveau compatbilité, tant que ça marche sur les navigateurs plus ou moins récents et IE11, ça ira

Mon problème avec mon code actuel utilisant display:table, c'est les boutons à la fin du formulaire.
Ce serait mieux s'ils s'affichaient côte-à-côte, et que le premier soit aligné avec le bord gauche des champs et non pas tout au bord gauche de la page, non ?
LE reste, apparament, ça a l'air de marcher pas trop mal.

Questions plus générales:
Est-ce qu'utiliser display:table dans ce contexte est judicieux ?
Peut-on faire mieux avec flexbox ? Comment ? J'ai du mal à comprendre comment flexbox fonctionne...

Merci pour vos réponses.


form { 
display: table; 
}

form>p { 
display: table-row; 
}

form p>input, form p>label, form p>span  { 
display: table-cell; 
}

label { 
text-align: right; 
padding-right: 7px; 
}



<form>
<p><label for="one">Label 1: </label>
<input type="text" id="one" value="blabla" />
<span>Valeur incorrecte</span>
</p>
<p><label for="two">Label 2 plus long: </label>
<input type="text" id="two" value="bip bip" />
<span>Valeur incorrecte</span>
</p>
<p><label for="three">Un très très très long label: </label>
<input type="text" id="three" value="coyote" />
<span>Valeur incorrecte</span>
</p>
<p>
<input type="submit" value="Valider" />
<input type="reset" value="Annuler" />
</p>
</form>
Bonsoir.

On peut y arriver avec votre système avec :
form > p:last-child::before
	{
	content: "";
	display: table-cell;
	}


Ce qui est amusant avec ::before, c'est que cela ne positionne pas vraiment 'avant' mais dedans et au début...

Smiley smile
Bonjour,
Vous allez être embêté avec les checkbox qui ont un label à droite (idem pour les radio).
Personnellement, j'ai tout encapsulé dans des span, quitte à avoir des span vides dans ce cas (ou une classe particulère et une pseudo-classe ::bofore comme suggéré par Zelena), et ce sont les spans qui reçoivent les styles de mise en page form>p>span{display:table-cell;}.
Cela permet de différencier les label à gauche (p>span:first-child>label} des label à droite (p>span+span>input+label).

Avec flex, je ne crois pas qu'on puisse faire mieux sans préciser de largeur fixe, vu que chaque paragraphe aurait son propre algo de calcul des largeurs.
Modifié par Seven tears (07 May 2017 - 20:04)
Modérateur
Seven tears a écrit :
Bonjour,
Vous allez être embêté avec les checkbox qui ont un label à droite (idem pour les radio).
Personnellement, j'ai tout encapsulé dans des span, quitte à avoir des span vides dans ce cas (ou une classe particulère et une pseudo-classe ::bofore comme suggéré par Zelena), et ce sont les spans qui reçoivent les styles de mise en page form&gt;p&gt;span{display:table-cell;}.
Cela permet de différencier les label à gauche (p&gt;span:first-child&gt;label} des label à droite (p&gt;span+span&gt;input+label).

Avec flex, je ne crois pas qu'on puisse faire mieux sans préciser de largeur fixe, vu que chaque paragraphe aurait son propre algo de calcul des largeurs.

tout a fait d'accord, un code pen pour illustrer https://codepen.io/anon/pen/pPdOyE

avec display:table, il y a 2 soucis:

- display:table-cell sur un input est sans réel effet (au mieux un conteneur supplementaire est génerer par le navigateur ... comme l'est tbody si est manquant dans un tableau)
- chaque row doit avoir le même nombre d'enfant , colspan n'existe pas en CSS

Avec flex (flex:x;) + justify-content et toujours un span et un pseudo autour des input https://codepen.io/anon/pen/qmVMRy

avec grid, on dispatch ou l'on veut les éléments et les <p>sont inutiles https://codepen.io/anon/pen/jmavBM
Modifié par gcyrillus (07 May 2017 - 23:45)
Pour l'alignement de tes boutons valider et annuler tu peux rajouter le label sans mettre de texte et ils s'aligneront avec tes autres inputs...

<p><label></label>
        <input type="submit" value="Valider" />
        <input type="reset" value="Annuler" />
</p>

Bonne nuit
Re,
@gcyrillus
Pour illustrer plus précisément, il ne faut pas utiliser systématiquement des input de type text : avec vos exemples, je ne comprenais pas, initialement, pourquoi un display flex donnait le résultat attendu, mais insérer ici ou là des textarea (qui n'ont pas la même largeur par défaut) permet de mieux comprendre les mécanismes sous-jacents.

@GJboba : la pseudo-classe ::before répond à ce problème., sans créer d'élément vide.
Pour flex je ne sais pas, je ne maîtrise pas encore mais je te propose une solution sans table-cell avec des tailles en %: j'ai gardé ton code et mis le mien à la suite pour que tu puisses comparer les comportements...

Avec les % tu vas avoir des comportements différents en fonction du fait que tu vas
dimensionner ou non le container global du formulaire (ici <div class='f2'>)
essai avec .f2 { width: 750px; } par exemple
Fait varier la taille de ta page pour comparer...

Bonne continuation

<!DOCTYPE html>

<html>
    <head>
        <title>TODO supply a title</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <style>
             
            .f1 form { 
                    display: table; 
                }

            .f1 form>p { 
                display: table-row; 
            }

            .f1 form p>input, form p>label, form p>span  { 
                display: table-cell; 
            }

            .f1 label { 
                text-align: right; 
                padding-right: 7px; 
            }
            
            
            .f2 form {
                display: block;
                width: 100%;
            }
            .f2 div {
                display: block;
            }
            .f2 label {
                display: inline-block;
                text-align: right;
                width: 20%;
            }
            .f2 input {
                display: inline-block;
            }
            .f2 input[type='text'] {
                width: 20%;
            }
            .f2 input[type='checkbox'] {
                margin-right: 20%;
            }
            .f2 input[type='radio'] {
                margin-right: 20%;
            }
            .f2 span {
                display: inline-block;
                width: 20%;
            }
            
        </style>
            
    </head>
    <body>
        <div class="f1">
            <form>
            <p><label for="one">Label 1: </label>
            <input type="text" id="one" value="blabla" />
            <span>Valeur incorrecte</span>
            </p>
            <p><label for="two">Label 2 plus long: </label>
            <input type="text" id="two" value="bip bip" />
            <span>Valeur incorrecte</span>
            </p>
            <p><label for="three">Un très très très long label: </label>
            <input type="text" id="three" value="coyote" />
            <span>Valeur incorrecte</span>
            </p>
            <p>
            <p><label></label>
            <input type="submit" value="Valider" />
            <input type="reset" value="Annuler" />
            </p>
            </form>
        </div>
        <div class="f2">
            <form>
                <div><label for="one">Label 1: </label>
                <input type="text" id="one" value="blabla" />
                <span>Valeur incorrecte</span>
                </div>
                <div><label for="two">Label 2 plus long: </label>
                <input type="text" id="two" value="bip bip" />
                <span>Valeur incorrecte</span>
                </div>
                <div><label for="three">Un très très très long label: </label>
                <input type="text" id="three" value="coyote" />
                <span>Valeur incorrecte</span>
                </div>
                <div><label for="four">Auto: </label>
                    <input type="checkbox" name="vehicule" value="moto">
                <span>commentaire</span>
                <div><label for="four">Moto: </label>
                    <input type="checkbox" name="vehicule" value="auto">
                <span>commentaire</span>
                <div><label for="fife">Homme: </label>
                    <input type="radio" name="genre" value="homme">
                <span>commentaire</span>
                <div><label for="six">Femme: </label>
                    <input type="radio" name="genre" value="femme">
                <span>commentaire</span>
                <div><label></label>
                <input type="submit" value="Valider" />
                <input type="reset" value="Annuler" />
                </div>                
            </form>
        </div>
    </body>
</html>
Bonsoir,

Merci pour vos réponses.

Je trouve l'astuce du before + content vide bien trouvée !
J'ai évidemment pensé à mettre un élément HTML (pe importe que ce soit span ou label) sans contenu, mais ça me paraissait être de la bidouille pas très saine sémantiquement parlant. ET de toute manière ça n'aurait pas résolu la position du deuxième bouton qui aurait quand même était beaucoup trop à droite au lieu d'être juste à côté du premier.

a écrit :
Cela permet de différencier les label à gauche (p>span:first-child>label} des label à droite (p>span+span>input+label).


Ca aussi c'est astucieux.

Du coup pour la checkbox et son label qui doit être à droite, ), je déduis du sélecteur que tu proposes que le span vide est obligatoire et que la technique du ::before ne marche pas ?

a écrit :
Avec flex, je ne crois pas qu'on puisse faire mieux sans préciser de largeur fixe, vu que chaque paragraphe aurait son propre algo de calcul des largeurs.


C'est bien ce que je craignais, chaque « boîte » qu'aurait formé chaque p aurait donc été indépendantes les unes des autres et il n'y aurait pas eu de moyen de leur appliquer un comportement collectif sans spécifier de taille nulle part.

a écrit :
avec grid, on dispatch ou l'on veut les éléments et les <p>sont inutiles
https://codepen.io/anon/pen/jmavBM


Wah! Ca a l'air assez génial ça. Par contre je ne comprends pas grand chose au code...

a écrit :
Pour flex je ne sais pas, je ne maîtrise pas encore mais je te propose une solution sans table-cell avec des tailles en %


Comme je l'ai dit en premier post, peut-être pas assez clairement, le but du jeu est de faire quelque chose qui peut s'appliquer à peu près à toutes les situations raisonnables. ET pour cela je pars du principe (peut-être à tort) que moins on spécifie de tailles, plus on a de chance pour que ça passe crème sur un maximum d'écrans.
Indiquer une taille même relative pour les labels ne me plaît pas, car je n'ai aucune véritable idée de la taille qu'ils vont occuper réellement. Ils ne feront jamais 2km, mais pour le reste je ne sais pas précisément.

Je ne vous l'ai pas dit, les habitués le savent déjà: je suis non-voyant. L'objectif c'est donc qu'une fois le code CSS terminé, je voudrais partir du principe qu'il marche tout le temps sans que je n'aie plus jamais à m'en préoccuper.
C'est aussi pour ça que les float ne me plaisent pas non plus, ça a un comportement trop capricieux, voire carrément aléatoire à mon niveau de compréhension. Les grilles et les tableaux au moins c'est facile à comprendre.
QuentinC a écrit :
Du coup pour la checkbox et son label qui doit être à droite, je déduis du sélecteur que tu proposes que le span vide est obligatoire et que la technique du ::before ne marche pas ?

Non, c'est juste que j'avais fait un choix à l'époque, l'autre étant de mettre une classe sur le paragraphe pour lui indiquer qu'il n'y a qu'un span et qu'il faut donc créer un élément avec :before. Le choix du span vide m'avait semblé plus pertinent, peut-être une question de support du :before dans ce temps-là (je parle comme un vieux, ça fait peur). On doit pouvoir faire mieux maintenant avec les sélecteurs CSS3 (avec :only-child par exemple).

Sinon, grid, j'ai bavé quand j'ai lu les specs il y a 4 ans. Je viens de voir avec l'article de Raphaël que c'était maintenant supporté par tous les navigateurs modernes, il va falloir que je m'y mette.

QuentinC a écrit :
Je ne vous l'ai pas dit, les habitués le savent déjà: je suis non-voyant.

Je sais, je te connais depuis TJS l'ami Smiley cligne (MrJo à l'époque, pareil, ça nous rajeunit pas Smiley vieux )