Mettere un div in un'ancora è mai corretto?


530

Ho sentito che mettere un elemento a blocchi all'interno di un elemento inline è un peccato 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>

Ma che dire se si disegna l'ancora esterna come display:blocknel foglio di stile? È ancora sbagliato? Le specifiche HTML 4.01 su elementi a livello di blocco e inline sembrano pensarlo:

I fogli di stile forniscono i mezzi per specificare il rendering di elementi arbitrari, incluso se un elemento viene reso come blocco o in linea. In alcuni casi, come uno stile in linea per gli elementi dell'elenco, questo può essere appropriato, ma in generale gli autori sono scoraggiati dal scavalcare l'interpretazione convenzionale degli elementi HTML in questo modo.

Qualcuno ha ulteriori suggerimenti su questo problema?



@DisgruntledGoat - Grazie per il link - vorrei averlo visto prima :-)
Tom

L'elemento anchor e \ o link è un controllo di automazione del browser. E quindi ha un rendering e un comportamento predefiniti del browser. Avvolgere un vero elemento HTML semplice: div all'interno di un intervallo è tuttavia un peccato. Il motivo alla base del fatto che un tag non aggiunge alcun comportamento a livello è un requisito per contrassegnare parti di testo senza disturbare il flusso del documento, non perché sono pensati per essere elementi incorporati. Da quel punto di vista, A, è un tag non fare nulla. La sua esistenza è al di là del problema e non è un peccato, ma può contribuire alla bruttezza e all'ambiguità del codice.
Bekim Bacaj,

Tutti gli altri che controllano qui in futuro, tieni presente che mentre i tag anchor sono in grado di contenere elementi a livello di blocco non li trovano in HTML5, non possono contenere un elemento a livello di blocco che contiene altri tag anchor! Perché sostanzialmente, i tag anchor non possono contenere al loro interno altri tag anchor. Si può leggere di più su quello qui: stackoverflow.com/questions/13052598/...
aderchox

Risposte:


748

A seconda della versione di HTML a cui ti stai rivolgendo:

  • HTML 5 afferma che l'<a>elemento "può essere racchiuso in interi paragrafi, elenchi, tabelle e così via, anche in intere sezioni, purché non vi sia contenuto interattivo (ad esempio pulsanti o altri collegamenti)".

  • HTML 4.01 specifica che gli<a>elementi possono contenere solo elementi incorporati . A<div>è un elemento a blocchi , quindi potrebbe non apparire all'interno di un<a> .

    Ovviamente sei libero di modellare un elemento inline in modo tale che appaia come un blocco, o addirittura in stile un blocco in modo che sia reso in linea. L'uso dei termini inlineeblock in HTML si riferisce alla relazione degli elementi con la struttura semantica del documento, mentre gli stessi termini in CSS sono più legati allo stile visivo degli elementi. Se fai visualizzare gli elementi in linea in modo a blocchi, va bene.

    Tuttavia, dovresti assicurarti che la struttura del documento abbia ancora senso quando i CSS non sono presenti, ad esempio quando si accede tramite una tecnologia di supporto come uno screen reader - o in effetti quando viene esaminato dal potente Googlebot.


4
C'è un DTD per 4.01 su w3.org/TR/REC-html40/sgml/dtd.html . A può contenere% inline%; % inline% è un mucchio di cose diverse (puoi seguire i link) ma DIV non è tra questi. Pertanto, una A con un DIV all'interno non è validabile in XML. Credo che DTD esprime le intenzioni del comitato abbastanza bene, quindi direi: No.
Carl Smotricz

2
@Ewan: il primo link nella mia risposta è alla sezione pertinente di HTML 4.01.
NickFitz,

62
Stavo per abbandonare la possibilità di farlo in un progetto fino a quando non ho letto l'ultima riga su HTML5, va bene saperlo, grazie.
Elaine Marley

16
La rete di sviluppatori Mozilla ( developer.mozilla.org/en-US/docs/Web/HTML/Element/a ) riflette il fatto che gli elementi <a> HTML5 ora supportano elementi di contenuto di flusso come <div>, <ul> o <table> .
AxeEffect,

12
Sotto HTML5, un un elemento è classificato come trasparente , che significa che può contenere flusso elementi (lettura default = blocco ) solo se il genitore della un elemento può contenere fluire elementi. Altrimenti, sono ammessi solo elementi di fraseggio (leggi default = inline ). Pertanto, se a è in una forma o div , può contenere un div , ma all'interno di una p , non può. Vedi w3.org/TR/html-markup/terminology.html
Patanjali

81

No, non verrà convalidato, ma sì, generalmente funzionerà nei browser moderni. Detto questo, usa uno span all'interno della tua ancora e posizionalo anche display: blocksu esso, che sicuramente funzionerà ovunque e si convaliderà!


