Правильно ли ставить div внутри якоря?

530

Я слышал, что помещение элемента блока во встроенный элемент - это грех 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>

Но что делать, если вы стилизуете внешний якорь, как display:blockв таблице стилей? Это все еще не так? Спецификация HTML 4.01 для блочных и встроенных элементов выглядит так:

Таблицы стилей предоставляют средства для задания рендеринга произвольных элементов, включая отображение элемента как блочного или встроенного. В некоторых случаях, таких как встроенный стиль для элементов списка, это может быть уместным, но, вообще говоря, авторам не рекомендуется переопределять традиционную интерпретацию элементов HTML таким способом.

У кого-нибудь есть еще советы по этому вопросу?

Том
источник
3
Смотрите также: stackoverflow.com/questions/1091739/html-div-in-link-problem .
DisgruntledGoat
@DisgruntledGoat - Спасибо за ссылку - жаль, что я видел это раньше :-)
Том
Элемент привязки и \ или ссылки является элементом управления браузером. И поэтому он имеет предопределенный рендеринг и поведение браузера. Чтобы обернуть настоящий простой HTML-элемент: div внутри span, однако, является грехом. Причиной того факта, что тег не добавляет никакого уровня поведения, является требование разметки частей текста без нарушения потока документов, а не потому, что они должны быть встроенными элементами. От этого pov, A, это тег ничего не делать. Его существование вне вопроса и не грех, но может способствовать уродливости кода и / или двусмысленности.
Беким Бакай
Всем остальным, кто проверяет здесь в будущем, обратите внимание, что хотя теги привязки МОГУТ содержать элементы уровня блока внутри них в HTML5, они не могут содержать элемент уровня блока, который содержит другие теги привязки! Потому что в основном теги привязки не могут иметь внутри себя другие теги привязки. Вы можете прочитать больше об этом здесь: stackoverflow.com/questions/13052598/…
aderchox

Ответы:

748

В зависимости от версии HTML, к которой вы обращаетесь:

  • HTML 5 гласит, что<a>элемент «может быть обернут вокруг целых абзацев, списков, таблиц и т. Д., Даже целых разделов, если в них нет интерактивного содержимого (например, кнопок или других ссылок)».

  • HTML 4.01 указывает, что<a>элементы могут содержать только встроенные элементы . A<div>является блочным элементом , поэтому он не может появляться внутри<a>.

    Конечно, вы можете стилизовать встроенный элемент таким образом, чтобы он казался блоком, или даже стилизовать блок так, чтобы он отображался как встроенный. Использование терминов inlineи blockв HTML относится к связи элементов с семантической структурой документа, тогда как те же термины в CSS больше связаны с визуальным оформлением элементов. Если вы заставляете встроенные элементы отображаться блочно, это нормально.

    Однако вы должны убедиться, что структура документа по-прежнему имеет смысл, когда отсутствует CSS, например, когда к нему обращаются с помощью вспомогательной технологии, такой как программа чтения с экрана, или даже когда его проверяет могущественный робот Google.

NickFitz
источник
4
Есть DTD для 4.01 на w3.org/TR/REC-html40/sgml/dtd.html . A может содержать% inline%; % inline% - это куча разных вещей (вы можете перейти по ссылкам), но DIV среди них нет. Таким образом, A с DIV внутри не является XML-проверяемым. Я думаю, что DTD достаточно хорошо выражает намерения комитета, поэтому я бы сказал: Нет.
Carl Smotricz
2
@Ewan: первая ссылка в моем ответе - на соответствующий раздел HTML 4.01.
NickFitz
62
Я собирался отказаться от возможности сделать это в проекте, пока не прочитал последнюю строчку о HTML5, это приятно знать, спасибо.
Элейн Марли,
16
Сеть разработчиков Mozilla ( developer.mozilla.org/en-US/docs/Web/HTML/Element/a ) отражает тот факт, что элементы <a> HTML5 теперь поддерживают элементы содержимого потока, такие как <div>, <ul> или <table> ,
AxeEffect
12
В HTML5 элемент a классифицируется как прозрачный , что означает, что он может содержать элементы потока (read default = block ), ТОЛЬКО если родительский элемент a может содержать элементы потока . В противном случае разрешены только элементы фразы (read default = inline ). Таким образом, если a находится в форме или div , он может содержать div , но внутри p он не может. См. W3.org/TR/html-markup/terminology.html
Патанджали
81

Нет, он не будет проверен, но да, как правило, он будет работать в современных браузерах. Тем не менее, используйте промежуток внутри вашего якоря, и установите display: blockна него, это, безусловно, будет работать везде, и это будет проверять!

