Last child with specific class [duplicate] - html

<div class="commentList">
<article class="comment " id="com21"></article>
<article class="comment " id="com20"></article>
<article class="comment " id="com19"></article>
<div class="something"> hello </div>
</div>
I want to select #com19 ?
.comment {
width:470px;
border-bottom:1px dotted #f0f0f0;
margin-bottom:10px;
}
.comment:last-child {
border-bottom:none;
margin-bottom:0;
}
That does not work as long as I do have another div.something as actual last child in the commentList. Is it possible to use the last-child selector in this case to select the last appearance of article.comment?
jsFiddle

:last-child only works when the element in question is the last child of the container, not the last of a specific type of element. For that, you want :last-of-type
http://jsfiddle.net/C23g6/3/
As per #BoltClock's comment, this is only checking for the last article element, not the last element with the class of .comment.
body {
background: black;
}
.comment {
width: 470px;
border-bottom: 1px dotted #f0f0f0;
margin-bottom: 10px;
}
.comment:last-of-type {
border-bottom: none;
margin-bottom: 0;
}
<div class="commentList">
<article class="comment " id="com21"></article>
<article class="comment " id="com20"></article>
<article class="comment " id="com19"></article>
<div class="something"> hello </div>
</div>

I guess that the most correct answer is: Use :nth-child (or, in this specific case, its counterpart :nth-last-child). Most only know this selector by its first argument to grab a range of items based on a calculation with n, but it can also take a second argument "of [any CSS selector]".
Your scenario could be solved with this selector: .commentList .comment:nth-last-child(1 of .comment)
But being technically correct doesn't mean you can use it, though, because this selector is as of now only implemented in Safari.
For further reading:
https://drafts.csswg.org/selectors-4/#the-nth-child-pseudo
http://caniuse.com/#search=nth-child

If you are floating the elements you can reverse the order
i.e. float: right; instead of float: left;
And then use this method to select the first-child of a class.
/* 1: Apply style to ALL instances */
#header .some-class {
padding-right: 0;
}
/* 2: Remove style from ALL instances except FIRST instance */
#header .some-class~.some-class {
padding-right: 20px;
}
This is actually applying the class to the LAST instance only because it's now in reversed order.
Here is a working example for you:
<!doctype html>
<head><title>CSS Test</title>
<style type="text/css">
.some-class { margin: 0; padding: 0 20px; list-style-type: square; }
.lfloat { float: left; display: block; }
.rfloat { float: right; display: block; }
/* apply style to last instance only */
#header .some-class {
border: 1px solid red;
padding-right: 0;
}
#header .some-class~.some-class {
border: 0;
padding-right: 20px;
}
</style>
</head>
<body>
<div id="header">
<img src="some_image" title="Logo" class="lfloat no-border"/>
<ul class="some-class rfloat">
<li>List 1-1</li>
<li>List 1-2</li>
<li>List 1-3</li>
</ul>
<ul class="some-class rfloat">
<li>List 2-1</li>
<li>List 2-2</li>
<li>List 2-3</li>
</ul>
<ul class="some-class rfloat">
<li>List 3-1</li>
<li>List 3-2</li>
<li>List 3-3</li>
</ul>
<img src="some_other_img" title="Icon" class="rfloat no-border"/>
</div>
</body>
</html>

Something that I think should be commented here that worked for me:
Use :last-child multiple times in the places needed so that it always gets the last of the last.
Take this for example:
.page.one .page-container .comment:last-child {
color: red;
}
.page.two .page-container:last-child .comment:last-child {
color: blue;
}
<p> When you use .comment:last-child </p>
<p> you only get the last comment in both parents </p>
<div class="page one">
<div class="page-container">
<p class="comment"> Something </p>
<p class="comment"> Something </p>
</div>
<div class="page-container">
<p class="comment"> Something </p>
<p class="comment"> Something </p>
</div>
</div>
<p> When you use .page-container:last-child .comment:last-child </p>
<p> you get the last page-container's, last comment </p>
<div class="page two">
<div class="page-container">
<p class="comment"> Something </p>
<p class="comment"> Something </p>
</div>
<div class="page-container">
<p class="comment"> Something </p>
<p class="comment"> Something </p>
</div>
</div>

