¿Es correcto poner un div dentro de un ancla?

530

He oído que poner un elemento de bloque dentro de un elemento en línea es un pecado 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>

Pero, ¿qué pasa si da estilo al ancla exterior como display:blocken la hoja de estilo? ¿Todavía está mal? La especificación HTML 4.01 en elementos de nivel de bloque e inline parece pensar que sí:

Las hojas de estilo proporcionan los medios para especificar la representación de elementos arbitrarios, incluido si un elemento se representa como bloque o en línea. En algunos casos, como un estilo en línea para elementos de lista, esto puede ser apropiado, pero en general, se desaconseja a los autores anular la interpretación convencional de elementos HTML de esta manera.

¿Alguien tiene más consejos sobre este tema?

Tom
fuente
3
Consulte también: stackoverflow.com/questions/1091739/html-div-in-link-problem .
DisgruntledGoat
@DisgruntledGoat - Gracias por el enlace - desearía haberlo visto antes :-)
Tom
El elemento ancla y \ o enlace es un control de automatización del navegador. Y por lo tanto, tiene un renderizado y comportamiento predefinidos. Para envolver un elemento html simple genuino: div dentro de un lapso sin embargo es un pecado. La razón detrás del hecho de que una etiqueta no agrega ningún comportamiento de nivel es un requisito para marcar partes del texto sin alterar el flujo del documento, no porque estén destinados a ser elementos en línea. Desde ese punto de vista, A, hay una etiqueta de no hacer nada. Su existencia está más allá del problema y no es un pecado, pero puede contribuir a la fealdad y / o ambigüedad del código.
Bekim Bacaj
¡Todos los demás que verifiquen aquí en el futuro, tengan en cuenta que si bien las etiquetas de anclaje PUEDEN contener elementos de nivel de bloque no los contienen en HTML5, no pueden contener un elemento de nivel de bloque que contenga otras etiquetas de anclaje! Porque básicamente, las etiquetas de anclaje no pueden tener otras etiquetas de anclaje en su interior. Puede leer más sobre eso aquí: stackoverflow.com/questions/13052598/…
aderchox

Respuestas:

748

Dependiendo de la versión de HTML que esté atendiendo:

  • HTML 5 establece que el<a>elemento "puede estar envuelto alrededor de párrafos enteros, listas, tablas, etc., incluso secciones completas, siempre que no haya contenido interactivo (por ejemplo, botones u otros enlaces)".

  • HTML 4.01 especifica que los<a>elementos solo pueden contener elementos en línea . A<div>es un elemento de bloque , por lo que puede no aparecer dentro de un<a>.

    Por supuesto, tiene la libertad de diseñar un elemento en línea de modo que parezca un bloque, o incluso diseñar un bloque para que se procese en línea. El uso de los términos inliney blocken HTML se refiere a la relación de los elementos con la estructura semántica del documento, mientras que los mismos términos en CSS están más relacionados con el estilo visual de los elementos. Si hace que los elementos en línea se muestren en bloque, está bien.

    Sin embargo, debe asegurarse de que la estructura del documento todavía tenga sentido cuando CSS no está presente, por ejemplo, cuando se accede a través de una tecnología de asistencia como un lector de pantalla, o de hecho cuando es examinado por el poderoso Googlebot.

NickFitz
fuente
44
Hay un DTD para 4.01 en w3.org/TR/REC-html40/sgml/dtd.html . A puede contener% en línea%; % inline% es un montón de cosas diferentes (puedes seguir los enlaces) pero DIV no está entre ellas. Por lo tanto, una A con un DIV dentro no es validable por XML. Creo que DTD expresa bastante bien las intenciones del comité, por lo que diría: No.
Carl Smotricz el
2
@Ewan: el primer enlace en mi respuesta es a la sección relevante de HTML 4.01.
NickFitz
6262
Estaba a punto de deshacerme de la posibilidad de hacer esto en un proyecto hasta que leí la última línea sobre HTML5, es bueno saberlo, gracias.
Elaine Marley
16
La red de desarrolladores de Mozilla ( developer.mozilla.org/en-US/docs/Web/HTML/Element/a ) refleja el hecho de que los elementos HTML5 <a> ahora admiten elementos de contenido de flujo como <div>, <ul> o <table> .
AxeEffect
12
Bajo HTML5, una un elemento se clasifica como transparente , lo que significa que puede contener de flujo de elementos (de lectura por defecto = bloque ) solamente si el padre de la un elemento puede contener fluya elementos. De lo contrario, solo se permiten elementos de fraseo (lectura predeterminada = en línea ). Por lo tanto, si a está en una forma o div , puede contener un div , pero dentro de una p , no puede. Ver w3.org/TR/html-markup/terminology.html
Patanjali
81

No, no validará, pero sí, generalmente funcionará en los navegadores modernos. Dicho esto, use un espacio dentro de su ancla y configúrelo display: blocktambién, eso definitivamente funcionará en todas partes, ¡y se validará!

