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

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

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

что не так в этом селекторе и как его исправить?

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

.home .red:first-child {
    border: 1px solid 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>

как я могу нацелить первого ребенка с class red?

18 ответов


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

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

к сожалению, нет подобного :first-of-class псевдо-класс для сопоставления первого дочернего элемента данного класса. Один обходной путь, что Леа 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>
  1. правила не применяются; граница не отображается.
    Этот элемент не имеет класса red, поэтому он пропущен.

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

  3. применяются оба правила; граница не отображается.
    Этот элемент имеет класс 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 */
    }
    
  • вы можете фильтровать по селекторы атрибутов или любой другой простой селекторы вместо классов.

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

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

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

имейте в виду, что этот ответ предполагает, что этот вопрос ищет каждый первый дочерний элемент с заданным классом. Нет ни псевдокласса, ни даже общего CSS-решения для n-го соответствия сложного селектора по всему документу - существует ли решение зависит сильно на структуре документа. библиотека jQuery предоставляет :eq(), :first, :last и больше для этой цели, но обратите внимание еще раз, что они функционируют совсем не так, как :nth-child() et al. Используя API селекторов, вы можете использовать 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) решение в первоначальном принятом ответе Филипп Daubmeier works (который был первоначально написан Мартын но удалены с), он ведет себя не так, как вы ожидали бы.

например, если вы хотите выбрать 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 элемент.


The :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 будет тогда красный.

обновление:

Я не знаю, почему Мартин удалил свой ответ, но у него было решение,: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>

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


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

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

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

скрипка или этого не произошло.

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

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


вы могли бы использовать 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>

чтобы соответствовать вашему селектору, элемент должен иметь имя класса 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>

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

  1. присвоить first класс для элемента при его создании, например:

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

    CSS:

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

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

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

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

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

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

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

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


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

<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 об этом.


Я использую ниже 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>

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


попробуйте это :

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

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

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>

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

.class:first-of-type { }

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


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

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

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

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

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

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

CodePen link


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

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

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

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

.home p:first-of-type

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

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