The new :has() pseudo class (not yet supported by all browsers) lets you get pretty close to a solution:
.class:has(+ :not(.class))
The limitation is that this will find any element with .class which is followed by an element that doesn't have this class. But this would match the use case of the question.

What about this solution?
div.commentList > article.comment:not(:last-child):last-of-type
{
color:red; /*or whatever...*/
}

This can now be solved with careful use of :has(), specifically:
/* switch out the {class} below */
.{class}:not(:has(~ .{class}))
A similar technique also allows you to select anything but the last occurrence of a class in a container, or the last occurrence within a group of elements. See the snippet below for examples.
Note: has() is currently supported in Chrome, Edge and Safari, but not Firefox (Jan 2022)
/* last in group */
.class:has(+ :not(.class)) {
background: pink;
}
/* anything but last in container */
.class:has(~ .class) {
box-shadow: 0 0 0 1px #F00A;
}
/* last in container */
.class:not(:has(~ .class)) {
background: #0F0A;
}
<div>
<div class="class">not-last</div>
<div class="class">not-last</div>
<div class="class">last-in-group</div>
<div>---</div>
<div class="class">not-last</div>
<div class="class">last-in-group</div>
<div>---</div>
<div class="class">last-class</div>
<div>---</div>
</div>

There are two ways to select the last element of a class.
Wrap your elements in a container element.
html:
<div class="container">
<div class="member">Member</div>
<div class="member">Member</div>
<div class="member">Member</div>
<div>
css:
.container:last-child {
color: red;
}
If you don't want to wrap your elements within another element then you can leverage last-of-type.
html:
<div class="member">Member</div>
<div class="member">Member</div>
<div class="member">Member</div>
css:
.member:last-of-type{
color: red;
}

Related

CSS selector to target img that is NOT in another element [duplicate]

This question already has answers here:
CSS negation pseudo-class :not() for parent/ancestor elements
(2 answers)
Closed 4 years ago.
Check this code below:
.aaa :not(.bbb) .ccc {
font-size: 20px;
color: #FF0000;
}
<div class="aaa">
<div>
<div>
<div class="bbb">
<div>
<div>
<div class="ccc">AQUI</div>
</div>
</div>
</div>
</div>
</div>
</div>
I want to match all .ccc element that are children of .aaa but are not children of .bbb. It means that the code above should NOT make the AQUI word be RED, but it gets RED anyway. What am I doing wrong?
There are actually elements which are not .bbb - the two divs before and after .bbb in this case. For this to work, you'll need to be more specific. You can add another class (zzz in the example), and if this class is not combined with .bbb the rule will be applied.
.aaa .zzz:not(.bbb) .ccc {
font-size: 20px;
color: #FF0000;
}
<div class="aaa">
<div>
<div>
<div class="zzz bbb">
<div>
<div>
<div class="ccc">AQUI</div>
</div>
</div>
</div>
</div>
</div>
</div>
The not(.bbb) will match any div without the class .bbb and you have a lot of them between .aaa and .ccc that why the text is red. To do what you want you need to consider two selectors
.aaa .ccc {
font-size: 20px;
color: #FF0000;
}
/*we reset the style if children of .bbb*/
.bbb .ccc {
color: initial;
font-size:initial;
}
<div class="aaa">
<div>
<div>
<div class="bbb">
<div>
<div>
<div class="ccc">AQUI</div>
</div>
</div>
</div>
</div>
</div>
</div>
You have overlooked that the .ccc is a child of components that match :not(.bbb):
<div class="aaa">
<div class="ccc"></div>
<div class="bbb">
<div> // <-- :not(.bbb)
<div class="ccc"></div>
</div>
</div>
</div>
You need to write two rules:
.aaa .ccc {
color: blue;
}
.aaa .bbb .ccc {
color: red;
}

