web-dev-qa-db-fra.com

Est-ce que placer une div à l'intérieur d'une ancre est toujours correct?

J'ai entendu dire que placer un élément de bloc à l'intérieur d'un élément en ligne est un péché HTML:

<a href="http://www.mydomain.com"><div>
What we have here is a problem. 
You see, an anchor element is an inline element,
and the div element is a block level element.
</div></a>

Mais qu’en est-il si vous appelez l’ancre externe display:block dans la feuille de style? Est-ce toujours faux? La spécification HTML 4.01 sur des éléments de niveau bloc et inline semble le penser:

Les feuilles de style fournissent les moyens pour spécifier le rendu de l'arbitraire éléments, y compris s'il s'agit d'un élément est rendu sous forme de bloc ou en ligne. Dans certains cas, comme un style en ligne pour les éléments de liste, cela peut être approprié, mais d’une manière générale, les auteurs sont découragés de annulant le conventionnel interprétation des éléments HTML dans par ici.

Quelqu'un at-il d’autres conseils à propos de ce problème?

469
Tom

Selon la version du HTML que vous hébergez:

  • HTML 5 indique que l'élément <a> "peut être entouré de paragraphes, de listes, de tableaux, etc., voire de sections entières, tant qu'il n'y a pas de contenu interactif (par exemple des boutons ou autres liens) ".

  • HTML 4.01 indique que les éléments <a> ne peuvent contenir que éléments en ligne . Un <div> est un élément de bloc , de sorte qu'il peut ne pas apparaître dans un <a>.

    Bien entendu, vous êtes libre de définir un élément en ligne tel que apparaît comme un bloc, ou même de le définir de manière à ce qu’il soit rendu en ligne. L'utilisation des termes inline et block en HTML fait référence à la relation des éléments avec la structure sémantique du document, alors que les mêmes termes en CSS sont davantage liés au style visuel des éléments. Si vous faites en sorte que les éléments en ligne s'affichent en bloc, c'est très bien.

    Cependant, vous devez vous assurer que la structure du document est toujours pertinente en l'absence de CSS, par exemple en cas d'accès via une technologie d'assistance telle qu'un lecteur d'écran, ou même lors d'un examen par le puissant Googlebot.

670
NickFitz

Non, cela ne validera pas, mais oui, cela fonctionnera généralement dans les navigateurs modernes. Cela étant dit, utilisez une étendue dans votre ancre et définissez également display: block dessus, cela fonctionnera certainement partout et il sera validé!

73
Eloff

La doc du W3C n'utilise pas les concepts tels que faux et sin, mais utilise des concepts tels que fournir le moyen, peut être approprié et découragé.

En fait, dans le deuxième paragraphe de section 4 _, la spéc 4.01 détaille ses mots comme suit

Les mots clés "DOIT", "NE DOIT PAS", "REQUIS", "DOIT", "NE DOIT PAS", "NE DEVRAIT PAS", "NE DEVRAIT PAS", "RECOMMANDÉ", "PEUT" et "FACULTATIF" dans ce document. à interpréter comme décrit dans [RFC2119]. Cependant, pour des raisons de lisibilité, ces mots n'apparaissent pas dans toutes les lettres majuscules de cette spécification.

Dans cet esprit, je pense que la déclaration définitive se trouve dans 7.5.3 Eléments de niveau bloc et inline, où il est dit

En règle générale, les éléments intégrés ne peuvent contenir que des données et d’autres éléments intégrés.

La condition "généralement" semble introduire suffisamment d'ambiguïté pour indiquer que HTML 4.01 autorise les éléments en ligne à contenir des éléments de bloc. 

Certes, CSS2 a une valeur de propriété d'affichage, inline-block , qui semble convenir à l'objectif que vous décrivez. Je ne sais pas si cela a déjà été largement soutenu, mais il semble que quelqu'un ait anticipé la nécessité de ce type de comportement.

La DTD semble moins tolérante ici, mais la texte de la DTD reporte à la spécification:

La spécification HTML 4.01 inclut des informations supplémentaires contraintes syntaxiques qui ne peuvent pas être exprimées dans les DTD.

Dans un autre commentaire, vous proposez de rendre un bloc actif en l'enveloppant dans une ancre. Je ne crois pas que HTML l'interdit, et CSS le permet clairement. Donc, pour répondre à la question du titre sur le fait de savoir si cela est exact, je réponds oui. Selon les normes, c'est parfois correct.

28
Ewan Todd

Avec la spécification HTML5 ... Il est maintenant possible de placer un élément de niveau bloc dans un élément en ligne. Il est donc parfaitement approprié de placer un "div" ou un "h1" dans un élément "a".

