fikkatra
fikkatra

Reputation: 5842

CSS: first and last adjacent siblings of class

I'm trying to accomplish this:

enter image description here

Elements with values should have a gray 'ribbon'. Elements with values have a class selected, elements without any value don't.

My HTML looks like this:

<div class="row">
    <span>.</span>
    <span>.</span>
    <span class="selected">2</span> <!-- Should be gray & rounded (left) -->
    <span class="selected">3</span> <!-- Should be gray -->
    <span class="selected">2</span> <!-- Should be gray & rounded (right) -->
    <span>.</span>
    <span>.</span>
    <span class="selected">5</span> <!-- Should be gray & rounded (left) -->
    <span class="selected">5</span> <!-- Should be gray & rounded (right) -->
    <span>.</span>
</div>
<div class="row">
    ...
</div>

To accomplish the gray ribbon, I think I need these CSS rules:

  1. All elements with class selected should have a gray background. Easy.
  2. The first and last element of a set of adjacent elements with the class 'selected', should be rounded. Not so easy.

As far as I know, there is no CSS selector like :first-of-class. And still, it wouldn't be enough, because multiple 'ribbons' can exist on the same line. I need something like :first-adjacent-sibling-of-class.

Is there any way to accomplish this with pure CSS, or do I need JavaScript?

Upvotes: 2

Views: 941

Answers (3)

zer00ne
zer00ne

Reputation: 44118

  • Each .selected is a circle.

  • All .selected ~ siblings of the first .selected have negative margins and the left side at border-radius:0

  • All .selected that follow a :not(.selected) + is a circle with a positive left margin.

  • All :not(.selected) that follow a .selected + have a positive left margin

  • Lines do not break unless you specifically make it so with markup

Demo

.row {
  white-space: nowrap;
}

.selected {
  background: grey;
  height: 4ex;
  width: 4ch;
  border-radius: 50%;
  display: inline-block;
  margin: 0 -4px;
  line-height: 2;
  text-align: center;
}

.selected~.selected {
  margin: 0 -12px;
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
}

*:not(.selected)+.selected {
  border-top-left-radius: 50%;
  border-bottom-left-radius: 50%;
  margin: 0 -12px 0 12px
}

.selected+*:not(selected) {
  margin: 0 0 0 12px
}
<div class="row">
  <span>.</span>
  <span>.</span>
  <span class="selected">2</span>
  <span class="selected">3</span>
  <span class="selected">2</span>
  <span>.</span>
  <span>.</span>
  <span class="selected">5</span>
  <span class="selected">5</span>
  <span>.</span>
</div>
<div class="row">
  <span>.</span>
  <span>.</span>
  <span class="selected">2</span>
  <span class="selected">3</span>

  <span>.</span>
  <span class="selected">2</span>
  <span>.</span>
  <span class="selected">5</span>
  <span class="selected">5</span>
  <span>.</span>
  <span class="selected">2</span>
  <span class="selected">2</span>
  <span class="selected">2</span>
  <span>.</span>
  <span>.</span>
  <span>.</span>
  <span class="selected">5</span>
  <span class="selected">5</span>
  <span class="selected">5</span>
</div>
<span class="selected">5</span>

Upvotes: 0

Jithin Raj  P R
Jithin Raj P R

Reputation: 6827

I think this would be best solution for your QUESTION

As i have used the style span.selected+span.selected:before itself so your selection is safe and will not break to the next line.

Try this and tell me if there is anything more.Ty. Cheers..

div {
  display: inline-block
}

span {
  display: inline-block;
  float: left;
  padding: 15px;
  position: relative;
  /* top: 0; */
  margin: 10px 0;
}

span.selected {
  background: gray;
  border-radius: 50%;
}

span.selected+span.selected:before {
  content: '';
  height: 100%;
  width: 40px;
  position: absolute;
  background: gray;
  top: 0;
  left: -20px;
  z-index: -1;
}

span.selected+span.not {
  border-radius: 50%;
}
<div>
  <span class="selected">1</span>
  <span class="selected">2</span>
  <span class="selected">3</span>
  <span class="selected">4</span>
  <span class="selected">5</span>
  <span class="not">6</span>
  <span class="not">7</span>
  <span class="not">8</span>
  <span class="not">9</span>
  <span class="selected">10</span>
  <span class="selected">11</span>
  <span class="selected">12</span>
  <span class="selected">13</span>
  <span class="selected">14</span>
  <span class="selected">15</span>
  <span class="not">16</span>
  <span class="not">17</span>
  <span class="not">18</span>
  <span class="not">19</span>
  <span class="not">20</span>
</div>

Upvotes: 4

Saravanan I
Saravanan I

Reputation: 1229

I think this might help, I added a not-selected class and targeted the adjacent selected element

.selected{
  background-color: #b7dafd;
}
span{
  float: left;
  padding: 10px;
  position: relative;
}
.not-selected+.selected{
  border-radius: 20px 0 0 20px;
  padding-left: 25px;
}
.selected+.not-selected:before{
  content: '';
  display: block;
  position: absolute;
  left:0;
  top: 0;
  height: 100%;
  border-right: 20px solid #b7dafd;
  border-radius: 0 20px 20px 0;
}
<div class="row">
    <span class="not-selected">.</span>
    <span class="not-selected">.</span>
    <span class="selected">2</span> <!-- Should be gray & rounded (left) -->
    <span class="selected">3</span> <!-- Should be gray -->
    <span class="selected">2</span> <!-- Should be gray & rounded (right) -->
    <span class="not-selected">.</span>
    <span class="not-selected">.</span>
    <span class="selected">5</span> <!-- Should be gray & rounded (left) -->
    <span class="selected">5</span> <!-- Should be gray & rounded (right) -->
    <span class="not-selected">.</span>
    <span class="not-selected">.</span>
    <span class="not-selected">.</span>
    <span class="selected">2</span> <!-- Should be gray & rounded (left) -->
    <span class="selected">3</span> <!-- Should be gray -->
    <span class="selected">2</span> <!-- Should be gray & rounded (right) -->
    <span class="not-selected">.</span>
    <span class="not-selected">.</span>
    <span class="not-selected">.</span>
    <span class="selected">5</span> <!-- Should be gray & rounded (left) -->
    <span class="selected">5</span> <!-- Should be gray & rounded (right) -->
    <span class="not-selected">.</span>
    <span class="not-selected">.</span>
    <span class="not-selected">.</span>
</div>

Upvotes: 5

Related Questions