Селектор CSS для первого элемента с классом

У меня есть набор элементов с red именем класса, но я не могу выбрать первый элемент с class="red" используя следующее правило CSS:

.red:first-child {
    border: 5px solid red;
}
<p class="red"></p>
<div class="red"></div>

Ответ 1

Это один из самых известных примеров того, как авторы не понимают, как работает :first-child. Представленный в CSS2, псевдокласс class :first-child представляет самый первый дочерний элемент родительского. Это. Там очень распространенное заблуждение, что он выбирает, какой дочерний элемент является первым, чтобы соответствовать условиям, указанным остальной частью составного селектора. Из-за того, как работают селекторы (см. здесь для объяснения), это просто неверно.

Селектор 3-го уровня вводит псевдо-класс :first-of-type, который представляет собой первый элемент среди братьев и сестер его типа элемента. Этот ответ объясняет, с иллюстрациями, разницу между :first-child и :first-of-type. Однако, как и в случае с :first-child, он не смотрит на какие-либо другие условия или атрибуты. В HTML тип элемента представлен именем тега. В вопросе этот тип p.

К сожалению, не существует подобного псевдо-класса :first-of-class для сопоставления первого дочернего элемента данного класса. Один обход, который Lea Verou и я придумал для этого (хотя и совершенно независимо), сначала применить ваши желаемые стили ко всем вашим элементам с этим классом:

/* 
 * Select all .red children of .home, including the first one,
 * and give them a border.
 */
.home > .red {
    border: 1px solid red;
}

... затем "отмените" стили для элементов с классом, которые приходят после первого, используя общий комбинированный блок ~ в главном правиле:

/* 
 * Select all but the first .red child of .home,
 * and remove the border from the previous rule.
 */
.home > .red ~ .red {
    border: none;
}

Теперь только первый элемент с class="red" будет иметь границу.

Вот пример того, как применяются правила:

<div class="home">
  <span>blah</span>         <!-- [1] -->
  <p class="red">first</p>  <!-- [2] -->
  <p class="red">second</p> <!-- [3] -->
  <p class="red">third</p>  <!-- [3] -->
  <p class="red">fourth</p> <!-- [3] -->
</div>
  • Правила не применяются; никакая граница не отображается.
    Этот элемент не имеет класса red, поэтому он пропустил.

  • Применяется только первое правило; отображается красная рамка.
    Этот элемент имеет класс red, но ему не предшествуют какие-либо элементы с классом red в его родительском элементе. Таким образом, второе правило не применяется, только первое, а элемент сохраняет свою границу.

  • Оба правила применяются; никакая граница не отображается.
    Этот элемент имеет класс red. Ему также предшествует хотя бы один другой элемент с классом red. Таким образом, применяются оба правила, а второе объявление border переопределяет первое, тем самым "отменяя" его, так сказать.

В качестве бонуса, хотя он был представлен в селекторах 3, общий синонимы-комбинатор на самом деле довольно хорошо поддерживается IE7 и новее, в отличие от :first-of-type и :nth-of-type(), которые поддерживаются только IE9. Если вам нужна хорошая поддержка браузера, вам повезло.

Фактически, тот факт, что комбинатор-сиблинг является единственным важным компонентом в этой технике и обладает такой удивительной поддержкой браузера, делает эту технику очень универсальной - вы можете адаптировать ее для фильтрации элементов другими вещами, помимо селекторов классов:

  • Вы можете использовать это, чтобы обойти :first-of-type в IE7 и IE8, просто предоставив селектор типов вместо селектора классов (опять же, больше о его неправильном использовании здесь в следующем разделе):

    article > p {
        /* Apply styles to article > p:first-of-type, which may or may not be :first-child */
    }
    
    article > p ~ p {
        /* Undo the above styles for every subsequent article > p */
    }
    
  • Вы можете фильтровать селектора атрибутов или любые другие простые селекторы вместо классов.

  • Вы также можете комбинировать этот метод переопределения с псевдоэлементами, хотя псевдоэлементы технически не являются простыми селекторами.

Обратите внимание, что для того, чтобы это сработало, вам нужно заранее знать, какие стили по умолчанию будут для ваших других элементов sibling, чтобы вы могли переопределить первое правило. Кроме того, поскольку это связано с отменой правил в CSS, вы не можете добиться того же самого с помощью одного селектора для использования с API селекторов или Selenium Локаторы CSS.

Стоит отметить, что селектор 4 вводит расширение к нотации :nth-child() (первоначально совершенно новый псевдокласс класса :nth-match()), что позволит вам использовать нечто вроде :nth-child(1 of .red) вместо гипотетического .red:first-of-class. Будучи относительно недавним предложением, недостаточно совместимых реализаций для его использования на производственных площадках. Надеюсь, это скоро изменится. Тем временем обходной путь, который я предложил, должен работать в большинстве случаев.

