Чи може CSS виявити кількість дітей, які має елемент?


304

Я, мабуть, відповідаю на власне запитання, але мені надзвичайно цікаво.

Я знаю, що CSS може вибрати окремих дітей з батьків, але чи є підтримка для стилювання дітей контейнера, якщо його батько має певну кількість дітей.

наприклад

container:children(8) {
  // style the parent this way if there are 8 children
}

Я знаю, що це звучить дивно, але мій менеджер попросив мене перевірити це, не знайшов нічого самостійно, тому я вирішив звернутися до ТА, перш ніж закінчити пошук.


2
Кількість запитів SCSS Mixin: codepen.io/jakob-e/pen/wgGpeP
Jakob E

Відповіді:


695

Пояснення:

Через попередню фразу в оригінальному запитанні, деякі громадяни ЗП висловлювали занепокоєння, що ця відповідь може бути оманливою. Зауважте, що в CSS3 стилі не можуть бути застосовані до батьківського вузла залежно від кількості дітей, які він має. Однак стилі можуть бути застосовані до дитячих вузлів залежно від кількості брати і сестер .


Оригінальна відповідь:

Неймовірно, що зараз це можливо виключно в CSS3.

/* one item */
li:first-child:nth-last-child(1) {
/* -or- li:only-child { */
    width: 100%;
}

/* two items */
li:first-child:nth-last-child(2),
li:first-child:nth-last-child(2) ~ li {
    width: 50%;
}

/* three items */
li:first-child:nth-last-child(3),
li:first-child:nth-last-child(3) ~ li {
    width: 33.3333%;
}

/* four items */
li:first-child:nth-last-child(4),
li:first-child:nth-last-child(4) ~ li {
    width: 25%;
}

Хитрість полягає в тому, щоб вибрати першу дитину, коли вона також є п’ятою з останніх дитини. Це ефективно вибирається виходячи з кількості братів і сестер.

Заслуга цієї техніки належить Андре Луїсу (відкритий) та Леа Веру (вишуканий).

Ви просто не любите CSS3? 😄

Приклад CodePen:

Джерела:


7
Дуже зручно. Я написав SASS mixin, який використовує цю техніку: codepen.io/anon/pen/pJeLdE?editors=110
SimpleJ

1
@IanSteffy Я щойно тестував це на Chrome 45.0.2454.85 (64-бітний), і він працює добре ...?
Matthemattics

2
Якщо вона працює в кодені, але не з моїм проектом, то, безумовно, я винна. Моє ліжко. Ця відповідь правильна! Правильно, кажу!
Ян S

3
Можливо, приємно додати, чому це працює, для людей, які не звикли до декількох псевдоселекторів (як я був дотепер;). Що відбувається тут, це те, що це вибирає дитину, яка є водночас дитиною x від початку / згори і дитина y від кінця. І тому це вибирає щось лише у тому випадку, якщо є саме діти x + y.
Леголас

7
Зауважте, що замість :first-child:nth-last-child(1)вас також можна використовувати :only-child.
Адам Рейс

40

Ні. Не дуже. Є кілька селекторів, які можуть вас зблизити, але, ймовірно, не працюватимуть у вашому прикладі та не мають найкращої сумісності браузера.

:only-child

Це :only-childодин з небагатьох істинних селекторів підрахунку в тому сенсі, що він застосовується лише тоді, коли є одна дитина з батьківського елемента. Використовуючи свій ідеалізований приклад, він діє так, children(1)напевно.

:nth-child

:nth-childСелектор може реально отримати , де ви хочете піти в залежності від того, що ви дійсно хочете зробити. Якщо ви хочете стилізувати всі елементи, якщо є 8 дітей, вам не пощастило. Якщо ви хочете застосувати стилі до 8-го та пізніших елементів, спробуйте це:

p:nth-child( n + 8 ){
    /* add styles to make it pretty */
}

На жаль, це, мабуть, не ті рішення, які ви шукаєте. Зрештою, вам, мабуть, знадобиться скористатись майстром Javascript, щоб застосувати стилі на основі підрахунку - навіть якщо ви використовували один із них, вам потрібно буде уважно ознайомитися із сумісністю браузера, перш ніж перейти до чистого CSS-рішення.

W3 CSS3 Spec на псевдокласах

РЕДАКЦІЯ Я читаю ваше запитання дещо інакше - є кілька інших способів стилю батьків , а не дітей. Дозвольте мені кинути декілька інших селекторів по-своєму:

:empty і :not

Це елементи стилів, у яких немає дітей. Це не так корисно самостійно, але, поєднавшись із :notселектором, ви можете стилізувати лише ті елементи, які мають діти:

div:not(:empty) {
    /* We know it has stuff in it! */
}

Ви не можете порахувати, скільки дітей тут доступно з чистим CSS, але це ще один цікавий вибір, який дозволяє робити цікаві речі.