13
Abir

Vous ne pouvez pas mettre <div> dans <a> - ce n'est pas valide (X) HTML.

Même si vous appelez display: block, vous ne pouvez toujours pas y insérer d’éléments de niveau bloc: le (X) HTML doit toujours obéir à la DTD (X) HTML (celle que vous utilisez), quelle modifie les choses.

Le navigateur l'affichera probablement comme vous le souhaitez, mais cela ne vous convient pas.

4
Greg

Il existe une DTD pour HTML 4 à http://www.w3.org/TR/REC-html40/sgml/dtd.html . Cette DTD est la forme traitable de la spécification, avec la limitation qu'une DTD gouverne XML et que HTML 4, en particulier la version "transitoire", autorise beaucoup de choses qui ne sont pas du XML "légal". Néanmoins, j’estime qu’il est presque possible de codifier l’intention des spécificateurs.

<!ELEMENT A - - (%inline;)* -(A)       -- anchor -->

<!ENTITY % inline "#PCDATA | %fontstyle; | %phrase; | %special; | %formctrl;">

<!ENTITY % fontstyle "TT | I | B | BIG | SMALL">

<!ENTITY % phrase "EM | STRONG | DFN | CODE | SAMP | KBD | VAR | CITE | ABBR | ACRONYM" >

<!ENTITY % special "A | IMG | OBJECT | BR | SCRIPT | MAP | Q | SUB | SUP | SPAN | BDO">

<!ENTITY % formctrl "INPUT | SELECT | TEXTAREA | LABEL | BUTTON">

J'interpréterais les tags listés dans cette hiérarchie comme le total des tags autorisés.

Bien que la spécification puisse dire "éléments en ligne", je suis presque certain que vous ne pouvez pas contourner l'intention en déclarant que le type d'affichage d'un élément de bloc est en ligne. Les étiquettes en ligne ont une sémantique différente, peu importe comment vous pouvez en abuser.

D'autre part, je trouve intrigant que l'inclusion de special semble permettre l'imbrication d'éléments A. Il y a probablement une formulation forte dans la spécification qui interdit cela même si sa syntaxe est correcte au niveau XML, mais je ne poursuivrai pas sur cette question car ce n'est pas le sujet de la question.

3
Carl Smotricz

Les éléments de niveau bloc tels que <div> peuvent être encapsulés par des balises <a> en HTML5. Bien qu'un <div> soit considéré comme un conteneur/wrapper pour le contenu de flux , les <a> sont considérés comme contenu de flux selon MDN . Sémantiquement, il peut être préférable de créer des éléments en ligne qui agissent comme des éléments de niveau bloc.

2
Beepye

C'est faux. Utilisez un span .

2
Jon Hadley

Si vous voulez créer un bloc <a>, pourquoi ne pas placer <a> dans le div, étant donné qu’il s’agit d’un élément block, vous obtiendrez le même effet.

1
Dave

Si vous le changez en élément de style bloc, alors non, ce n'est plus «faux», mais cela ne sera probablement pas validé. Mais cela n’a pas beaucoup de sens de faire ce que vous faites. Vous devez soit simplement conserver la balise d'ancrage en tant qu'élément de niveau bloc sans div interne, ou placer la div à l'extérieur.

1
Chris

Je pense que la plupart du temps, quand les gens posent cette question, ils ont construit un site avec seulement des divs, et maintenant l'un des divs doit être un lien.

J'ai vu quelqu'un utiliser une image vide transparente, PNG, à l'intérieur d'une balise d'ancrage pour créer un lien dans une div, et l'image avait la même taille que la div.

Assez triste en fait ... mais ça marche ...

0
user1081070

Si vous voulez éviter le problème sémantique de placer des divs dans des balises d'ancrage, placez simplement la balise d'ancre au même niveau que les div, encapsulez-les tous avec un conteneur avec la position: relative, définissez la position de votre balise d'ancrage: absolute et développez-la remplissez le récipient. De plus, si ce n'est pas à la fin du flux de contenu, assurez-vous de placer un index z pour le placer au-dessus du contenu.

Comme suggéré, j'ai ajouté un code de balisage:

<div class="div__container>
  <div class="div__one>
  </div>
  <div class="div__two">
  </div>
  <a href="#"></a>
</div>

Et le css:

.div__container {
  position: relative; 
}
.div__container a {
  position: absolute;
  top: 0;
  bottom: 0;      
  left: 0;
  right: 0;
  z-index: 999;
}
0
Eugen