You can apply different rules to the first match of multiple siblings (using CSS) by setting the rule for all siblings and overriding it for subsequent ones:
#foo > .B {
color: red;
}
#foo > .B ~ .B {
color: black;
}
<div id="foo">
<div class="A">
A
</div>
<div class="B">
B
</div>
<div class="B">
C
</div>
<div class="B">
D
</div>
</div>
However, this is not possible for the last match, as CSS only parses forwards, never backwards.
But you can use JavaScript for it. Here's how:
let parentSelector = '#foo', childSelector = '.B',
parentElement = document.querySelector(parentSelector),
firstChild = parentElement.querySelector(childSelector),
lastChild = [].slice.call(parentElement.querySelectorAll(childSelector)).slice(-1)[0];
Test:
let parentSelector = '#foo',
childSelector = '.B',
parentElement = document.querySelector(parentSelector),
firstChild = parentElement.querySelector(childSelector),
lastChild = [].slice.call(parentElement.querySelectorAll(childSelector)).slice(-1)[0];
firstChild.style.color = 'red';
lastChild.style.color = 'orange';
<div id="foo">
<div class="A">
A
</div>
<div class="B">
B
</div>
<div class="B">
C
</div>
<div class="B">
D
</div>
<div class="A">
E
</div>
</div>
You can take it further and apply classes to first and last elems instead of modifying styles on the fly, to increase maintainability, but that's a different subject altogether.
Keep in mind the above code only parses the first element matched by parentSelector
. If you have more than one and want to parse all, it gets a bit more complex:
let parentSelector = '.parent',
childSelector = '.B',
firstChild = (parent, childSelector) => parent.querySelector(childSelector),
lastChild = (parent, childSelector) => [].slice.call(parent.querySelectorAll(childSelector)).slice(-1)[0],
applyMyChanges = el => {
firstChild(el, childSelector).style.color = 'red';
lastChild(el, childSelector).style.color = 'orange'
};
[].slice.call(document.querySelectorAll(parentSelector)).map( applyMyChanges );
<div class="parent">
<div class="A">A</div>
<div class="B">B</div>
<div class="B">C</div>
<div class="B">D</div>
<div class="A">E</div>
</div>
<div class="parent">
<div class="A">A</div>
<div class="B">B</div>
<div class="B">C</div>
<div class="B">D</div>
<div class="A">E</div>
</div>
jQuery syntax for this task is a tad more concise:
For one instance (with #id
):
let parentSelector = '#foo',
childSelector = '.B';
$(childSelector, parentSelector).first().css({color:'red'});
$(childSelector, parentSelector).last().css({color:'orange'});
For any number of instances (with .class
):
let parentSelector = '.parent',
childSelector = '.B';
$(parentSelector).each(function() {
$(childSelector, this).first().css({color:'red'});
$(childSelector, this).last().css({color:'orange'});
});
jQuery test:
let parentSelector = '.parent',
childSelector = '.B';
$(parentSelector).each(function() {
$(childSelector, this).first().css({color:'red'});
$(childSelector, this).last().css({color:'orange'});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="parent">
<div class="A">A</div>
<div class="B">B</div>
<div class="B">C</div>
<div class="B">D</div>
<div class="A">E</div>
</div>
<div class="parent">
<div class="A">A</div>
<div class="B">B</div>
<div class="B">C</div>
<div class="B">D</div>
<div class="A">E</div>
</div>