Select all descendant of one class except those inside another class (and vice versa)

I want to target all descendant paragraphs of a certain class while ignoring all descendant paragraphs of another class inside the first (this should work no matter which class is inside which). To achieve this I had to use 4 selectors, like this:
* {
margin: 0.2em 0;
width: fit-content;
}
div {
margin-left: 1em
}
/* == 4 selectors to achieve desired effect = */
.orange p {
background: orange;
}
.cyan .orange p {
background: orange;
}
.cyan p {
background: cyan;
}
.orange .cyan p {
background: cyan;
}
<div class="orange">
<p>Orange</p>
<div>
<p>Orange</p>
<div>
<p>Orange</p>
<div class="cyan">
<p>Cyan</p>
<div>
<p>Cyan</p>
</div>
</div>
</div>
</div>
</div>
<div class="cyan">
<p>Cyan</p>
<div>
<p>Cyan</p>
<div>
<p>Cyan</p>
<div class="orange">
<p>Orange</p>
<div>
<p>Orange</p>
</div>
</div>
</div>
</div>
</div>
The question is:
Can this be achieved using only two selectors? [The order of these two selectors should be able to change without altering the effect.]
I have tried selectors like:
.orange:not(.cyan) p {
background: orange;
}
.cyan:not(.orange) p {
background: cyan;
}
but it doesn't target the last one well, for it is inheriting the style of the first. I am looking for two selectors that match these cases without any particular order in the style sheet.
Here is a simple solution with CSS variables. Check the following question for more details: CSS scoped custom property ignored when used to calculate variable in outer scope
* {
margin: 0.2em 0;
width: fit-content;
}
div {
margin-left: 1em
}
p {
background: var(--c);
}
.cyan {
--c:cyan;
}
.orange {
--c:orange;
}
<div class="orange">
<p>Orange</p>
<div>
<p>Orange</p>
<div>
<p>Orange</p>
<div class="cyan">
<p>Cyan</p>
<div>
<p>Cyan</p>
</div>
</div>
</div>
</div>
</div>
<div class="cyan">
<p>Cyan</p>
<div>
<p>Cyan</p>
<div>
<p>Cyan</p>
<div class="orange">
<p>Orange</p>
<div>
<p>Orange</p>
</div>
</div>
</div>
</div>
</div>
You can scale it to any number of coloration as you only need one selector per color and the order doesn't matter:
* {
margin: 0.2em 0;
width: fit-content;
}
div {
margin-left: 1em
}
p {
background: var(--c);
}
.cyan {
--c:cyan;
}
.orange {
--c:orange;
}
.blue {
--c:lightblue;
}
<div class="orange">
<p>Orange</p>
<div>
<p>Orange</p>
<div>
<p>Orange</p>
<div class="cyan">
<p>Cyan</p>
<div class="blue">
<p>Blue</p>
</div>
</div>
</div>
</div>
</div>
<div class="cyan">
<p>Cyan</p>
<div class="blue">
<p>Blue</p>
<div>
<p>Blue</p>
<div class="orange">
<p>Orange</p>
<div>
<p>Orange</p>
</div>
</div>
</div>
</div>
</div>
You cannot achieve what you want, because this is not how CSS works. Both of your statement will have the same specificity, so CSS determines which rule will win according to the order in the CSS file. For the inner styles, you will need to have a statement which has a greater specificity. This can either be achieved with listing all combinations of classes or by e.g. using the child-selector (>).
I thought, I'd share an improvement to your solution. It still uses 4 CSS statements (for 2 colors) but it does not require you to write down all possible combinations (in case of more than 2 classes, it is less effort; see the example below).
First, you colorize any child <p> of a cyan element with the color cyan. Then, you overwrite this behavior with the child-selector which targets only direct children of your element. .orange > p then overwrites .cyan p. The same goes with orange/cyan.
* { font-family: sans-serif; }
.cyan p {
background: cyan;
}
.orange p {
background: orange;
}
.red p {
background: red;
}
.cyan > p {
background: cyan;
}
.orange > p {
background: orange;
}
.red > p {
background: red;
}
<ul>
<li class="orange">
<ul>
<li class="cyan"><p>.orange >> .cyan</p></li>
<li class="red"><p>.orange >> red</p></li>
<li><p>.orange >> –</p></li>
</ul>
</li>
<li class="cyan">
<ul>
<li class="orange"><p>.cyan >> .orange</p></li>
<li class="red"><p>.cyan >> .red</p></li>
<li><p>.cyan >> –</p></li>
</ul>
</li>
<li class="red">
<ul>
<li class="orange"><p>red >> orange</p></li>
<li class="cyan"><p>red >> cyan</p></li>
<li><p>.red >> –</p></li>
</ul>
</li>
</ul>

