it-swarm.com.ru

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>

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

828
Rajat

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

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

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

/* 
 * 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 переопределяет первое, тем самым "отменяя" его, так сказать.

В качестве бонуса, хотя он был представлен в Selectors 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, вы не можете добиться того же с помощью одного селектора для использования с локаторами CSS Selectors API или Selenium .

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

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

1291
BoltClock

Селектор :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>

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

312
Philip Daubmeier

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

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

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

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

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

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

67
SamGoody

вы можете использовать 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>
19
Moes

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

Поскольку другие ответы охватывают то, что неправильно с ним, я попробую другую половину, как это исправить. К сожалению, я не знаю, что у вас есть только 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");
    
8
Nick Craver

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

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>
5
Yener Örer

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

<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 и, наконец, все . красные элементы , которые размещаются сразу после элементов span.

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

5
StinkyCat

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

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

3
Jamie Paterson

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

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

3
Prabhakar

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

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

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

.class:first-of-type { }

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

2
Gabriel Fair

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

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

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

#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>
1
Yavor Ivanov

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

 .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

0
Santosh Khalse

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

<!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>
0
Alexander V. Ulyanov