CSS Rule exclude parent class - css

How can I write a CSS Rule that selects all div.box that are not inside .container?
The following snippet is not working because there is a div without .container inside the div.container.
div:not(.container) .box {
background:red;
}
<div class="box">box</div> <!-- select this -->
<div class="container">
<div>txt</div>
<div><div class="box">box</div></div>
</div>
<div class="box">box</div> <!-- select this -->

If you do not want to override every attribute, the only way I see is to give an additional class to the boxes inside of the specific container.
.box:not(.exclude) {
background: red;
}
<div class="box">box</div> <!-- select this -->
<div class="container">
<div>txt</div>
<div><div class="box exclude">box</div></div>
</div>
<div class="box">box</div> <!-- select this -->

In a way, the CSS rule you are asking for is sort of backwards. You should start with the most generic rules, and then add more specific ones. In your case, you should do something like the following:
/* Generic Box styles */
.box
{
border: 1px solid black;
}
/* Boxes in a container */
.container .box
{
color: blue;
}
<div class="box">Generic Box</div>
<div class="container">
<div class="box">I'm in a container</div>
</div>

Select all div.box or all div not inside .container? What you ask for and what you say you want selected in the html code sample are not the same thing. That said, your css selectors are just out of order. Try:
div.box:not(.container) {
background:red;
}
and
<div class="box">box</div>
<div class="container">
<div>txt</div>
<div><div class="box">box</div></div>
</div>
<div class="box">box</div>
If you want all the divs, just remove the .box

Related

Show/hide sibling div based on content

Hello – I would like to show content in a div based on the content in another div. For example, if sibling1 is empty, I would like to hide sibling2 (in parent1 below). If sibling1 has content, I would like to show sibling2 (parent2 below). I'd prefer to be able to do this with CSS, is this possible? If not, I can work with a simple javascript suggestion as well.
<!---hide sibling2--->
<div class="parent1">
<div class="sibling1"></div>
<div class="sibling2">hide</div>
</div>
<!---show sibling2--->
<div class="parent2">
<div class="sibling1">has content</div>
<div class="sibling2">show</div>
</div>
.parent {
height: 100px;
border: 1px solid;
}
.sibling1 { background: green; }
.sibling2 { background: red; }
.sibling1:empty + .sibling2 { display: none; }
<!---hide sibling2--->
<div class="parent">
<div class="sibling1"></div>
<div class="sibling2">hide</div>
</div>
<!---show sibling2--->
<div class="parent">
<div class="sibling1">has content</div>
<div class="sibling2">show</div>
</div>

Is it possible to have scss selector that selects class only if it is last child of other element?

I have layout that is generated dynamically so order of elements could change. Each element that is part of this layout has its own different class. I want to be able to select element of certain class but only if it is last child of its parent to apply styling. If element with different class is last child of its parent, it should not be selected. Is it possible to have this kind of scss selector and achieve this functionality without using javascript?
Example:
<div class="parent">
<div class="child1">Hello!</div>
<div class="child2">Hello!</div>
<div class="child3">Hello!</div>
</div>
I want to select element with class child3 only if it is last child of div with class parent.
So if child2 class element is last child of div class parent it is not selected, for example here:
<div class="parent">
<div class="child1">Hello!</div>
<div class="child3">Hello!</div>
<div class="child2">Hello!</div>
</div>
Yes, and this is the normal CSS behaviour. You can do something like this:
.parent .child3:last-child {}
This is a rule that selects:
a .child3 element inside .parent.
.child3 element comes as the last, there's no other elements after that including text.
For SCSS, you can do something like this:
.parent {
.child3 {
&:last-child {
// Rules.
}
}
}
Example Snippet
.parent .child3:last-child {
background: #ccf;
}
<strong>Trial 1</strong>
<div class="parent">
<div class="child1">Hello!</div>
<div class="child2">Hello!</div>
<div class="child3">Hello!</div>
</div>
<hr />
<strong>Trial 2</strong>
<div class="parent">
<div class="child1">Hello!</div>
<div class="child3">Hello!</div>
<div class="child2">Hello!</div>
</div>
Preview
You can select elements by their attributes, so something like this would achieve your goal.
.parent div {
width: 50px;
height: 50px;
background-color: blue;
border: solid 1px black;
}
.parent div:last-of-type[class="child3"] {
background-color: red;
}
<div class="parent">
<div class="child1">Hello!</div>
<div class="child3">Hello!</div>
<div class="child2">Hello!</div>
</div>
<div class="parent">
<div class="child1">Hello!</div>
<div class="child2">Hello!</div>
<div class="child3">Hello!</div>
</div>
https://www.w3schools.com/cssref/css_selectors.asp

can not exclude class from css * selector