Имейте в виду, что этот ответ предполагает, что вопрос ищет каждый первый дочерний элемент, который имеет данный класс. Для n-го совпадения сложного селектора по всему документу нет ни псевдо-класса, ни даже общего решения CSS, независимо от того, существует ли решение, в значительной степени зависит от структуры документа. jQuery предоставляет :eq(), :first, :last и больше для этой цели, но еще раз обратите внимание, что они работают по-разному, чем :nth-child() и др.. Используя API Selectors, вы можете использовать document.querySelector() для получения первого совпадения:

var first = document.querySelector('.home > .red');

Или используйте document.querySelectorAll() с индексом для выбора любого конкретного соответствия:

var redElements = document.querySelectorAll('.home > .red');
var first = redElements[0];
var second = redElements[1];
// etc

Несмотря на то, что работает .red:nth-of-type(1) решение в исходном принятом ответе Philip Daubmeier (которое первоначально было написано Martyn, но с тех пор удаляется), он не ведет себя так, как вы ожидали.

Например, если вы хотите только выбрать p в исходной разметке:

<p class="red"></p>
<div class="red"></div>

... тогда вы не можете использовать .red:first-of-type (эквивалентно .red:nth-of-type(1)), потому что каждый элемент является первым (и единственным) одним из его типов (p и div соответственно), поэтому оба будет соответствовать селектору.

Когда первый элемент определенного класса также является первым его типом, псевдокласс будет работать, но это происходит только по совпадению. Такое поведение продемонстрировано в ответе Филиппа. В тот момент, когда вы вставите элемент того же типа перед этим элементом, селектор завершится с ошибкой. Принимая обновленную разметку:

<div class="home">
  <span>blah</span>
  <p class="red">first</p>
  <p class="red">second</p>
  <p class="red">third</p>
  <p class="red">fourth</p>
</div>

Применение правила с помощью .red:first-of-type будет работать, но как только вы добавите еще один p без класса:

<div class="home">
  <span>blah</span>
  <p>dummy</p>
  <p class="red">first</p>
  <p class="red">second</p>
  <p class="red">third</p>
  <p class="red">fourth</p>
</div>

... селектор немедленно выйдет из строя, потому что первый элемент .red теперь является вторым элементом p.

Ответ 2

Селектор :first-child предназначен, как и название, для выбора первого дочернего элемента родительского тега. Дети должны быть встроены в один и тот же родительский тег. Ваш точный пример будет работать (просто попробовал здесь):

<body>
    <p class="red">first</p>
    <div class="red">second</div>
</body>

Возможно, вы вложили теги в разные теги родителя? Являются ли ваши метки класса red действительно тегами под родительским?

Обратите внимание также, что это применимо только к первому такому тегу во всем документе, но каждый раз, когда вокруг него обертывается новый родитель, например:

<div>
    <p class="red">first</p>
    <div class="red">second</div>
</div>
<div>
    <p class="red">third</p>
    <div class="red">fourth</div>
</div>

first и third будет затем красным.

Update:

Я не знаю, почему мартин удалил свой ответ, но у него было решение, селектор :nth-of-type:

<html>
<head>
<style type="text/css">
.red:nth-of-type(1)
{
    border:5px solid red;
} 
</style>
</head>

<body>
    <div class="home">
        <span>blah</span>
        <p class="red">first</p>
        <p class="red">second</p>
        <p class="red">third</p>
        <p class="red">fourth</p>
    </div>
</body>
</html>

Кредиты Martyn. Более подробная информация, например здесь. Имейте в виду, что это селектор CSS 3, поэтому не все браузеры узнают его (например, IE8 или старше).

Ответ 3

Правильный ответ:

.red:first-child, :not(.red) + .red { border:5px solid red }

Часть I: если элемент сначала принадлежит его родительскому элементу и имеет класс "красный", он должен получить границу.
Часть II: Если элемент ".red" не является первым для своего родителя, но сразу же следует за элементом без класса ".red", он также заслуживает честь указанной границы.

Fiddle или этого не произошло.

Ответ Филиппа Даубмайера, хотя и принят, неверен - см. прилагаемую скрипку.
Ответ BoltClock будет работать, но без необходимости определяет и перезаписывает стили
(в частности, проблема, когда она иначе наследует другую границу - вы не хотите объявлять другую грани: none)

EDIT: В случае, если у вас есть красный цвет, следующий за не красным несколько раз, каждый "первый" красный получит границу. Чтобы этого избежать, нужно использовать ответ BoltClock. См. fiddle

Ответ 4

вы можете использовать first-of-type или nth-of-type(1)

.red {
  color: green;  
}

/* .red:nth-of-type(1) */
.red:first-of-type {
  color: red;  
}
<div class="home">
  <span>blah</span>
  <p class="red">first</p>
  <p class="red">second</p>
  <p class="red">third</p>
  <p class="red">fourth</p>
</div>

Ответ 5

Чтобы соответствовать вашему селектору, элемент должен иметь имя класса red и должен быть первым дочерним элементом его родителя.

<div>
    <span class="red"> <!-- MATCH -->
</div>

<div>
    <span>Blah</span>
    <p class="red"> <!-- NO MATCH -->
</div>

<div>
    <span>Blah</span>
    <div><p class="red"></div> <!-- MATCH -->
</div>

Ответ 6

