Вопрос или проблема
Я наткнулся на вопрос о селекторе CSS. Как выбрать первое вхождение <span>
, игнорируя иерархию. Я знаю, что могу использовать JavaScript с document.querySelectorAll('span')
, чтобы получить первый объект DOM и назначить ему класс. Но есть ли способ достичь этого без использования JavaScript?
HTML-структура произвольная, поэтому такие селекторы, как div:first-child > p:first-of-type > div:first-of-type span:first-of-type
, слишком специфичны. Я хочу, чтобы селектор работал даже в случае изменения структуры HTML.
Я попробовал что-то вроде этого, но не понимаю, почему MISS ME 4
тоже выбран.
span:first-of-type:not(:has(span):nth-child(n+2 of :has(span)) span) {
color: red;
font-weight: bold;
}
<div>
<h1>Выберите первое вхождение span</h1>
<p>
<span>HIT ME</span>
<div>
<span>MISS ME 1</span>
<span>MISS ME 2</span>
<span>MISS ME 3</span>
</div>
<span>MISS ME 4</span>
<span>MISS ME 5</span>
</p>
<p>
<span>MISS ME 6</span>
<span>MISS ME 7</span>
</p>
</div>
<div>
<p>
<span>MISS ME 7</span>
<span>MISS ME 8</span>
</p>
<p>
<span>MISS ME 9</span>
<span>MISS ME 10</span>
<span>MISS ME 11</span>
</p>
<p>
<span>MISS ME 12</span>
<span>MISS ME 13</span>
<span>MISS ME 14</span>
<div>
<span>MISS ME 15</span>
<span>MISS ME 16</span>
<span>MISS ME 17</span>
</div>
</p>
</div>
Возможно ли это вообще? У меня совсем нет идей.
</div><div class="s-prose js-post-body" itemprop="text">
Чтобы выбрать первый span в документе, выберите элемент span, который:
- не предшествует соседний элемент span
- не предшествует соседний элемент, содержащий элемент span
- не имеет предшествующего предка, который является соседним элементом span
- не имеет предшествующего предка, который является соседним элементом, содержащим элемент span
Используйте:
span:not(span ~ span):not(:has(span) ~ span):not(span ~ * span):not(:has(span) ~ * span)
span:not(span ~ span):not(:has(span) ~ span):not(span ~ * span):not(:has(span) ~ * span) {
color: red;
font-weight: bold;
}
<div>
<h1>Выберите первое вхождение span</h1>
<p>
<span>HIT ME</span>
<div>
<span>MISS ME 1</span>
<span>MISS ME 2</span>
<span>MISS ME 3</span>
</div>
<span>MISS ME 4</span>
<span>MISS ME 5</span>
</p>
<p>
<span>MISS ME 6</span>
<span>MISS ME 7</span>
</p>
</div>
<div>
<p>
<span>MISS ME 7</span>
<span>MISS ME 8</span>
</p>
<p>
<span>MISS ME 9</span>
<span>MISS ME 10</span>
<span>MISS ME 11</span>
</p>
<p>
<span>MISS ME 12</span>
<span>MISS ME 13</span>
<span>MISS ME 14</span>
<div>
<span>MISS ME 15</span>
<span>MISS ME 16</span>
<span>MISS ME 17</span>
</div>
</p>
</div>
Ответ или решение
Чтобы выбрать первое вхождение тега <span>
в HTML-документе, игнорируя иерархию, необходимо использовать подход, который позволяет обойти ограничения стандартных селекторов CSS. Обычно, при использовании селекторов, таких как :first-child
или :first-of-type
, вы сталкиваетесь с проблемами, когда структура документа меняется, что делает ваш селектор неэффективным.
Проблема:
В представленном вопросе необходимо выбрать первый элемент <span>
, независимо от того, в каком родительском элементе он находится. Стандартные селекторы недостаточны для этой задачи, ведь они не дают возможности игнорировать иерархию элементов.
Решение:
В последнее время появляется возможность использовать более современные CSS-селекторы, такие как :has()
, но это не поддерживается всеми браузерами (на момент написания). Тем не менее, можно воспользоваться комбинацией селекторов, которые помогут отфильтровать нужный элемент. Ниже приведён пример, как можно попытаться решить данную задачу:
span:not(:has(span)):nth-of-type(1) {
color: red;
font-weight: bold;
}
Однако это не идеальное решение, так как оно может не сработать в случае наличия вложенных элементов <span>
внутри других контейнеров.
Альтернативный подход:
Для точного выбора первого <span>
, игнорируя иерархию и избегая использования JavaScript, можно использовать следующую комбинацию селекторов:
span:not(:has(span)) {
color: red;
font-weight: bold;
}
Это позволит выбрать все элементы <span>
, которые не содержат другие элементы <span>
, но здесь также необходимо будет учитывать контекст, в котором вы работаете. В случае, если структура изменится, может потребоваться дополнительное уточнение селектора.
Примечания:
- Следите за совместимостью – Использование селекторов, таких как
:has()
, не поддерживается всеми браузерами, поэтому важно протестировать решение в разных средах. - Адаптивность – Всегда старайтесь разрабатывать такие селекторы, которые будут адаптивны к изменениям в HTML-структуре. Возможное решение требует тщательной проверки.
Выводы:
Выбор первого тега <span>
без учета иерархии с помощью только CSS — это сложная задача. Тем не менее, применение современных селекторов и комбинаций может помочь добиться нужного результата. Важно помнить о разумном использовании возможностей CSS, чтобы избежать проблем с совместимостью и производительностью.
Этот метод далеко не идеален, но дает вам направление для поиска оптимальных решений. Если вы всё же хотите добиться 100% контроля, лучшее решение будет включать в себя JavaScript, который может избирательно модифицировать элементы на странице.