Eloff
источник
7
Если вы установите display: block, разве это, технически, не станет блочным элементом?
WhyNotHugo
20
@ Hugo Это технически важно?
Энди Чейз
5
HTML 4.01 указывает, что aэлементы могут содержать только встроенные элементы. Если вы сделаете spanэлемент блок-элементом, он не должен быть технически внутри якоря.
WhyNotHugo
22
@Hugo: кажется, что ограничение в HTML4 семантическое, а не презентационное. Семантически, a <div>является блочным уровнем, а a <span>является встроенным, даже если сопровождающий CSS документ диктует иное.
Рой Тинкер
Добавлен стиль = "display: block;" в теге span, и это работает как шарм. Просто играл с отступами, чтобы получить желаемый результат
Harif87
31

В документе W3C не используются такие понятия, как ложь и грех , но он использует такие понятия, как средства , которые могут быть уместными и обескураженными .

На самом деле, во втором абзаце раздела 4 спецификация 4.01 содержит следующие слова:

Ключевые слова «ДОЛЖЕН», «НЕ ДОЛЖЕН», «ТРЕБУЕТСЯ», «ДОЛЖЕН», «НЕ ДОЛЖЕН», «СЛЕДУЕТ», «НЕ СЛЕДУЕТ», «РЕКОМЕНДУЕТСЯ», «МОЖЕТ» и «ДОПОЛНИТЕЛЬНО» в этом документе интерпретироваться как описано в [RFC2119]. Однако для удобства чтения эти слова не отображаются заглавными буквами в данной спецификации.

Имея это в виду, я считаю, что окончательное утверждение содержится в 7.5.3 Блочных и встроенных элементах , где говорится

Как правило, встроенные элементы могут содержать только данные и другие встроенные элементы.

Условие «в целом», по-видимому, вводит достаточно двусмысленности, чтобы сказать, что HTML 4.01 позволяет встроенным элементам содержать блочные элементы.

Конечно, CSS2 имеет значение свойства display, inline-block , которое кажется подходящим для цели, которую вы описываете. Я не уверен, что это когда-либо получило широкую поддержку, но кажется, что кто-то предвидел необходимость такого поведения.

DTD, кажется, здесь менее прощающий, но текст DTD подчиняется спецификации:

Спецификация HTML 4.01 включает в себя дополнительные синтаксические ограничения, которые не могут быть выражены в DTD.

В другом комментарии вы предлагаете сделать блок активным, поместив его в якорь. Я не верю, что HTML запрещает это, а CSS явно позволяет это. Поэтому, чтобы ответить на заглавный вопрос о том, является ли он правильным, я отвечаю да По меркам это иногда правильно.

Эван Тодд
источник
2
Я был с тобой, пока не упомянул проктип.
Роберт Харви
Не doctype, doctype.com
Эван Тодд
Вы, вероятно, правы - я должен был использовать doctype.com. Оппс - я постараюсь вспомнить в следующий раз. PHP -> ТАК, HTML -> doctype.com
Том
2
Я считаю, что нет опции «голосовать за закрытие, как принадлежит на doctype.com» (и не должно быть).
Роберт Харви
7
Я согласен с Робом - Stack Overflow для программирования. HTML / CSS, безусловно, программирует, на мой взгляд.
DisgruntledGoat
13

Со спецификацией HTML5 ... Теперь можно поместить элемент уровня блока внутри встроенного элемента. Так что теперь вполне уместно поместить «div» или «h1» внутри элемента «a».

Abir
источник
1
Только внутри элементов потока (по умолчанию = блок ) или прозрачных элементов (например, a ) с родителями, которые допускают элементы потока . Например, p не допускает элементы потока (например, div ), а только элементы phrasing (default = inline ), поэтому a внутри p не может содержать div . Однако, a внутри div может содержать p s, div s или любой другой элемент потока .
Патанджали
4

Вы не можете положить <div>внутрь <a>- это недопустимый (X) HTML.

Даже если вы стилизуете диапазон с помощью display: block, вы все равно не можете поместить в него элементы уровня блока: (X) HTML по-прежнему должен подчиняться (X) HTML DTD (независимо от того, какой вы используете), независимо от того, как работает CSS меняет вещи.

Браузер, вероятно, отобразит его так, как вы хотите, но это не поможет.

Greg
источник
4

DTD для HTML 4 можно найти по адресу http://www.w3.org/TR/REC-html40/sgml/dtd.html . Этот DTD является машинно-обрабатываемой формой спецификации, с ограничением, что DTD управляет XML и HTML 4, особенно «временный» вариант, допускает множество вещей, которые не являются «легальными» XML. Тем не менее, я считаю, что это близко к кодификации намерений спецификаторов.

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

Я бы интерпретировал теги, перечисленные в этой иерархии, как сумму разрешенных тегов.