Force text over 2 lines with CSS

I'd like to have all surnames on the second line AND maintain the exact same width for test div. What is the best way of achieving this with CSS?
HTML:
<div class="test">
<h1>Mike S</h1>
</div>
<div class="test">
<h1>Mike Smith</h1>
</div>
<div class="test">
<h1>Mike Smiths</h1>
</div>
CSS:
.test {width:25%;float:left;background:red;margin-right:20px}
h1 {text-align:center}
http://jsfiddle.net/zcg9k5xh/
Update your code with this:
.test {width:25%;float:left;background:red;margin-right:20px}
h1 {text-align:center}
h1 span{display: block;}
<div class="test">
<h1>Mike <span>S</span></h1>
</div>
<div class="test">
<h1>Mike <span>Smith</span></h1>
</div>
<div class="test">
<h1>Mike <span>Smiths</span></h1>
</div>
You can also do this by using css, update above css
h1 span{display: list-item;list-style:none;}
jsfiddle with this
http://jsfiddle.net/zcg9k5xh/2/
Given that it seems you are willing to change your HTML, I would recommend you simply add <br> after the first name, instead of wrapping the last name in any other tags. This would be deemed best practice.
The HTML <br> Element (or HTML Line Break Element) produces a line
break in text
This will give more semantic HTML- without the need to adjust native element styling, or clutter your DOM with uneccessary nodes.
.test {
width: 25%;
float: left;
background: red;
margin-right: 20px
}
h1 {
text-align: center
}
<div class="test">
<h1>Mike<br>S</h1>
</div>
<div class="test">
<h1>Mike<br>Smith</h1>
</div>
<div class="test">
<h1>Mike<br>Smiths</h1>
</div>
Use the word-spacing attribute to the child tag:
.test {
width: 25%;
float: left;
background: red;
margin-right: 20px
}
h1 {
background-color: blue;
word-spacing: 100px;
}
<div class="test">
<h1>Mike S</h1>
</div>
<div class="test">
<h1>Mike Smith</h1>
</div>
<div class="test">
<h1>Mike Smiths</h1>
</div>
I don't see what you are asking, it seems like the jsfiddle is what you are asking here.
But you can always set width to 100% so it cover for the text, if you want all that text in the same div then put it all under one Div tag.
Is this what you want?
.test {width:25%;float:left;background:red;margin-right:20px}
h1 {text-align:center}
<div class="test">
<h1>Mike</h1>
<h1>S</h1>
</div>
<div class="test">
<h1>Mike</h1>
<h1>Smith</h1>
</div>
<div class="test">
<h1>Mike</h1>
<h1>Smiths</h1>
</div>

:hover command won't work with a general sibling selector