7
Se imposti display: block, tecnicamente, non diventa un elemento a blocchi?
WhyNotHugo

20
@hugo È tecnicamente importante?
Andy Chase,

5
Bene, HTML 4.01 specifica che gli aelementi possono contenere solo elementi incorporati. Se trasformi un spanelemento in un elemento a blocchi, tecnicamente non dovrebbe trovarsi all'interno di un'ancora.
WhyNotHugo,

22
@Hugo: sembra che la restrizione in HTML4 sia semantica, non di presentazione. Semanticamente, a <div>è a livello di blocco e a <span>è in linea, anche se il CSS di accompagnamento del documento impone diversamente.
Roy Tinker,

Aggiunto style = "display: block;" nel tag span e ha funzionato come un fascino. Ho appena giocato con il padding per ottenere il risultato desiderato
Harif87

31

Il documento W3C non usa concetti come sbagliato e peccato , ma usa quelli come fornire i mezzi , può essere appropriato e scoraggiato .

In realtà, nel secondo paragrafo della sezione 4 , la specifica 4.01 elenca le sue parole come segue

Le parole chiave "DEVE", "NON DEVE", "RICHIESTO", "DEVONO", "NON DEVONO", "DOVREBBE", "NON DOVREBBE", "CONSIGLIATO", "MAGGIO" e "OPZIONALE" in questo documento sono da interpretare come descritto in [RFC2119]. Tuttavia, per motivi di leggibilità, queste parole non compaiono in tutte le lettere maiuscole in questa specifica.

Con questo in mente, credo che l'affermazione definitiva sia in 7.5.3 Elementi a livello di blocco e in linea , dove dice

Generalmente, gli elementi in linea possono contenere solo dati e altri elementi in linea.

La condizione "generalmente" sembra introdurre abbastanza ambiguità per dire che HTML 4.01 consente agli elementi inline di contenere elementi a blocchi.

Certamente, CSS2 ha un valore di proprietà di visualizzazione, blocco in linea , che sembra adatto allo scopo che descrivi. Non sono sicuro che sia mai stato ampiamente supportato, ma sembra che qualcuno abbia anticipato la necessità di quel tipo di comportamento.

Il DTD sembra essere meno indulgente qui, ma il testo del DTD differisce dalle specifiche:

La specifica HTML 4.01 include ulteriori vincoli sintattici che non possono essere espressi nei DTD.

In un altro commento, suggerisci di voler rendere attivo un blocco avvolgendolo in un'ancora. Non credo che HTML lo proibisca e CSS chiaramente lo consente. Quindi, per rispondere alla domanda sul titolo se è mai corretta, dico di sì. Per gli standard, a volte è corretto.


2
Mi hai avuto fino a quando non hai menzionato doctype.
Robert Harvey,

Non doctype, doctype.com
Ewan Todd,

Probabilmente hai ragione: avrei dovuto usare doctype.com. Opps - Proverò a ricordare per la prossima volta. PHP -> SO, HTML -> doctype.com
Tom

2
La mia opinione è che non esiste un'opzione "vota per chiudere come appartiene a doctype.com" (né dovrebbe esserci).
Robert Harvey,

7
Sono d'accordo con Rob - StackTranslate.it è per la programmazione. HTML / CSS è certamente una programmazione a mio avviso.
DisgruntledGoat

13

Con la specifica HTML5 ... Ora è possibile inserire un elemento a livello di blocco all'interno di un elemento inline. Quindi ora è perfettamente appropriato inserire un 'div' o 'h1' all'interno di un elemento 'a'.


1
Solo all'interno di elementi di flusso (default = blocco ) o elementi trasparenti (come a ) con genitori che consentono elementi di flusso . Ad esempio, p non consente gli elementi di flusso (come div ), ma solo gli elementi di frase (default = inline ), quindi una a all'interno di una p non può contenere un div . Tuttavia, un a dentro un div può contenere p s, div s o qualsiasi altro flusso elemento di .
Patanjali

4

Non puoi metterlo <div>dentro <a>- non è HTML (X) valido.

Anche se hai uno stile con display: block non puoi ancora inserire elementi a livello di blocco al suo interno: l'HTML (X) deve ancora obbedire al DTD (X) HTML (qualunque sia quello che usi), non importa come il CSS altera le cose.

Il browser probabilmente lo visualizzerà come vuoi, ma ciò non lo rende giusto.


4

C'è un DTD per HTML 4 su http://www.w3.org/TR/REC-html40/sgml/dtd.html . Questo DTD è la forma processabile dalla macchina della specifica, con la limitazione che un DTD governa XML e HTML 4, in particolare il sapore "transitorio", consente molte cose che non sono XML "legali". Tuttavia, ritengo che si avvicini alla codifica dell'intento degli specificatori.

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

Interpreterei i tag elencati in questa gerarchia come totale dei tag consentiti.