I want to apply a style on all children of a class except .fixedsize children:
.inner *:not(.fixedsize){
max-width:100%
}
.fixedsize > *{
max-width:none
}
<div class="inner">
<div>
<div id="map" class="fixedsize">
inspect the map here
<div id="childOfMap">inspect the child of map here</div>
</div>
</div>
</div>
It seems not working. How can I exclude it and all of its children from * selector?
Edit:
When I inspect the main element (map) in stackoverflow snippet it has no max-width:100% and this is ok. But in runtime and perhaps a more complex codes when I inspect the map, It has max-width:100% calculated from this * selector.
The issue is that the :not() selector is more specific, so you need to increase the specifity of the other selector or use !important
.inner *:not(.fixedsize) {
border:1px solid red;
}
/*Adding not() will make the specifity of this one higher*/
.fixedsize *:not(#randomId) {
border:none;
}
<div class="inner">
<div>
<div id="map" class="fixedsize">
no border
<div id="childOfMap">no border <span>here also</span></div>
</div>
<div>Content</div>
</div>
<div>some other content<span>here</span></div>
</div>
With !important:
.inner *:not(.fixedsize) {
border:1px solid red;
}
.fixedsize * {
border:none!important;
}
<div class="inner">
<div>
<div id="map" class="fixedsize">
no border
<div id="childOfMap">no border <span>here also</span></div>
</div>
<div>Content</div>
</div>
<div>some other content<span>here</span></div>
</div>

Complex css to only select first instance of an element

I need to be able to apply a width to a div but only if any of it's parents have a class of grid.
Obviously the child selector allows me to select an element if it's a direct child of the grid div:
.grid > .test {
width: 300px;
}
<div class="grid">
<div class="test"></div>
</div>
I need a selector that allows me to select the .test div even if its not the direct child of grid:
<div class="grid">
<div class="another">
<div class="test"></div>
</div>
</div>
You'd imagine that I could just use a bog-standard selector like:
.grid .test
Problem with this is that I only want to match the first instance of the .test div. The above selector matches all instances even if they're nested. Any subsequent div's with a class of test should be ignored.
<div class="grid">
<div class="another">
<div class="test">
<div class="test"></div> <!-- this should be ignored somehow -->
</div>
</div>
</div>
http://jsfiddle.net/hs3G9/1/
Is there any way to do this with css or do I need to resort to JS?
There isn’t a way of excluding that inner .test element without JavaScript. If the two had been siblings, you could do something like:
.grid .test:first-of-type {}
edit: Right you are; you can cook something up with the :not selector.
Using the :first-child selector in css should work.
So for you case:
<style>
.grid .test:first-child {
background-color: rgba(0,0,0,.2);
}
</style>
<div class="grid">
<div class="another">
<div class="test">
<div class="test"></div> <!-- this should be ignored somehow -->
</div>
</div>
</div>

:first-child fails when an element of a different class is dynamically inserted above

So, I've encountered a situation where inserting an element of a different class/id breaks all css-rules on that :first-child.
<div id="nav">
<div class="nSub">abcdef</div>
<div class="nSub">abcdef</div>
<div class="nSub">abcdef</div>
<div class="nSub">abcdef</div>
<div class="nSub">abcdef</div>
</div>
.nSub:first-child { margin-top:15px; -moz-border-radius-topleft:5px; /* ... */ }
.nSub { background:#666; /* ... */ }
.nSub:last-child { -moz-border-radius-bottomleft:5px; /* ... */ }
As soon as I insert an element of another class/id above, like this:
$('nav').insert({top:'<div id="newWF"></div>'});
all declarations for .nSub:first-child are being ignored in both FF 3.6 and Safari 4.
EDIT:
sorry if I did not say it clearly: the element inserted above is supposed to NOT have the classname ".nSub"
<div id="nav">
<div id="newWF"></div>
<div class="nSub">abcdef</div> <!-- BROKEN CSS -->
<div class="nSub">abcdef</div>
<div class="nSub">abcdef</div>
<div class="nSub">abcdef</div>
<div class="nSub">abcdef</div>
</div>
That's because the first element with class nSub is no longer the first-child of the parent, and thus the style no longer matches.
If the dynamically inserted element would also have class nSub, then the rule would still match, and match for the newly inserted element (which is now the first child).
I'm no CSS3 expert, but you could try the :nth-of-type selector:
.nSub:nth-of-type(1) {
/* Rules for the first .nSub here */
}
This is because, you don't set the class for this inserted element, I guess...
In you CSS-File you say ".nSub:first-child", but the element you are inserting is not of that class: "
Maybe it helps, if you add the class-attribute to that element, too:
$('nav').insert({top:'<div id="newWF" class="nSub"></div>'});
What PatrikAkerstrand said about the rule no longer matching is correct. The :first-child pseudo (unfortunately) only targets the first child of its parent that also has the element/class/whatever you specified.
I just spent half an hour cursing at why the following wouldn't work
<div id="header">
<img src="path/file.png" />
<div class="img"></div>
<div class="img"></div>
<div class="img"></div>
</div>
#header .img {
margin:0 25px;
}
#header .img:first-child,
#header .img:last-child {
margin:0;
}
I found that the solution were to wrap the div.img's into a div.images, like this
<div id="header">
<img src="path/file.png" />
<div class="images">
<div class="img"></div>
<div class="img"></div>
<div class="img"></div>
</div>
</div>
#header .images .img {
margin:0 25px;
}
#header .images .img:first-child,
#header .images .img:last-child {
margin:0;
}
Edit: If you don't want to add non-semantic workaround markup, you can use the :first-of-type pseudo-class. This, however, is not supported in earlier versions of IE.

Resources