Хотя в спецификации может быть указано «встроенные элементы», я почти уверен, что это не означает, что вы можете обойти намерение, объявив тип отображения элемента блока как встроенный. Встроенные теги имеют различную семантику, независимо от того, как вы можете злоупотреблять ими.

С другой стороны, я нахожу интригующим, что включение, specialкажется, позволяет вкладывать Aэлементы. Вероятно, в спецификации есть сильная формулировка, которая запрещает это, даже если он синтаксически корректен в XML, но я не буду вдаваться в подробности, так как это не тема вопроса.

Карл Смотриц
источник
Ты знаешь, что - - значит. Я пытался найти объяснение, но я не смог его найти.
Эван Тодд
4

Элементы уровня блока, такие как <div>могут быть обернуты <a>тегами в HTML5. Хотя a <div>считается контейнером / оберткой для содержимого потока, а <a>s рассматривается как содержимое потока в соответствии с MDN . Семантически может быть лучше создать встроенные элементы, которые действуют как элементы уровня блока.

Beepye
источник
1
Как а элементы являются прозрачными , только если родительский элемент а позволяет потоку ( по умолчанию в качестве блока ) элементов.
Патанджали
2

Если вы хотите избежать семантической проблемы размещения элементов div внутри тегов привязки, просто поместите тег привязки на тот же уровень, что и элементы div, оберните их все контейнером position: относительный, сделайте позицию тега привязки абсолютной и разверните ее до заполнить контейнер. Также, если это не конец потока контента, убедитесь, что вы добавили z-index, чтобы разместить его над контентом.

Как и предполагалось, я добавил код разметки:

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

И CSS

.div__container {
  position: relative; 
}
.div__container a {
  position: absolute;
  top: 0;
  bottom: 0;      
  left: 0;
  right: 0;
  z-index: 999;
}
Eugen
источник
1
Хотя ваш ответ может быть правильным, было бы полезно, если бы вы проиллюстрировали его разметкой.
Даташаман
1

Если вы собираетесь заняться созданием <a>блока, почему бы не поместить его <a>в div, будучи элементом блока, это даст вам тот же эффект.

Дейв
источник
36
Поскольку я мог бы хотеть, чтобы якорь заключил многократные div.
Том
1

Если вы измените его на элемент блочного стиля, то нет, это больше не «неправильно», но, вероятно, не будет проверено. Но не имеет смысла делать то, что ты делаешь. Вы должны либо просто оставить тег привязки как элемент уровня блока без внутреннего элемента div, либо поместить элемент div снаружи.

Крис
источник
1

Это не правильно. Используйте промежуток .

Джон Хэдли
источник
4
Rofl это то же самое, что с использованием div. я думаю, что я видел, как это сделано (с divs) на blip.tv, но как другие упоминают, что это неправильно в соответствии со спецификацией block = block, если div или span или что-то в этом роде!
Джеймс Митч
0

Я думаю, что в большинстве случаев, когда люди задают этот вопрос, они создают сайт, содержащий только div, и теперь один из div должен быть ссылкой.

Я видел, как кто-то использовал прозрачное пустое изображение, PNG, внутри тега привязки просто для создания ссылки внутри div, и изображение было того же размера, что и div.

Довольно печально на самом деле ... но это работает ...

user1081070
источник
0

Вы можете добиться этого, добавив псевдоэлемент ":: before"

Чистый трюк CSS;)

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

Просто как к сведению.

Если ваша цель - сделать ваш div кликабельным, вы можете использовать jQuery / Java Script.

Определите ваш div следующим образом:

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

Ваш jQuery будет тогда реализован так:

 <script type="text/javascript">

    $(document).ready(function () {

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

Это также будет работать для нескольких div-ов - согласно комментарию Тома в этой теме

Сольвейг
источник
17
Это ужасно, его нельзя использовать с клавиатурой, вы не можете видеть ссылку при наведении курсора. Он работает почти как ссылка, но не является реальной ссылкой. Вы также не можете щелкнуть по нему средней кнопкой или щелкнуть правой кнопкой мыши по ссылке.
WhyNotHugo
1
Это, безусловно, имеет свое применение. Вы можете поместить якорь внутри div и перенаправить div-click к местоположению дочернего якоря. Установив курсор на элемент div на указатель, вы тем самым получите внешний вид привязки, а также допустимое запасное решение только с привязкой внутри элемента div, если javascript не разрешен или по причинам доступности. Вы получаете семантически и синтаксически правильный HTML, и вам не нужно возиться с сомнительными изменениями стиля отображения.
Педери
Если у вас есть div, содержащий ссылку, обработчик кликов может перехватить событие, найти привязку (убедитесь, что она только одна), а затем использовать ее. Доступно через обычный тег привязки. Это позволит иметь корзину с изображениями и надписью и ссылку «читать дальше» - например. Мысли?
Julix