5542 sujets

Sémantique web et HTML

Bonjour à tous
Je suis en train de mettre à jour un vieux bout de code contenant un <form>. Tant qu'à faire j'aimerais le mettre au goût du jour.
A l'époque le façon de faire consistait à écrire quelque chose comme:

<form....>
  <table>
    <tr>
        <th>Le texte explicatif:</th>
        <td><input ...></td>
    </tr>
    ....
  </table>
</form>


En utilisant HTML5 et CSS3, on peut simplifier le code en remplaçant chaque <tr> par un

<label><span>Le texte explicatif:</span><input...></label>

Cette forme de <label> (sans "for=") évite de devoir donner un id à chaque <input>, ce qui est important si on est dans le contexte de nombreuses <form>

Le problème, c'est qu'on a parfois besoin d'ajouter dans chaque "ligne" d'autres éléments explicatifs.

La doc dit que les <label> sont des éléments inline, mais il n'est pas clair si on doit les considérer comme des éléments similaires à <span>, auquel cas on ne peut pas mettre à l'intérieur des éléments de type block, ou si ce sont des "inline-block", auquel cas on peut y mettre tout ce qu'on veut.
Comment faites vous?
Modérateur
Et l'eau,

tu peux très bien faire ceci :


<form action="">
    <div class="input text">
        <label>
            <span>label pour un champ</span>
            <input type="text" id="un_champ" name="un_champ">
        </label>
    </div>
</form>
Modérateur
bonjour, les éléments en ligne ne peuvent avoir comme enfant que d'autre élément en ligne. pas de div ou de p par exemple. ça c'est pour la sémantique.

Coté CSS, display:block sur un label et son span enfant ne sont pas interdit, c'est juste un rendu visuel qui ne change en rien la sémantique de ton document.

Tu peut donc construire ton document de façon valide puis le styliser sans t’inquiéter.

Cdt,
Modifié par gcyrillus (18 Mar 2020 - 12:30)
Modérateur
gcyrillus a écrit :
bonjour, les éléments en ligne ne peuvent avoir comme enfant d'autre élément en ligne. pas de div ou de p par exemple. ça c'est pour la sémantique.


Je pense que tu veux plutôt dire :
les éléments en ligne ne peuvent avoir comme enfant d'autre élément de type block.

exemple à ne pas faire suite à ta remarque :

<span>
        <div></div>
</span>

Modifié par niuxe (18 Mar 2020 - 12:28)
Dans le cas d'infos supplémentaires, j'aurais

<form>
  <div class="input">
    <label><span>texte</span><input ></label>
      <div class="info">.....</div>
  </div>
</form>

mais comment styler ça pour que les textes soient ajustés l'un au dessus de l'autre, ce que les <table> font par construction?
Toutes les solutions auxquelles j'arrive reviennent à insérer des <div> intermédiaires, je me me retrouve avec l'équivalent de mon design par <table> avec un code plus difficile à lire.
Pour mieux expliquer le problème, voici le code actuel à "mettre à la mode":

<form name="uploadForm" enctype="multipart/form-data" method="post" action="uploadReport.php">
  <table style="margin:auto;">
    <tr>
      <th colspan="2" style="text-align:center;">Chargement d'un compte rendu</th>
    </tr>
    <tr>
      <th>Fichier PDF à charger:</th>
        <td>
          <input type="hidden" name="MAX_FILE_SIZE" value="1000000" />
          <input name="uploadedfile" type="file" size="50" />
	    </td>
    </tr>
    <tr>
      <th>Type de réunion:</th>
        <td>
          <select id="meetingType" name="meeting" onchange="setMeetingType();">
            <option value="CA" selected="selected">Réunion du CA</option>
            <option value="AG">Assemblée générale</option>
            <option value="other">autre</option>
          </select>
          <input id="other" name="other" style="display:none;" type="text" />
      </td>
    </tr>
    <tr>
      <th>Date de la réunion:</th>
      <td id="dateCell" onmouseover="showCalendar();">
        <input name="meetingDate" type="text" value="" />
      </td>
    </tr>
    <tr>
      <th colspan="2" style="text-align:center;">
        <input type="button" value="OK" onclick="upload();" />
        <input type="button" value="Abandon" onclick="parent.closeUpload();" />
      </th>
    </tr>
  </table>
</form>

