CSS general sibling combinator (ie ~) - css

I am trying to understand why the following example does not behave as expected. I have a style that selects general siblings, but I also have children which I would not expect to be selected, but occasionally are. Here is a minimal example that illustrates the problem.
The first div>div.h is a descendant, and the ~ does NOT match it. The second p>div.h is clearly a descendant, but the ~ selector DOES match it. I tried in Chrome,Safari and Firefox, all behave the same. I must be missing something. Is p "special"?
<html>
<head>
<style>
.anchor ~ .h { color: orange }
.anchor2 ~ .h { color: blue }
</style>
</head>
<body>
<div>
<div class="h">black 1</div>
<div class="h">black 2</div>
<p class="anchor">the anchor</p>
<div class="h">orange 1</div>
<div>
<div class="h">should be black</div>
</div>
<p>
<div class="h">why isn't this black</div>
</p>
<div class="h">orange 2</div>
<p class="anchor2">anchor2</p>
<div class="h">blue 1</div>
<div class="h">blue 2</div>
</div>
</body>
</html>

<div> elements are not valid children of <p>.
Your browser corrects your errors (takes your <div> and places it after <p> instead of inside it) and by doing so, makes div.h a sibling of .anchor:
Now, if you use inline elements in your paragraphs, the browser doesn't correct your markup and you get your expected result:
.anchor ~ .h {
color: orange
}
.anchor2 ~ .h {
color: blue
}
<div>
<div class="h">black 1</div>
<div class="h">black 2</div>
<p class="anchor">the anchor</p>
<div class="h">orange 1</div>
<div>
<span class="h">should be black</span>
</div>
<p>
<span class="h">why isn't this black</span>
</p>
<div class="h">orange 2</div>
<p class="anchor2">anchor2</p>
<div class="h">blue 1</div>
<div class="h">blue 2</div>
</div>

Related

css/sass :not(:first-of-type) not working, is hiding all elements of type

I have a sass block that i have tried several different ways:
I've tried this:
.progress-body {
display: none;
&:first-of-type {
display: block;
}
}
and this:
.progress-body {
&:not(:first-of-type) {
display: none;
}
}
and this:
.progress-body:not(:first-of-type) {
display: none;
}
when applied to HTML that looks like this:
<div class="panel">
<div class="panel-heading">
</div>
<div class="panel-body progress-body">
<div class="row">
<div class="col-md-12">
<p class="lead">Step 1: Choose your template...</p>
</div>
</div>
</div>
<div class="panel-body progress-body">
<div class="row">
<div class="col-md-12">
<p class="lead">Step 2: Compose your email...</p>
</div>
</div>
</div>
</div>
the result is that it hides all the elements with the progress-body class. This is normally pretty straight forward CSS so no idea what is wrong here...
In this case progress-body is not the first-of-type, this would technically be .panel-heading since the first-of-type refers to the type element selector (div) and not the class.
The :first-of-type CSS pseudo-class represents the first element of
its type among a group of sibling elements.
Ref: :first-of-type - CSS | MDN
Consider wrapping your .progress-body elements in a containing element, you will achieve the expected behaviour, since .progress-body would be the first of its type with the class name .progress-body.
Code Snippet Demonstration:
.progress-body:not(:first-of-type) {
display: none;
}
<div class="panel">
<div class="panel-heading">
</div>
<div class="panel-outer-body">
<div class="panel-body progress-body">
<div class="row">
<div class="col-md-12">
<p class="lead">Step 1: Choose your template...</p>
</div>
</div>
</div>
<div class="panel-body progress-body">
<div class="row">
<div class="col-md-12">
<p class="lead">Step 2: Compose your email...</p>
</div>
</div>
</div>
</div>
</div>
If you can't wrap as UncaughtTypeError wrote in his answer, youcan use (general) sibling selectors.
.progress-body + .progress-body {display: none;}
or
.progress-body ~ .progress-body {display: none;}
I expect the first is block by default, if you didn't change it elsewhere.

CSS: Change child on parent hover (only single child)

