Элементы группы с CSS

Я сделал быстрый шаблон, чтобы объяснить, чего я пытаюсь достичь: http://codepen.io/anon/pen/XJWrjO

Как вы можете видеть, существует два класса элементов. .one и .two

Я хочу сгруппировать следующие элементы друг с другом через css. Это будет визуальная группировка; не структурная группировка.

Вкратце, я хочу сделать, чтобы дать margin-top первому элементу для каждого кластера классов и margin-bottom последнему элементу каждого кластера.

Итак, в зависимости от моего примера здесь находятся кластеры:

1,2,3,4         - red cluster
5,6,7           - cyan cluster
8,9             - red cluster
10,11,12,13,14  - cyan cluster
15              - red cluster
16,17           - cyan cluster

Таким образом, согласно этой структуре, div5 будет иметь margin-top, а div7 будет иметь margin-bottom.

Или, div5 будет иметь margin-top, а div8 будет иметь margin-top (аналогичный результат с предыдущим утверждением)

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

Нет JS, только CSS.

Ответ 1

Поскольку вы не можете комбинировать :last-child с селектором .class, трудно назначить margin-bottom последнему элементу кластера. Но вы можете обнаружить переключатель в другой кластер, используя +:

.one + .two, .two + .one {
    margin-top: 50px;
}

См. DEMO.

РЕДАКТИРОВАТЬ в отношении комментария с общим правилом: Там нет такого общего правила, о котором я знаю, что будет работать прямо сейчас, поскольку CSS не предоставляет ничего подобного :nth-of-class и не поддерживает обратные ссылки на классы предыдущих селекторов. Таким образом, вы не можете сделать что-либо вроде

.{class-variable} + :not(.{class-variable})

но если у вас есть список всех возможных классов, вы можете сделать что-то подобное:

.one + :not(.one), 
.two + :not(.two) {
    margin-top: 50px;
}

Вам нужно будет повторить это для каждого класса, который находится в списке. См. DEMO 2, который имеет три разных класса.

При генерации вывода вам нужно будет собрать все классы в массиве и создать дополнительный элемент стиля в вашем выпуске, чтобы каждый раз не адаптировать ваш CSS. В PHP это может выглядеть как

$style = '';
foreach ($classes AS $class) {
    $style .= '.' . $class . ' + :not(.' . $class . '), ';
}
if ($style != '') {
    $output = '<style>' . substr($style, 0, -2) . ' { margin-top: 50px; }</style>';
}

Ответ 2

Чтобы показать альтернативу, вы можете упорядочить кластеры в разметке, назначив атрибут data-cluster:

<div class="two" data-cluster="red">6</div>

И затем настройте его как хотите:

div[data-cluster="red"] {
  background: red;
  margin-top: 10px;
}

div[data-cluster="red"] + div[data-cluster="red"] {
  margin-top: 0; 
}

Демо

Ответ 3

Просто чтобы добавить ответ @Paul (отличный), вы могли бы подойти к этой проблеме наоборот, применив верхнее поле для всех дочерних элементов, а затем переопределите это поле, когда дочерний элемент следит за ребенком с тем же классом.

Вот так:

div {
  width: 100%;
  margin: 2px;
  margin-top: 50px;
}
.one + .one, .two + .two {
  margin-top: 0;
}

ОБНОВЛЕННЫЙ КОДЕКС

Одним из преимуществ этого подхода является то, что селектор :not, который не поддерживается старыми браузерами например ie8, - это не необходимо.

Здесь пример с 3 классами

div {
  width: 100%;
  margin: 2px;
  margin-top: 50px;
} 
.one + .one, .two + .two, .three + .three {
  margin-top: 0;
}

CODEPEN 2

body {
  padding: 64px;
  margin: 0;
  text-align: center;
  font-size: 20px;
  font-family: Arial;
  line-height: 40px;
}
div {
  width: 100%;
  margin: 2px;
  margin-top: 50px;
}
.one + .one,
.two + .two,
.three + .three {
  margin-top: 0;
}
.one {
  background-color: tomato;
}
.two {
  background-color: aqua;
}
.three {
  background-color: maroon;
}
<div class="one">1</div>
<div class="one">2</div>
<div class="three">3</div>
<div class="three">4</div>
<div class="two">5</div>
<div class="two">6</div>
<div class="two">7</div>
<div class="one">8</div>
<div class="one">9</div>
<div class="two">10</div>
<div class="two">11</div>
<div class="three">12</div>
<div class="three">13</div>
<div class="two">14</div>
<div class="one">15</div>
<div class="two">16</div>
<div class="two">17</div>

Ответ 4

проверить, может быть, это помогает вам, что вы достигаете: -

Демо

div:nth-child(1){margin-top:10px;color:green}
div:nth-child(17){margin-bottom:10px;color:yellow}

Ответ 5

Это то, чего вы пытаетесь достичь?

Отметьте демо.

CSS

.one-group div:last-child{
margin-bottom:15px;}

.two-group div:last-child{
margin-bottom:15px;}