Поскольку другие ответы касаются того, что с ним не так, я попробую другую половину, как исправить это. К сожалению, я не знаю, что у вас есть CSS только решение, по крайней мере, не то, о чем я могу думать. Есть еще некоторые варианты, хотя....

  • Назначьте класс first элементу при его создании, например:

    <p class="red first"></p>
    <div class="red"></div>
    

    CSS

    .first.red {
      border:5px solid red;
    }
    

    Этот CSS соответствует только элементам и first и red.

  • В качестве альтернативы, сделайте то же самое в JavaScript, например, здесь, какой jQuery вы будете использовать для этого, используя тот же CSS, что и выше:

    $(".red:first").addClass("first");
    

Ответ 7

Согласно вашей обновленной проблеме

<div class="home">
  <span>blah</span>
  <p class="red">first</p>
  <p class="red">second</p>
  <p class="red">third</p>
  <p class="red">fourth</p>
</div>

как насчет

.home span + .red{
      border:1px solid red;
    }

Это выберет класс home, затем элемент span и, наконец, все элементы.red, которые будут размещены сразу после элементов span.

Ссылка: http://www.w3schools.com/cssref/css_selectors.asp

Ответ 8

Вы можете изменить свой код на что-то подобное, чтобы заставить его работать.

<div class="home">
  <span>blah</span>
  <p class="red">first</p>
  <p class="red">second</p>
  <p class="red">third</p>
  <p class="red">fourth</p>
</div>

Это делает вам работу

.home span + .red{
      border:3px solid green;
    }

Вот ссылка CSS из SnoopCode об этом.

Ответ 9

Приведенные выше ответы слишком сложны.

.class:first-of-type { }

Это выберет первый тип класса. MDN Source

Ответ 10

Я использую ниже CSS, чтобы иметь фоновое изображение для списка ul li

#footer .module:nth-of-type(1)>.menu>li:nth-of-type(1){
  background-position: center;
  background-image: url(http://monagentvoyagessuperprix.j3.voyagesendirect.com/images/stories/images_monagentvoyagessuperprix/layout/icon-home.png);
  background-repeat: no-repeat;
}
<footer id="footer">
  <div class="module">
    <ul class="menu ">
      <li class="level1 item308 active current"></li>
      <li> </li>
    </ul> 
  </div>
  <div class="module">
    <ul class="menu "><li></li>
      <li></li> 
    </ul>
  </div>
  <div class="module">
    <ul class="menu ">
      <li></li>
      <li></li>
    </ul>
  </div>
</footer>

Ответ 11

Вы можете использовать nth-of-type (1), но убедитесь, что сайту не нужно поддерживать IE7 и т.д., если это так, используйте jQuery для добавления класса body, затем найдите элемент через класс тела IE7, затем имя элемента, затем добавьте в него стиль nth-child.

Ответ 12

Попробуйте следующее:

    .class_name > *:first-child {
        border: 1px solid red;
    }

Ответ 13

Я получил это в своем проекте.

div > .b ~ .b:not(:first-child) {
	background: none;
}
div > .b {
    background: red;
}
<div>
      <p class="a">The first paragraph.</p>
      <p class="a">The second paragraph.</p>
      <p class="b">The third paragraph.</p>
      <p class="b">The fourth paragraph.</p>
  </div>

Ответ 14

По какой-то причине ни один из приведенных выше ответов, по-видимому, не рассматривал случай реального первого и единственного первого потомка родителя.

#element_id > .class_name:first-child

Все приведенные выше ответы потерпят неудачу, если вы захотите применить стиль только к первому дочернему классу в этом коде.

<aside id="element_id">
  Content
  <div class="class_name">First content that need to be styled</div>
  <div class="class_name">
    Second content that don't need to be styled
    <div>
      <div>
        <div class="class_name">deep content - no style</div>
        <div class="class_name">deep content - no style</div>
        <div>
          <div class="class_name">deep content - no style</div>
        </div>
      </div>
    </div>
  </div>
</aside>

Ответ 15

Попробуйте этот простой и эффективный

 .home > span + .red{
      border:1px solid red;
    }

Ответ 16

Попробуйте это решение:

 .home p:first-of-type {
  border:5px solid red;
  width:100%;
  display:block;
}
<div class="home">
  <span>blah</span>
  <p class="red">first</p>
  <p class="red">second</p>
  <p class="red">third</p>
  <p class="red">fourth</p>
</div>

Ответ 17

Нужно только первый и только один абзац сделать красным. Как?

<!DOCTYPE html><html><head><style>

article p:nth-child(1){background: red}
article p:first-child{background: red}

</style></head><body>

<p style="color:blue">Needed only first and only one paragraph had red. How?</p>

<article>
<p>The first paragraph.</p>
<div><p>The second paragraph.</p></div>
<p>The third paragraph.</p>
<div><p>The fourth paragraph.</p></div>
</article>

</body></html>

Ответ 18

Если вы используете jQuery, вы можете использовать: первый селектор.

Ответ 19

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

В этом случае также возможно использовать этот селектор

.home p:first-of-type

но это селектор элемента, а не класс.

Вот хороший список селекторов CSS: https://kolosek.com/css-selectors/