Ist es jemals richtig, ein Div in einen Anker zu stecken?

530

Ich habe gehört, dass das Einfügen eines Blockelements in ein Inline-Element eine HTML-Sünde ist:

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

Aber was ist, wenn Sie den äußeren Anker wie display:blockim Stylesheet stylen? Ist es immer noch falsch? Die HTML 4.01-Spezifikation für Block- und Inline-Elemente scheint dies zu glauben:

Stylesheets bieten die Möglichkeit, das Rendern beliebiger Elemente festzulegen, einschließlich der Frage, ob ein Element als Block oder Inline gerendert wird. In einigen Fällen, z. B. bei einem Inline-Stil für Listenelemente, kann dies angemessen sein. Im Allgemeinen wird den Autoren jedoch davon abgeraten, die herkömmliche Interpretation von HTML-Elementen auf diese Weise zu überschreiben.

Hat jemand weitere Tipps zu diesem Thema?

Tom
quelle
@ DisgruntledGoat - Danke für den Link - wünschte, ich hätte das früher gesehen :-)
Tom
Das Anker- und / oder Linkelement ist eine Browser-Automatisierungssteuerung. Und deshalb hat es einen vom Browser vordefinierten Rendering und Verhalten. Um ein echtes einfaches HTML-Element zu verpacken: div innerhalb einer Spanne ist jedoch eine Sünde. Der Grund für die Tatsache, dass ein Tag kein Ebenenverhalten hinzufügt, ist eine Anforderung beim Markieren von Textteilen, ohne den Dokumentfluss zu stören, nicht weil sie als Inline-Elemente gedacht sind. Von diesem POV ist A ein Do-Nothing-Tag. Seine Existenz ist jenseits des Problems und keine Sünde, kann aber zur Hässlichkeit und / oder Mehrdeutigkeit des Codes beitragen.
Bekim Bacaj
Alle anderen, die hier in Zukunft prüfen, beachten Sie bitte, dass Ankertags zwar Elemente auf Blockebene enthalten können, diese jedoch nicht in HTML5 enthalten, jedoch kein Element auf Blockebene, das andere Ankertags enthält! Denn im Grunde können Ankertags überhaupt keine anderen Ankertags enthalten. Mehr dazu lesen Sie hier: stackoverflow.com/questions/13052598/…
aderchox

Antworten:

748

Abhängig von der HTML-Version, für die Sie sich interessieren:

  • In HTML 5 heißt es, dass das<a>Element "ganze Absätze, Listen, Tabellen usw., sogar ganze Abschnitte, umschließen darf, solange kein interaktiver Inhalt darin ist (z. B. Schaltflächen oder andere Links)".

  • HTML 4.01 gibt an, dass<a>Elemente nur Inline-Elemente enthalten dürfen. A<div>ist ein Blockelement , daher wird es möglicherweise nicht in einem angezeigt<a>.

    Natürlich sind Sie frei , um Stil eines Inline - Element , so dass es scheint so einen Block ein Block oder in der Tat Stil zu sein , dass es inline gerendert wird. Die Verwendung der Begriffe inlineund blockin HTML bezieht sich auf die Beziehung der Elemente zur semantischen Struktur des Dokuments, während dieselben Begriffe in CSS eher mit dem visuellen Stil der Elemente zusammenhängen. Wenn Sie Inline-Elemente blockweise anzeigen lassen, ist das in Ordnung.

    Sie sollten jedoch sicherstellen, dass die Struktur des Dokuments auch dann noch sinnvoll ist, wenn kein CSS vorhanden ist, z. B. wenn Sie über eine unterstützende Technologie wie einen Bildschirmleser darauf zugreifen - oder wenn dies vom mächtigen Googlebot geprüft wird.