I can change child on parent hover like this:
.parent:hover .child{ ... }
Problem is, that this will change all childs in document.
(I'm using parent 10x on the page => it will change childs in all these parent)
Is there a CSS way, how to change only child of the parent, that I'm currently hovering over?
Example:
<div class="parent">
<p class="child"></p>
</div>
<div class="parent">
<p class="child"></p>
</div>
<div class="parent">
<p class="child"></p>
</div>
If I hover over first .parent, I want change on its .child. But my mentioned solution will affect all childs.
You'll want to directly select the child using the ">" or the "adjacent sibling combinator"
.parent:hover > .child{
background: red;
}
<div class="parent">
<p class="child">child one</p>
</div>
<div class="parent">
<p class="child">child two</p>
</div>
<div class="parent">
<p class="child">child three</p>
</div>

How to apply style to first div after h2 in css?

I want to apply the first div color as red. other div as default.
I tried this but not working.
.community_team:first-child + div{
color:red;
}
Actual html below
<div class="community_team">
<h2>Managers</h2>
<div class="comm_team_item clearfix">
First Mangaer
<div>
<div class="comm_team_item clearfix">
2nd Mangaer
<div>
<div class="comm_team_item clearfix">
3rd Mangaer
<div>
</div>
Use the first-of-type pseudo selector. In the example below, this will match the first div element that is a child of .community_team.
Also your div elements aren't closed. Change <div> to </div> to close.
.community_team div:first-of-type {
color: red;
}
<div class="community_team">
<h2>Managers</h2>
<div class="comm_team_item clearfix">
First Mangaer
</div>
<div class="comm_team_item clearfix">
2nd Mangaer
</div>
<div class="comm_team_item clearfix">
3rd Mangaer
</div>
</div>
Also you can use the adjacent sibling combinator to target the first div after the h2 that is within .community-team. If there should ever be an instance where you may have a div prior to your h2 but you still want to target the first div after the h2.
.community_team h2 + div {
color: red;
}
<div class="community_team">
<div>This div is prior to the h2</div>
<h2>Managers</h2>
<div class="comm_team_item clearfix">
First Mangaer
</div>
<div class="comm_team_item clearfix">
2nd Mangaer
</div>
<div class="comm_team_item clearfix">
3rd Mangaer
</div>
</div>

CSS :not() selector. Apply style if parent does not exist

I am trying to apply a style to a div based on its parent class. I am using the :not() selector to select the div whose parent is not .container1, the second div should be red, but it's not working.
Example 1
.myDiv:not(.container1) > .myDiv {
color: red;
}
<div class="container1">
<div class="myDiv">Div 1</div>
</div>
<div class="container2">
<div class="myDiv">Div 2</div>
</div>
Example 2
.myDiv:not(.container1 .myDiv) {
color: red;
}
<div class="container1">
<div class="myDiv">Div 1</div>
</div>
<div class="container2">
<div class="myDiv">Div 2</div>
</div>
Is this even possible with CSS? Or is my syntax just off?
You're selecting wrong elements. No reverse lookups possible, see here:
div:not(.container1) > .myDiv {
color: red;
}
<div class="container1">
<div class="myDiv">Div 1</div>
</div>
<div class="container2">
<div class="myDiv">Div 2</div>
</div>
Ideally, you'd group those parent divs under the same class in order to avoid the super-generic div selector:
.container:not(.container1) > .myDiv {
color: red;
}
<div class="container container1">
<div class="myDiv">Div 1</div>
</div>
<div class="container container2">
<div class="myDiv">Div 2</div>
</div>
CSS can't do "parent lookups" like that. You would need to reverse the structure to something like:
.my-container:not(.container1) .myDiv
Granted, you would need to add the shared my-container class to all "parent" divs of interest.

Select all but first element using CSS3

I need to select all headers but the first
<div class="block">
<div class="header">first</div>
</div>
<div class="block">
<div class="header">second</div>
</div>
<div class="block">
<div class="header">third</div>
</div>
<div class="block">
<div class="header">fourth</div>
</div>
Using jquery I would do this $(".header:not(:first)"), I'm however restricted to CSS/CSS3. I cannot tag the elements other than in my example.
Using .header:not(:first-child) wont do the trick
The .header elements are not siblings, therefore you should probably select all but the first .block element, then select the descendant .header from there:
.block:not(:first-child) .header {}
Depending on your markup, you may also want to negate the first of type if the element's types differ:
.block:not(:first-of-type) .header {}
.block:not(:first-child) .header {
color: #f00;
}
<div class="block">
<div class="header">first</div>
</div>
<div class="block">
<div class="header">second</div>
</div>
<div class="block">
<div class="header">third</div>
</div>
<div class="block">
<div class="header">fourth</div>
</div>
As David Thomas points out, you can also use the adjacent sibling combinator, + or the general sibling combinator, ~ in order to select all following siblings:
.block ~ .block .header {}
or:
.block + .block .header {}
.block + .block .header {
color: #f00;
}
<div class="block">
<div class="header">first</div>
</div>
<div class="block">
<div class="header">second</div>
</div>
<div class="block">
<div class="header">third</div>
</div>
<div class="block">
<div class="header">fourth</div>
</div>

Resources