Le contexte: il s'agit d'uploader un compte rendu de réunion.
la <form> est dans un <iframe>
La fonction showCalendar() génère un calendrier graphique et le positionne (avec pas mal de difficulté) au bon endroit. Aujourd'hui j'ajouterais une <div> position:relative dans la cellule contenant
<input name="meetingDate" type="text" value="" />

pour y ancrer le calendrier en question.
Vous remarquerez que la mode de l'époque était le XHTML, d'où les "/>" pour clore les <input>
Modifié par PapyJP (18 Mar 2020 - 14:12)
Modérateur
quelle visuel recherches tu à faire ? edit, okay, vu !

... label{display:block} ne vas pas ?

Ensuite, un label et un div côte à côte n'est pas valide.

en gros la logique HTML à suivre :
inline/inline-block : éléments dans le flux d'une zone d'élément eux même inline.(pas de frère en block)

block : élément de structures dans le flux d’éléments block uniquement. (pas de frères inline).

L’exception: la balise <a> , probablement une french touch.

Rappel Smiley cligne :display:inline/block ne modifie que le visuel et ne change pas le code HTML.
Modifié par gcyrillus (18 Mar 2020 - 13:30)
Modérateur
Voici un exemple possible:

<form name="uploadForm" id="bis" enctype="multipart/form-data" method="post" action="uploadReport.php">
  <fieldset>
    <legend>Chargement d'un compte rendu</legend>
    <label><b>Fichier PDF à charger: </b>
      <input type="hidden" name="MAX_FILE_SIZE" value="1000000" />
      <input name="uploadedfile" type="file" size="50" /></label>
    <label><b>Type de réunion: </b>
      <select id="meetingType" name="meeting" onchange="setMeetingType();">
        <option value="CA" selected="selected">Réunion du CA</option>
        <option value="AG">Assemblée générale</option>
        <option value="other">autre</option>
      </select>
      <input id="other" name="other" style="display:none;" type="text" />
    </label>
    <label><b>Date de la réunion:</b>
      <span id="dateCell" onmouseover="showCalendar();">
        <input name="meetingDate" type="text" value="" />
      </span></label>
    <input type="button" value="OK" onclick="upload();" />
    <input type="button" value="Abandon" onclick="parent.closeUpload();" />
  </fieldset>
</form>

et le css :
form {
  display: table;/* [cligne] provocation gentille (ou width:max-content) , => optionnel met un bg pour voir si utile */
  margin: auto;
  text-align: center;
}
label {
  display: block;
}
fieldset {
  border: none;
}
legend {
  width: 100%;
  font-weight: bold;
}
#dateCell {
  display: inline-block;
  position: relative;
}


et le codepen pour tester et jouer avec https://codepen.io/gc-nomade/pen/zYGaRZB

Est ce que cela commence à répondre à tes interrogations ?
Modifié par gcyrillus (18 Mar 2020 - 13:45)
Meilleure solution
Grâce à <input type="date"> la complexité du code a soudainement disparu...
Voici ce que ça donne. Merci encore pour ton aide.

<form name="uploadForm" enctype="multipart/form-data" method="post" action="uploadReport.php"  autocomplete="off">
  <fieldset>
  <legend>Chargement d'un compte rendu</legend>
  <label><b>Fichier PDF à charger: </b>
    <input type="hidden" name="MAX_FILE_SIZE" value="1000000">
    <input name="uploadedfile" type="file" size="50"></label>
  <label><b>Type de réunion: </b>
    <select id="meetingType" name="meeting" onchange="setMeetingType();">
    <option value="CA" selected="selected">Réunion du CA</option>
    <option value="AG">Assemblée générale</option>
    <option value="AGE">Assemblée générale extraordinaire</option>
    <option value="other">autre</option>
    </select>
    <input id="other" name="other" type="text" >
  </label>
  <label><b>Date de la réunion:</b>
    <input name="meetingDate" type="date" value="">
    </span>
  </label>
  <div class="controls">
    <input type="button" value="OK" onclick="upload();">
    <input type="button" value="Abandon" onclick="parent.closeUpload();">
  </div>
  </fieldset>
</form>