NickFitz
quelle
4
Es gibt eine DTD für 4.01 unter w3.org/TR/REC-html40/sgml/dtd.html . A kann% inline% enthalten; % inline% ist eine Reihe verschiedener Dinge (Sie können den Links folgen), aber DIV gehört nicht dazu. Daher ist ein A mit einem DIV nicht XML-validierbar. Ich denke, dass die DTD die Absichten des Komitees ziemlich gut zum Ausdruck bringt, also würde ich sagen: Nein.
Carl Smotricz
2
@Ewan: Der erste Link in meiner Antwort führt zum entsprechenden Abschnitt von HTML 4.01.
NickFitz
62
Ich wollte gerade die Möglichkeit aufgeben, dies in einem Projekt zu tun, bis ich die letzte Zeile über HTML5 gelesen habe. Das ist gut zu wissen, danke.
Elaine Marley
16
Das Mozilla Developer Network ( developer.mozilla.org/en-US/docs/Web/HTML/Element/a ) spiegelt die Tatsache wider, dass HTML5 <a> -Elemente jetzt Flow-Inhaltselemente wie <div>, <ul> oder <table> unterstützen .
AxeEffect
12
Unter HTML5 wird ein a- Element als transparent eingestuft. Dies bedeutet, dass es NUR Flusselemente enthalten kann (read default = block ), wenn das übergeordnete Element eines Elements Flusselemente enthalten kann . Andernfalls sind nur Phrasierungselemente ( Standard lesen = Inline ) zulässig. Wenn also das a in einer Form oder einem Div vorliegt , kann es ein Div enthalten , in einem p jedoch nicht. Siehe w3.org/TR/html-markup/terminology.html
Patanjali
81

Nein, es wird nicht validiert, aber ja, es funktioniert im Allgemeinen in modernen Browsern. Davon abgesehen, verwenden Sie eine Spannweite in Ihrem Anker und setzen Sie display: blocksie ebenfalls ein, die definitiv überall funktioniert und sich bestätigt!

Eloff
quelle
7
Wenn Sie festlegen display: block, wird es technisch nicht zu einem Blockelement?
WhyNotHugo
20
@hugo Ist das technisch wichtig?
Andy Chase
5
Nun, HTML 4.01 gibt an, dass aElemente möglicherweise nur Inline-Elemente enthalten. Wenn Sie ein spanElement zu einem Blockelement machen, sollte es sich technisch gesehen nicht in einem Anker befinden.
WhyNotHugo
22
@Hugo: Es scheint, dass die Einschränkung in HTML4 semantisch und nicht präsentativ ist. Semantisch gesehen ist a auf <div>Blockebene und a <span>inline, auch wenn das zugehörige CSS des Dokuments etwas anderes vorschreibt.
Roy Tinker
Stil hinzugefügt = "display: block;" im Span-Tag und es funktionierte wie ein Zauber. Ich habe gerade mit Polsterung gespielt, um mein gewünschtes Ergebnis zu
erzielen
31

Das W3C-Dokument verwendet keine Konzepte wie falsch und sündig , aber es verwendet solche wie die Mittel , die angemessen und entmutigend sein können .

Tatsächlich listet die Spezifikation 4.01 im zweiten Absatz von Abschnitt 4 ihre Wörter wie folgt auf

Die Schlüsselwörter "MUSS", "MUSS NICHT", "ERFORDERLICH", "MUSS", "MUSS NICHT", "SOLLTE", "SOLLTE NICHT", "EMPFOHLEN", "KÖNNEN" und "OPTIONAL" in diesem Dokument lauten zu interpretieren wie in [RFC2119] beschrieben. Aus Gründen der Lesbarkeit erscheinen diese Wörter jedoch nicht in allen Großbuchstaben dieser Spezifikation.

In diesem Sinne glaube ich, dass die endgültige Aussage in 7.5.3 Block-Level- und Inline-Elementen enthalten ist , wo es heißt

Im Allgemeinen dürfen Inline-Elemente nur Daten und andere Inline-Elemente enthalten.

Die Bedingung "allgemein" scheint genug Mehrdeutigkeit einzuführen, um zu sagen, dass HTML 4.01 es Inline-Elementen erlaubt, Blockelemente zu enthalten.

Sicherlich hat CSS2 einen Anzeigeeigenschaftswert, Inline-Block , der für den von Ihnen beschriebenen Zweck geeignet zu sein scheint. Ich bin mir nicht sicher, ob es jemals allgemein unterstützt wurde, aber es scheint, dass jemand die Notwendigkeit eines solchen Verhaltens vorweggenommen hat.

Die DTD scheint hier weniger nachsichtig zu sein, aber der Text der DTD weicht von der Spezifikation ab:

Die HTML 4.01-Spezifikation enthält zusätzliche syntaktische Einschränkungen, die in den DTDs nicht ausgedrückt werden können.

In einem anderen Kommentar schlagen Sie vor, dass Sie einen Block aktivieren möchten, indem Sie ihn in einen Anker einschließen. Ich glaube nicht, dass HTML das verbietet, und CSS erlaubt es eindeutig. Um die Titelfrage zu beantworten, ob sie jemals richtig ist, sage ich ja. Nach den Maßstäben ist es manchmal richtig.