I am trying to have a display that changes when hovering a div class. The idea is to have one div disappear when hovering another. I have tried using general sibling selectors to make the display change from inline to none. The CSS is as follows:
#Inicio {width: 100%;
height: 100%;
background-color: yellow;
position: absolute;
display: inline;
}
.buttons:hover ~ #Inicio {display: none;}
.buttons {width: 80%;
margin-left: auto;
margin-right: auto;
position: static;
margin-left: 10%;
font-size: 22px;
border-top: 1px solid white;
padding-top: 20px;
padding-bottom: 20px; }
.buttons:hover {font-size: 24px;
transition: all .5s ;}
And the HTML:
<div id="wrapper">
<div id="menubar">
<div id="menu">
<h1>Menu</h1>
</div>
<div class="buttons">
Inicio
</div>
<div class="buttons">
Productos
</div>
<div class="buttons">
Localizacion
</div>
<div class="buttons">
El equipo
</div>
<div class="buttons">
Ideas
</div>
<div class="buttons">
La pagina
</div>
</div>
<div id="content">
<div id="inicio"></div>
</div>
</div>
First of all, your id names doesn't match, its case sensitive, you #inicio and #Inicio are completely two different things..
And as I commented, the issue is that you cannot pop out of the element using CSS means you cannot select the parent element and than go ahead and select the parents sibling element, so you need to change your DOM, you are trying to select an element which is adjacent to the buttons parent element and not the button itself, so the best you can do is this
.buttons:hover ~ #content > #inicio {
display: none;
}
Demo
Altered DOM, you need to bring the elements on the same level, if #inicio is nested, it's fine, but to select it's parent, bring the elements adjacent to each other on the same level so that all are direct child to an element having an id of #wrapper
<div id="wrapper">
<div id="menu">
<h1>Menu</h1>
</div>
<div class="buttons">
Inicio
</div>
<div class="buttons">
Productos
</div>
<div id="content">
<div id="inicio">Disappear this</div>
</div>
</div>
As #enguerranws commented, I thought to put a compatibility table as well,
Credits - Support Table
Maybe because it's #inicio, not #Inicio ?
Then you need to change your DOM. You have to put #inicio in .buttons div. Or :
.buttons:hover ~ #Inicio
Won't work.
<div id="wrapper">
<div id="menubar">
<div id="menu">
<h1>Menu</h1>
</div>
<div class="buttons">
<span>Inicio</span>
<div id="inicio"></div>
</div>
</div>
<div id="content">
</div>
</div>
You should use that structure. Btw, I added a span to wrap your text, as it's not valid to put text directly in block element (here: div).

How can I select the last element with a specific class, not last child inside of parent?