Eloff
fuente
77
Si configura display: block, ¿no se convierte, técnicamente, en un elemento de bloque?
WhyNotHugo
20
@hugo ¿Importa técnicamente?
Andy Chase
55
Bueno, HTML 4.01 especifica que los aelementos solo pueden contener elementos en línea. Si convierte un spanelemento en un elemento de bloque, técnicamente no debería estar dentro de un ancla.
WhyNotHugo
22
@Hugo: Parece que la restricción en HTML4 es semántica, no presentacional. Semánticamente, a <div>es de nivel de bloque y a <span>está en línea, incluso si el CSS que acompaña al documento dicta lo contrario.
Roy Tinker
Estilo agregado = "display: block;" en la etiqueta span y funcionó a las mil maravillas. Acabo de jugar con relleno para obtener el resultado deseado
Harif87
31

El documento W3C no usa conceptos como mal y pecado , pero sí usa aquellos como proporcionar los medios , puede ser apropiado y desalentado .

En realidad, en el segundo párrafo de la sección 4 , la especificación 4.01 detalla sus palabras de la siguiente manera

Las palabras clave "DEBE", "NO DEBE", "REQUERIDO", "DEBE", "NO DEBE", "DEBE", "NO DEBE", "RECOMENDARSE", "PUEDE" y "OPCIONAL" en este documento. para ser interpretado como se describe en [RFC2119]. Sin embargo, para facilitar la lectura, estas palabras no aparecen en mayúsculas en esta especificación.

Con eso en mente, creo que la declaración definitiva está en 7.5.3 Elementos de nivel de bloque e inline , donde dice

En general, los elementos en línea pueden contener solo datos y otros elementos en línea.

La condición "en general" parece introducir suficiente ambigüedad para decir que HTML 4.01 permite que los elementos en línea contengan elementos de bloque.

Ciertamente, CSS2 tiene un valor de propiedad de visualización, bloque en línea , que parece ser adecuado para el propósito que usted describe. No estoy seguro de si alguna vez fue ampliamente compatible, pero parece que alguien anticipó la necesidad de ese tipo de comportamiento.

El DTD parece ser menos indulgente aquí, pero el texto de la DTD difiere de la especificación:

La especificación HTML 4.01 incluye restricciones sintácticas adicionales que no se pueden expresar dentro de los DTD.

En otro comentario, sugiere que desee activar un bloque envolviéndolo en un ancla. No creo que HTML lo prohíba, y CSS claramente lo permite. Entonces, para responder la pregunta del título sobre si alguna vez es correcto, digo que sí. Según los estándares, a veces es correcto.

Ewan Todd
fuente
2
Me tuviste hasta que mencionaste doctype.
Robert Harvey
No doctype, doctype.com
Ewan Todd
Probablemente tengas razón: debería haber usado doctype.com. Opps: intentaré recordar la próxima vez. PHP -> SO, HTML -> doctype.com
Tom
2
Mi opinión es que no hay una opción "votar para cerrar como pertenece a doctype.com" (ni debería haberla).
Robert Harvey
77
Estoy de acuerdo con Rob: Stack Overflow es para programación. HTML / CSS ciertamente está programando desde mi punto de vista.
DisgruntledGoat
13

Con la especificación HTML5 ... Ahora es posible poner un elemento a nivel de bloque dentro de un elemento en línea. Así que ahora es perfectamente apropiado poner un 'div' o 'h1' dentro de un elemento 'a'.

Abir
fuente
1
Solo elementos de flujo interno (predeterminado = bloque ) o elementos transparentes (como a ) con elementos primarios que permiten elementos de flujo . Por ejemplo, p no permite elementos de flujo (como div ), sino solo elementos de fraseo (por defecto = en línea ), por lo que un a dentro de p no puede contener un div . Sin embargo, un a dentro de un div puede contener p s, div s o cualquier otro elemento de flujo .
Patanjali
4

No se puede poner <div>dentro <a>: no es HTML (X) válido.

Aunque diseñe un lapso con pantalla: bloque, aún no puede colocar elementos de nivel de bloque dentro de él: el (X) HTML todavía tiene que obedecer al (X) HTML DTD (cualquiera que use), sin importar cómo sea el CSS Altera las cosas.

El navegador probablemente lo mostrará como desee, pero eso no lo hace correcto.

Greg
fuente
4

Hay un DTD para HTML 4 en http://www.w3.org/TR/REC-html40/sgml/dtd.html . Este DTD es la forma de especificación procesable por máquina, con la limitación de que un DTD gobierna XML y HTML 4, especialmente el sabor "transitorio", permite muchas cosas que no son XML "legales". Aún así, considero que se trata de codificar la intención de los especificadores.

<!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">

Interpretaría que las etiquetas enumeradas en esta jerarquía son el total de etiquetas permitidas.

Si bien la especificación puede decir "elementos en línea", estoy bastante seguro de que no tiene la intención de que pueda evitar la intención declarando el tipo de visualización de un elemento de bloque está en línea. Las etiquetas en línea tienen una semántica diferente, independientemente de cómo pueda abusar de ellas.

Por otro lado, me parece intrigante que la inclusión de specialparece permitir Aelementos de anidación . Probablemente hay una redacción fuerte en la especificación que no lo permite, incluso si es XML sintácticamente correcto, pero no lo seguiré más allá, ya que no es el tema de la pregunta.