Варто зазначити, що оригінальне запитання було відредаговано, зробивши початкове "Ні" трохи оманливим (просто fyi 😛)
Matthemattics

18

ПРИМІТКА. Це рішення поверне дітям множини певної довжини, а не батьківський елемент, як ви просили. Сподіваємось, це все-таки корисно.

Андре Луїс придумав метод: http://lea.verou.me/2011/01/styling-children-based-on-their-number-with-css3/ На жаль, він працює лише в IE9 і вище.

По суті, ви поєднуєте: nth-child () з іншими псевдокласами, які мають справу з положенням елемента. Такий підхід дозволяє задавати елементи із наборів елементів із визначеною довжиною .

Наприклад, :nth-child(1):nth-last-child(3)відповідає першому елементу в наборі, а також є 3-м елементом з кінця набору. Це робить дві речі: гарантує, що в наборі є лише три елементи і що у нас є перший з трьох. Щоб вказати другий елемент набору трьох елементів, ми використали б :nth-child(2):nth-last-child(2).


Приклад 1 - Виберіть усі елементи списку, якщо в комплекті є три елементи:

li:nth-child(1):nth-last-child(3),
li:nth-child(2):nth-last-child(2),
li:nth-child(3):nth-last-child(1) {
    width: 33.3333%;
}

Приклад 1 альтернативи від Lea Verou:

li:first-child:nth-last-child(3),
li:first-child:nth-last-child(3) ~ li {
    width: 33.3333%;
}


Приклад 2 - цільовий останній елемент набору з трьома елементами списку:

li:nth-child(3):last-child {
    /* I'm the last of three */
}

Приклад 2 альтернатива:

li:nth-child(3):nth-last-child(1) {
    /* I'm the last of three */
}


Приклад 3 - цільовий другий елемент набору з чотирма елементами списку:

li:nth-child(2):nth-last-child(3) {
    /* I'm the second of four */
}

1
знову ж таки, це кількість братів і сестер, а не дітей
TMS

@TMS див. Редагування прийнятої відповіді - питання ОП було незручно сформульовано
ifugu

Цей підхід ідеально підходить для тих випадків, коли кожен елемент повинен бути викладений по-різному, виходячи з його положення у списку, наприклад, щоб отримати рівномірні кругові перетворення: li:nth-child(3):nth-last-child(1) { transform: rotate(120deg); } li:nth-child(2):nth-last-child(2) { transform: rotate(240deg); }і так далі ...
Грег Сміт

11

Опрацьовуючи рішення Метта, я використав таку реалізацію Compass / SCSS.

@for $i from 1 through 20 {
    li:first-child:nth-last-child( #{$i} ),
    li:first-child:nth-last-child( #{$i} ) ~ li {
      width: calc(100% / #{$i} - 10px);
    }
  }

Це дозволяє швидко розширити кількість елементів.


4
Замість цього ви можете легко використовувати Flexbox…
Michał Miszczyszyn

6

так, ми можемо це зробити, використовуючи nth-дитини так

div:nth-child(n + 8) {
    background: red;
}

Це зробить дитину 8-го діва далі червоною. Сподіваюся, це допомагає ...

Крім того, якщо хтось коли-небудь скаже "ей, вони не можуть бути виконані зі стилем за допомогою css, використовуйте JS !!!" сумнівайтеся в них негайно. CSS сьогодні надзвичайно гнучкий

Приклад :: http://jsfiddle.net/uWrLE/1/

У прикладі перші 7 дітей сині, потім 8 далі червоні ...


1
Можливо, додати примітку про нещасливу відсутність підтримки ?
benesch

2
Я не думаю, що це саме те, що просить Броді - це буде стилювати дітей після певної кількості, але не може вибрати предка / елемента, що містить, залежно від кількості дітей.
Бен Халл

Це насправді якась гарна інформація, хоча, дякую алан, але бджола має рацію, я намагалася сказати "якщо у елемента є стільки дітей, нам цей стиль". Якщо я не помиляюся, ваш метод мав би бути 8-м дитиною, але перші 7 були б самотніми і голими.
Броді

@primatology - Єдиний браузер, який не підтримує nth-дитини, - IE <9. Всі інші підтримують його дві версії назад або більше.
Роб

-1 Це не зробить дитину-дитиною червоною, це зробить діва червоним на основі його кількості у своїх побратимів ! Ні в якому разі не пов'язаний з дитиною дива!
TMS

5

Якщо ви збираєтеся робити це в чистому CSS (з використанням scss), але у вас є різні елементи / класи всередині одного батьківського класу, ви можете використовувати цю версію !!

  &:first-of-type:nth-last-of-type(1) {
    max-width: 100%;
  }

  @for $i from 2 through 10 {
    &:first-of-type:nth-last-of-type(#{$i}),
    &:first-of-type:nth-last-of-type(#{$i}) ~ & {
      max-width: (100% / #{$i});
    }
  }

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.