<div class="commentList">
<article class="comment " id="com21"></article>
<article class="comment " id="com20"></article>
<article class="comment " id="com19"></article>
<div class="something"> hello </div>
</div>
I want to select #com19 ?
.comment {
width:470px;
border-bottom:1px dotted #f0f0f0;
margin-bottom:10px;
}
.comment:last-child {
border-bottom:none;
margin-bottom:0;
}
That does not work as long as I do have another div.something as actual last child in the commentList. Is it possible to use the last-child selector in this case to select the last appearance of article.comment?
jsFiddle
:last-child only works when the element in question is the last child of the container, not the last of a specific type of element. For that, you want :last-of-type
http://jsfiddle.net/C23g6/3/
As per #BoltClock's comment, this is only checking for the last article element, not the last element with the class of .comment.
body {
background: black;
}
.comment {
width: 470px;
border-bottom: 1px dotted #f0f0f0;
margin-bottom: 10px;
}
.comment:last-of-type {
border-bottom: none;
margin-bottom: 0;
}
<div class="commentList">
<article class="comment " id="com21"></article>
<article class="comment " id="com20"></article>
<article class="comment " id="com19"></article>
<div class="something"> hello </div>
</div>
I guess that the most correct answer is: Use :nth-child (or, in this specific case, its counterpart :nth-last-child). Most only know this selector by its first argument to grab a range of items based on a calculation with n, but it can also take a second argument "of [any CSS selector]".
Your scenario could be solved with this selector: .commentList .comment:nth-last-child(1 of .comment)
But being technically correct doesn't mean you can use it, though, because this selector is as of now only implemented in Safari.
For further reading:
https://drafts.csswg.org/selectors-4/#the-nth-child-pseudo
http://caniuse.com/#search=nth-child
If you are floating the elements you can reverse the order
i.e. float: right; instead of float: left;
And then use this method to select the first-child of a class.
/* 1: Apply style to ALL instances */
#header .some-class {
padding-right: 0;
}
/* 2: Remove style from ALL instances except FIRST instance */
#header .some-class~.some-class {
padding-right: 20px;
}
This is actually applying the class to the LAST instance only because it's now in reversed order.
Here is a working example for you:
<!doctype html>
<head><title>CSS Test</title>
<style type="text/css">
.some-class { margin: 0; padding: 0 20px; list-style-type: square; }
.lfloat { float: left; display: block; }
.rfloat { float: right; display: block; }
/* apply style to last instance only */
#header .some-class {
border: 1px solid red;
padding-right: 0;
}
#header .some-class~.some-class {
border: 0;
padding-right: 20px;
}
</style>
</head>
<body>
<div id="header">
<img src="some_image" title="Logo" class="lfloat no-border"/>
<ul class="some-class rfloat">
<li>List 1-1</li>
<li>List 1-2</li>
<li>List 1-3</li>
</ul>
<ul class="some-class rfloat">
<li>List 2-1</li>
<li>List 2-2</li>
<li>List 2-3</li>
</ul>
<ul class="some-class rfloat">
<li>List 3-1</li>
<li>List 3-2</li>
<li>List 3-3</li>
</ul>
<img src="some_other_img" title="Icon" class="rfloat no-border"/>
</div>
</body>
</html>
Something that I think should be commented here that worked for me:
Use :last-child multiple times in the places needed so that it always gets the last of the last.
Take this for example:
.page.one .page-container .comment:last-child {
color: red;
}
.page.two .page-container:last-child .comment:last-child {
color: blue;
}
<p> When you use .comment:last-child </p>
<p> you only get the last comment in both parents </p>
<div class="page one">
<div class="page-container">
<p class="comment"> Something </p>
<p class="comment"> Something </p>
</div>
<div class="page-container">
<p class="comment"> Something </p>
<p class="comment"> Something </p>
</div>
</div>
<p> When you use .page-container:last-child .comment:last-child </p>
<p> you get the last page-container's, last comment </p>
<div class="page two">
<div class="page-container">
<p class="comment"> Something </p>
<p class="comment"> Something </p>
</div>
<div class="page-container">
<p class="comment"> Something </p>
<p class="comment"> Something </p>
</div>
</div>
The new :has() pseudo class (not yet supported by all browsers) lets you get pretty close to a solution:
.class:has(+ :not(.class))
The limitation is that this will find any element with .class which is followed by an element that doesn't have this class. But this would match the use case of the question.
What about this solution?
div.commentList > article.comment:not(:last-child):last-of-type
{
color:red; /*or whatever...*/
}
This can now be solved with careful use of :has(), specifically:
/* switch out the {class} below */
.{class}:not(:has(~ .{class}))
A similar technique also allows you to select anything but the last occurrence of a class in a container, or the last occurrence within a group of elements. See the snippet below for examples.
Note: has() is currently supported in Chrome, Edge and Safari, but not Firefox (Jan 2022)
/* last in group */
.class:has(+ :not(.class)) {
background: pink;
}
/* anything but last in container */
.class:has(~ .class) {
box-shadow: 0 0 0 1px #F00A;
}
/* last in container */
.class:not(:has(~ .class)) {
background: #0F0A;
}
<div>
<div class="class">not-last</div>
<div class="class">not-last</div>
<div class="class">last-in-group</div>
<div>---</div>
<div class="class">not-last</div>
<div class="class">last-in-group</div>
<div>---</div>
<div class="class">last-class</div>
<div>---</div>
</div>
There are two ways to select the last element of a class.
Wrap your elements in a container element.
html:
<div class="container">
<div class="member">Member</div>
<div class="member">Member</div>
<div class="member">Member</div>
<div>
css:
.container:last-child {
color: red;
}
If you don't want to wrap your elements within another element then you can leverage last-of-type.
html:
<div class="member">Member</div>
<div class="member">Member</div>
<div class="member">Member</div>
css:
.member:last-of-type{
color: red;
}