Carl Smotricz
fuente
¿Sabes lo que - - significa? Traté de encontrar una explicación pero no pude encontrarla.
Ewan Todd
4

Los elementos de nivel de bloque como <div>pueden ser envueltos por <a>etiquetas en HTML5. Aunque a <div>se considera un contenedor / envoltorio para el contenido de flujo y <a>se considera contenido de flujo de acuerdo con MDN . Semánticamente, puede ser mejor crear elementos en línea que actúen como elementos de nivel de bloque.

Beepye
fuente
1
Como un elementos son transparentes , sólo si el elemento de matriz de la una permite el flujo (por defecto como de bloque ) elementos.
Patanjali
2

Si desea evitar el problema semántico de colocar divs dentro de las etiquetas de anclaje, simplemente coloque la etiqueta de anclaje en el mismo nivel que los divs, envuélvalos todos con un contenedor con posición: relativo, haga su posición de etiqueta de anclaje: absoluta y amplíelo a llenar el recipiente Además, si no está al final del flujo de contenido, asegúrese de colocar un índice z allí para colocarlo sobre el contenido.

Como sugerí, he agregado un código de marcado:

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

Y el css:

.div__container {
  position: relative; 
}
.div__container a {
  position: absolute;
  top: 0;
  bottom: 0;      
  left: 0;
  right: 0;
  z-index: 999;
}
Eugen
fuente
1
Si bien su respuesta puede ser correcta, sería útil que la ilustrara con un marcado.
datashaman
1

Si vas a hacer el esfuerzo de hacer un <a>bloque, ¿por qué no ponerlo <a>dentro del div, siendo un elemento de bloque te dará el mismo efecto?

Dave
fuente
36
Porque podría querer que el ancla encierre múltiples divs.
Tom
1

Si lo cambia a un elemento de estilo de bloque, entonces no, ya no es 'incorrecto', pero probablemente no se validará. Pero no tiene mucho sentido hacer lo que estás haciendo. Debe mantener la etiqueta de anclaje como un elemento de nivel de bloque sin div interno, o colocar el div en el exterior.

Chris
fuente
1

Está incorrecto. Usa un lapso .

Jon Hadley
fuente
44
rofl eso es lo mismo que usar un div. ¡Creo que he visto esto hecho (con divs) en blip.tv pero como otros mencionan que está mal de acuerdo con spec block = block si div o span o lo que sea lo mismo!
James Mitch
0

Creo que la mayoría de las veces cuando las personas hacen esta pregunta, han creado un sitio con solo divs, y ahora uno de los div debe ser un enlace.

Vi a alguien usar una imagen vacía transparente, PNG, dentro de una etiqueta de anclaje solo para hacer un enlace dentro de un div, y la imagen tenía el mismo tamaño que el div.

Bastante triste en realidad ... pero funciona ...

usuario1081070
fuente
0

puede lograr esto agregando ":: before" Pseudo-elemento

Truco CSS puro;)

a:before{
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 1;
  pointer-events: auto;
  content: "";
  background-color: rgba(0,0,0,0);
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" rel="stylesheet"/>
<div class="card" style="width: 18rem;">
  <img src="https://via.placeholder.com/250" class="card-img-top" alt="...">
  <div class="card-body">
    <h5 class="card-title">Card with stretched link</h5>
    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
    <a href="#" class="btn btn-primary stretched-link">Go somewhere</a>
  </div>
</div>

AkshayKumar
fuente
-9

Solo como un FYI.

Si su objetivo es hacer que su div sea clicable, puede usar jQuery / Java Script.

Define tu div así:

<div class="clickableDiv" style="cursor:pointer">
  This is my div. Try clicking it!
</div>

Su jQuery se implementaría así:

 <script type="text/javascript">

    $(document).ready(function () {

        $("div.clickableDiv").click(function () {
            alert("Peekaboo"); 
        });
    });
</script>

Esto también funcionaría para múltiples divs, según el comentario de Tom en este hilo

resolviendo
fuente
17
Esto es horrible, no se puede usar con un teclado, no se puede ver el enlace al pasar el ratón. Funciona casi como un enlace, pero no es un enlace real. Tampoco puede hacer clic con el botón central o hacer clic con el botón derecho en él como un enlace.
WhyNotHugo
1
Ciertamente tiene sus usos. Puede colocar un ancla dentro del div y hacer que el clic div se redirija a la ubicación del ancla secundaria. Al configurar el cursor en el div para que apunte, tiene la apariencia de un ancla, además de una solución de respaldo válida con solo el ancla dentro del div si javascript no está permitido o por razones de accesibilidad. Obtiene html semánticamente y sintácticamente correcto, y no tiene que jugar con alteraciones cuestionables del estilo de visualización.
Pedery
Si tiene un div que contiene un enlace, puede hacer que un controlador de clics capture el evento, busque el ancla (asegúrese de que solo haya uno) y luego úselo. Accesible a través de la etiqueta de anclaje normal. Esto permitiría tener un cubo de figuras con imagen y leyenda y un enlace "leer más", por ejemplo. Pensamientos?
Julix