Ewan Todd
quelle
2
Sie hatten mich, bis Sie Doctype erwähnt haben.
Robert Harvey
Nicht doctype, doctype.com
Ewan Todd
Sie haben wahrscheinlich Recht - ich hätte doctype.com verwenden sollen. Opps - Ich werde versuchen, mich für das nächste Mal zu erinnern. PHP -> SO, HTML -> doctype.com
Tom
2
Meiner Meinung nach gibt es keine Option "Abstimmung zum Schließen, wie es auf doctype.com gehört" (und sollte es auch nicht geben).
Robert Harvey
7
Ich stimme Rob zu - Stack Overflow dient zur Programmierung. HTML / CSS programmiert aus meiner Sicht sicherlich.
DisgruntledGoat
13

Mit HTML5-Spezifikation ... Es ist jetzt möglich, ein Element auf Blockebene in ein Inline-Element einzufügen. Jetzt ist es vollkommen angemessen, ein 'div' oder 'h1' in ein 'a'-Element einzufügen.

Abir
quelle
1
Nur innerhalb von Flow- Elementen (Standard = Block ) oder transparenten Elementen (wie a ) mit übergeordneten Elementen , die Flow- Elemente zulassen . Zum Beispiel p erlaubt keine Strömungselemente (wie div ), aber nur Phrasierung Elemente (default = inline ), so dass ein ein in einem p keine enthalten kann div . Jedoch kann eine ein innerhalb eines div kann enthalten p s, div s oder irgendein anderes Strömungselement.
Patanjali
4

Sie können nicht <div>hineinstecken <a>- es ist kein gültiges (X) HTML.

Auch wenn Sie einen Bereich mit display: block formatieren, können Sie dennoch keine Elemente auf Blockebene einfügen: Der (X) HTML-Code muss immer noch der (X) HTML-DTD (je nachdem, welche Sie verwenden) gehorchen, unabhängig davon, wie das CSS ist verändert die Dinge.

Der Browser zeigt es wahrscheinlich so an, wie Sie es möchten, aber das macht es nicht richtig.

Greg
quelle
4

Es gibt eine DTD für HTML 4 unter http://www.w3.org/TR/REC-html40/sgml/dtd.html . Diese DTD ist die maschinenverarbeitbare Form der Spezifikation, mit der Einschränkung, dass eine DTD XML und HTML 4 regelt, insbesondere die "vorübergehende" Variante, die viele Dinge zulässt, die kein "legales" XML sind. Dennoch denke ich, dass es nahe daran liegt, die Absicht der Spezifizierer zu kodifizieren.

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

Ich würde die in dieser Hierarchie aufgelisteten Tags als die Summe der zulässigen Tags interpretieren.

Während die Spezifikation möglicherweise "Inline-Elemente" sagt, ist es ziemlich sicher, dass Sie die Absicht nicht umgehen können, indem Sie den Anzeigetyp eines Blockelements als Inline deklarieren . Inline-Tags haben unterschiedliche Semantiken, unabhängig davon, wie Sie sie missbrauchen.

Andererseits finde ich es faszinierend, dass die Einbeziehung von specialVerschachtelungselementen zuzulassen scheint A. Es gibt wahrscheinlich eine starke Formulierung in der Spezifikation, die dies nicht zulässt, selbst wenn es XML-syntaktisch korrekt ist, aber ich werde dies nicht weiter verfolgen, da es nicht das Thema der Frage ist.

Carl Smotricz
quelle
Weißt du was - - bedeutet ? Ich habe versucht, eine Erklärung zu finden, aber ich konnte keine finden.
Ewan Todd
4

Elemente auf Blockebene wie <div>können <a>in HTML5 durch Tags umbrochen werden . Obwohl a <div>als Container / Wrapper für den Flussinhalt betrachtet wird und <a>als Flussinhalt gemäß MDN betrachtet wird . Semantisch kann es besser sein, Inline-Elemente zu erstellen, die als Elemente auf Blockebene fungieren.

Beepye
quelle
1
Als ein Element ist transparent , nur dann , wenn das Mutterelement der a ermöglicht Strömung (default als Block ) -Elemente.
Patanjali
2

