Is this what you want to achieve?
.a>.c {
border: solid red;
border-width: 0 1px;
}
.a>*:not(.c) + .c,
.a>.c:first-child {
border-top-width: 1px;
}
.a>.c + *:not(.c) {
border-top: 1px solid red;
}
.a>.c:last-child {
border-bottom-width: 1px;
}
<div class="a">
<div class="b">B</div>
<div class="b">B</div>
<div class="c">C</div>
<div class="c">C</div>
<div class="d">D</div>
</div>
<hr />
<div class="a">
<div class="c">C</div>
<div class="b">B</div>
<div class="b">B</div>
<div class="c">C</div>
<div class="c">C</div>
<div class="d">D</div>
</div>
<hr />
<div class="a">
<div class="a">A</div>
<div class="b">B</div>
<div class="b">B</div>
<div class="c">C</div>
<div class="c">C</div>
<div class="d">D</div>
<div class="c">C</div>
</div>
<hr />
<div class="a">
<div class="c">C</div>
<div class="c">C</div>
<div class="c">C</div>
</div>
<hr />
<div class="a">
<div class="c">C</div>
</div>
The only "trick" is that I have to use the top border of an immediately following element after a .c
in order to place the "bottom" border of the last .c
in a group of .c
s. Currently there's no way to select a group of immediate siblings with a certain class. The point in evaluation when you know the last element with .c
in a group is the last is when you evaluate the next item and see it doesn't have .c
. But at that point, you can't style the element before, because CSS
only parses forward, never backwards.
In short, if you have a margin between elements, there is no way to do only with CSS
(* see note). It would be trivial with javascript
(I can provide it, if of any help).
* Actually, you could make this work even if with margins between elements, by null
-ing the margins between .c
and any :not(.c)
and applying the difference to the first child of the :not(.c)
instead. It's cumbersome to find a magical solution that would work in any case. Most times, these things are coded looking at the existing elements and finding tricks to make it "look like" it works.
That's all we have right now. :)