Mentre la specifica può dire "elementi in linea", sono abbastanza sicuro che non si intende aggirare l'intento dichiarando in linea il tipo di visualizzazione di un elemento di blocco. I tag incorporati hanno una semantica diversa, indipendentemente da come potresti abusarne.

D'altra parte, trovo intrigante che l'inclusione di specialsembra consentire Aelementi di nidificazione . Probabilmente ci sono alcune parole forti nelle specifiche che non lo consentono anche se sono sintatticamente XML corrette ma non lo perseguirò ulteriormente poiché non è l'argomento della domanda.


Sai cosa - - significa. Ho provato a trovare una spiegazione ma non sono riuscito a trovarne una.
Ewan Todd,

4

Gli elementi a livello di blocco come <div>possono essere racchiusi in <a>tag in HTML5. Sebbene a <div>sia considerato un contenitore / wrapper per il contenuto di flusso e <a>'considerato contenuto di flusso secondo MDN . Semanticamente potrebbe essere meglio creare elementi in linea che fungono da elementi a livello di blocco.


1
Come un elementi sono trasparenti , solo se l'elemento principale del una consente flusso (default block ) elementi.
Patanjali,

2

Se vuoi evitare il problema semantico di posizionare i div all'interno dei tag di ancoraggio, posiziona il tag di ancoraggio allo stesso livello dei div, avvolgili tutti con un contenitore con posizione: relativo, rendi la posizione del tuo tag di ancoraggio: assoluta ed espandi a riempire il contenitore. Inoltre, se non si trova alla fine del flusso di contenuti, assicurati di lanciare un indice z per posizionarlo sopra il contenuto.

Come suggerito, ho aggiunto un codice di markup:

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

E il css:

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

1
Sebbene la tua risposta possa essere corretta, sarebbe utile se la illustrassi con il markup.
datashaman,

1

Se stai andando allo sforzo di creare un <a>blocco, perché non mettere <a>dentro il div, essendo un elemento a blocchi ti darà lo stesso effetto.


36
Perché potrei volere che l'ancora racchiuda più div.
Tom,

1

Se lo cambi in un elemento in stile blocco, allora no, non è più "sbagliato", ma probabilmente non verrà convalidato. Ma non ha molto senso fare quello che stai facendo. Dovresti semplicemente mantenere il tag di ancoraggio come elemento a livello di blocco senza div interno, oppure posizionare il div all'esterno.


1

È sbagliato. Usa una campata .


4
rofl è la stessa cosa che usare un div. penso di aver visto questo fatto (con div) su blip.tv ma come altri menzionano il suo errore secondo spec block = block se div o span o qualunque cosa sia la stessa!
James Mitch,

0

Penso che la maggior parte delle volte quando le persone fanno questa domanda, hanno creato un sito con solo div, e ora uno dei div deve essere un link.

Ho visto qualcuno usare un'immagine vuota trasparente, PNG, all'interno di un tag di ancoraggio solo per creare un collegamento all'interno di un div e l'immagine aveva le stesse dimensioni del div.

Abbastanza triste in realtà ... ma funziona ...


0

puoi ottenere ciò aggiungendo lo pseudo-elemento ":: before"

Trucco 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>


-9

Proprio come un FYI.

Se il tuo obiettivo è rendere selezionabile il tuo div, puoi usare jQuery / Java Script.

Definisci il tuo div in questo modo:

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

Il tuo jQuery verrebbe quindi implementato in questo modo:

 <script type="text/javascript">

    $(document).ready(function () {

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

Funzionerebbe anche per più div - come da commento di Tom in questa discussione


17
Questo è orribile, non può essere utilizzato con una tastiera, non è possibile vedere il collegamento al passaggio del mouse. Funziona quasi come un collegamento, ma non è un vero collegamento. Non è nemmeno possibile fare clic con il tasto centrale o fare clic con il tasto destro su di esso come collegamento.
WhyNotHugo

1
Certamente ha i suoi usi. È possibile inserire un'ancora all'interno del div e fare in modo che il reindirizzamento div-clic si posizioni sulla posizione dell'ancora figlio. Impostando il cursore sul div come puntatore, si ha quindi l'aspetto di un'ancora, oltre a una valida soluzione di fallback con solo l'ancora all'interno del div se javascript non è consentito o per motivi di accessibilità. Ottieni html semanticamente e sintatticamente corretto e non devi armeggiare con alterazioni discutibili dello stile di visualizzazione.
Pedery,

Se hai un div che contiene un link, potresti fare in modo che un gestore di clic catturi l'evento, trova l'ancoraggio (assicurati che ce ne sia solo uno) e quindi utilizzalo. Accessibile tramite la normale etichetta di ancoraggio. Ciò consentirebbe di avere un secchio di figure con immagine e didascalia e link "leggi altro", ad esempio. Pensieri?
Julix,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.