Wenn Sie die semantische Schwierigkeit vermeiden möchten, Divs in Ankertags zu platzieren, platzieren Sie das Ankertag einfach auf derselben Ebene wie die Divs, wickeln Sie sie alle in einen Container mit der Position: relative ein, machen Sie Ihre Ankertag-Position: absolut und erweitern Sie sie auf Füllen Sie den Behälter. Auch wenn es nicht am Ende des Inhaltsflusses ist, stellen Sie sicher, dass Sie einen Z-Index hineinwerfen, um ihn über dem Inhalt zu platzieren.

Wie vorgeschlagen habe ich einen Markup-Code hinzugefügt:

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

Und die CSS:

.div__container {
  position: relative; 
}
.div__container a {
  position: absolute;
  top: 0;
  bottom: 0;      
  left: 0;
  right: 0;
  z-index: 999;
}
Eugen
quelle
1
Ihre Antwort mag zwar richtig sein, aber es wäre hilfreich, wenn Sie sie mit einem Markup illustrieren würden.
Datashaman
1

Wenn Sie sich die Mühe machen wollen, einen <a>Block zu erstellen, warum nicht <a>in das div einfügen, da es ein Blockelement ist, das den gleichen Effekt erzielt.

Dave
quelle
36
Weil ich möchte, dass der Anker mehrere Divs einschließt.
Tom
1

Wenn Sie es in ein Element im Blockstil ändern, ist es nicht mehr 'falsch', aber es wird wahrscheinlich nicht validiert. Aber es macht nicht viel Sinn, das zu tun, was Sie tun. Sie sollten entweder nur das Ankertag als Element auf Blockebene ohne inneres Div beibehalten oder das Div nach außen setzen.

Chris
quelle
1

Es ist falsch. Verwenden Sie eine Spanne .

Jon Hadley
quelle
4
rofl das ist das gleiche wie mit einem div. Ich glaube, ich habe dies (mit divs) auf blip.tv gesehen, aber wie andere erwähnen, ist es laut spec block = block falsch, wenn div oder span oder was auch immer dasselbe ist!
James Mitch
0

Ich denke, dass die Leute die meiste Zeit, wenn sie diese Frage stellen, eine Site mit nur Divs erstellt haben, und jetzt muss einer der Divs ein Link sein.

Ich habe gesehen, dass jemand ein transparentes leeres Bild, PNG, in einem Ankertag verwendet hat, um einen Link innerhalb eines Divs herzustellen, und das Bild hatte dieselbe Größe wie das Div.

Eigentlich ziemlich traurig ... aber es funktioniert ...

user1081070
quelle
0

Sie können dies erreichen, indem Sie das Pseudoelement ":: before" hinzufügen

Reiner CSS-Trick;)

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>

Akshay kumar
quelle
-9

Nur als FYI.

Wenn Sie Ihr Div anklickbar machen möchten, können Sie jQuery / Java Script verwenden.

Definiere dein Div so:

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

Ihre jQuery würde dann folgendermaßen implementiert:

 <script type="text/javascript">

    $(document).ready(function () {

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

Dies würde auch für mehrere Divs funktionieren - gemäß Toms Kommentar in diesem Thread

lösen
quelle
17
Das ist schrecklich, es kann nicht mit einer Tastatur verwendet werden, man kann den Link beim Schweben nicht sehen. Es funktioniert fast wie ein Link, ist aber kein echter Link. Sie können auch nicht mit der mittleren Maustaste darauf klicken oder als Link mit der rechten Maustaste darauf klicken.
WhyNotHugo
1
Es hat sicherlich seine Verwendung. Sie können einen Anker in das div setzen und den div-Klick zum Standort des untergeordneten Ankers umleiten lassen. Wenn Sie den Cursor auf dem div auf den Zeiger setzen, erhalten Sie das Erscheinungsbild eines Ankers sowie eine gültige Fallback-Lösung mit nur dem Anker innerhalb des div, wenn Javascript nicht zulässig ist oder aus Gründen der Barrierefreiheit. Sie erhalten semantisch und syntaktisch korrektes HTML und müssen sich nicht mit fragwürdigen Änderungen des Anzeigestils herumschlagen.
Pedery
Wenn Sie ein Div haben, das einen Link enthält, kann ein Click-Handler das Ereignis abfangen, den Anker finden (stellen Sie sicher, dass es nur einen gibt) und diesen dann verwenden. Zugänglich über das normale Ankertag. Dies würde es ermöglichen, einen Eimer mit Zahlen mit Bild und Beschriftung und einen Link "Lesen Sie mehr" zu haben - zum Beispiel. Gedanken?
Julix