form  * {
	padding:0.25em 0;
}
label {
  display: block;
}
fieldset {
  border: none;
}
legend {
  width: 100%;
	text-align:center;
  font-weight: bold;
	font-size:1.1em;
}
label {
        display:block;
	position:relative;
}
label b {
	display:inline-block;
	width:12em;
}
select, input[type="text"] {
	border-radius:0.5em;
}
option {padding:0;}
#other {display: none;}
#other.active {
	display: block;
	position:absolute;
	top:1em;
	left:13em;
	width:17em;
	z-index:100;
}
div.controls {
	text-align: center;
}
div.controls > * {
	display: inline-block;
	border:1px solid gray;
	padding:0.5em;
	min-width:5em;
	border-radius:0.5em;
	margin:0 0.25em;
	
}

Remarque: ça fonctionne en mettant des "display" appropriés dans le CSS
Si je comprends bien, le navigateur vérifie d'abord que le CSS est cohérent, c'est à dire par exemple qu'il n'y a pas de balise définies comme de type block à l'intérieur de balises de type inline. Une fois cette vérification initiale réalisée il applique le CSS qui peut styler les balises comme il l'entend.
J'avais déjà noté qu'on peut mettre un <button> dans un <p>, et comme un <button> est défini comme inline-block par défaut, on peut mettre des blocks à l'intérieur d'un <button>, ce qui m'a été fort utile dans un autre contexte.
Modifié par PapyJP (18 Mar 2020 - 17:08)
Modérateur
en fait les navigateurs sont plutôt cool, ils vont tenter de réparer les erreurs html et afficher le doc et les styles autant qu'ils le peuvent , il se peut que l'(es) erreur(s) trouvée(s) provoque(nt) un affichage différent d'un nav à l'autre , chacun pouvant faire une correction différente.

L'exemple le plus courant est la balise <tbody> systématiquement ajouté dans un tableau si elle n'est pas présente, une erreur sans conséquence sauf si un sélecteur CSS ne la prend pas en compte . ex sur codepen : table>tr

Les erreurs vont devenir éventuellement un problème pour le référencement, les lecteurs d’écrans, les scripts parcourant le DOM .

Il y a deux manière rapide de vérifier la construction d'un document :

1) pour se faire une idée rapide : afficher la page sans aucun style. Si le contenu devient illisible ou incohérent. il y a un soucis .

2) le validateur du w3c https://validator.w3.org/#validate_by_input+with_options la aussi , c'est pour te donner une idée. par exemple ton code passé au validateur met en évidence que tu as laisser trainé un </span> (probablement coincé là par le confinement Smiley cligne ).

Bonne continuation
Modifié par gcyrillus (18 Mar 2020 - 17:48)
Problème annexe:
upload/1584549696-48769-iframe.png

Comme je l'ai déjà remarqué dans d'autres circonstances, la bordure droite de l'iframe n'est pas correctement affichée:
Code CSS

#uploadFrame.active {
	display: block;
	background:white;
	position:absolute;
	top: 2em;
	left:50%;
	width:80%;
	transform:translateX(-50%);
	height:15em;
	padding-top:2em;
	background:white;
	border:1px solid black;
	border-radius: 0.5em;
}

Je sais que par défaut les bordures des iframe sont stylées différemment selon les navigateurs, mais si je mets une définition homogène il ne devrait pas y avoir de problème.
Modérateur
c'est étrange, la partie de la bordure manquante semble correspondre à la position d'une barre de défilement du document embarqué a 2em du haut , scroll que l'on ne voit pas apparaitre .
avec un padding tout autour de l'iframe, tu pourrais vérifier si cela est bien ça.

voici une version en HTML valide + mis en iframe pour tester le rendu. https://codepen.io/gc-nomade/pen/QWbxBBp mais je n'ai pas vu ton bug de bordure Smiley decu
Modifié par gcyrillus (18 Mar 2020 - 18:19)
gcyrillus a écrit :
c'est étrange, la partie de la bordure manquante semble correspondre à la position d'une barre de défilement du document embarqué a 2em du haut , scroll que l'on ne voit pas apparaitre .
avec un padding tout autour de l'iframe, tu pourrais vérifier si cela est bien ça.

Le padding:2em (au lieu de padding-top:2em) donne le bon résultat.
Mais il n'y a pas de barre de défilement où que ce soit.
Ce n'est pas la première fois que je rencontre ce genre de problème, je retiens le "truc" de mettre un padding dans <iframe> (et pas simplement dans le document affiché dans <iframe>)