I'm trying to style all div elements except those in two different class groups. Everything I've tried doesn't seem to work.
The below test code should make the div with "test" text content be orange, but none of the selectors work.
div {
height: 40px;
width: 100px;
background: cyan;
display: inline-block;
}
div:not(.ZoomBar):not(.row.heading) {
background: orange;
}
div:not(.ZoomBar, .row.heading) {
background: orange;
}
div:not(.ZoomBar),
div:not(.row.heading) {
background: orange;
}
<div class="ZoomBar">ZoomBar</div>
<div class="row heading">Heading</div>
<div>Test</div>
You can use something like this
You cannot add unfortunately multiple class in a single not selector.
div {
height: 40px;
width: 100px;
background: cyan;
display: inline-block;
}
div:not(.ZoomBar):not([class="row heading"]){
background: orange;
}
<div class="ZoomBar">ZoomBar</div>
<div class="row heading">Heading</div>
<div class="heading">Heading</div>
<div>Test</div>
The problem with :not() is that it only allows one simple selector at a time. This means any of :not(div), :not(.ZoomBar), :not(.row) and/or :not(.heading). It does not accept either
a compound selector, .row.heading, which consists of two class selectors; or
a comma-separated list of multiple selectors, .ZoomBar, .row.heading.
It's worth noting however that the selectors you've tried will work in jQuery, though not CSS.
Your problem is compounded (heh) by the fact that you're looking for both kinds of exclusions in a single rule. But it's still doable; it simply means you'll need to write a slightly more convoluted rule, with two selectors to account for the two class selectors in .row.heading:
div {
height: 40px;
width: 100px;
background: cyan;
display: inline-block;
}
div:not(.ZoomBar):not(.row),
div:not(.ZoomBar):not(.heading) {
background: orange;
}
<div class="ZoomBar">ZoomBar</div>
<div class="row heading">Heading</div>
<div class="heading row">Heading</div>
<div class="heading foo row">Heading</div>
<div class="heading">Heading</div>
<div>Test</div>
If these are the only possible combinations of class names, you might be able to get away with simply excluding div elements with a class attribute using div:not([class]), but based on your question I suspect that this isn't the case.
For instance, notice in the above snippet that the div[class="heading"] element matches div:not(.ZoomBar):not(.row), and is therefore colored orange. If you may have elements with either class name but not both, those elements will be accounted for.
The answer is this:
div {
height: 40px;
width: 100px;
background: cyan;
display: inline-block;
}
div:not([class*="ZoomBar"]):not([class*="row heading"]):not([class*="heading row"]) {
background: orange;
}
https://jsfiddle.net/ars9fL56/5/
Related
When the .post-item <div> is hovered I want to execute some specific styles (change background-color and cursor) but I don't want this to happen if the .rating-wrapper <div> is hovered too. This happens because I want the .rating-wrapper to do something different than the hover of its parent. Basic question: How to do only child's hover, ignoring the parent's hover
HTML:
<div class="post-item">
<div class="rating-wrapper">
<div class="upvote">
<img src="/images/upvote_arrow.png" alt="upvote" />
</div>
<div class="rating"></div>
<div class="downvote">
<img src="/images/downvote_arrow.png" alt="downvote" />
</div>
</div>
<span class="owner-data">
<img src="" alt="" class="owner-avatar" />
<span class="owner-username"></span>
</span>
<span class="creation-date"></span>
<div class="title"></div>
</div>
Since you want to change the style of the parent element based on a pseudo-class of the child element, this isn't really possible with CSS alone today.
You can do it with the :has() pseudo-class but that is currently only supported in Safari (with support for Chrome a few months away and no sign of it in Firefox, Edge, Opera or elsewhere).
#parent {
background: white;
border: solid black 1px;
padding: 2em;
max-width: 50%;
margin: auto;
}
#parent:hover:not(:has(#child:hover)) {
background: orange;
}
#child {
background: #aaa;
border: solid black 1px;
padding: 2em;
}
#child:hover {
background: green;
}
<div id="parent">
<div id="child"></div>
</div>
For a more reliable approach, you should probably look at adding a splash of JavaScript to the mix.
Use mouseenter and mouseleave events to modify the classes of the parent element, then reference the class in your stylesheet.
const parent = document.querySelector('#parent');
const child = document.querySelector('#child');
const enter = event => parent.classList.add('child-hover');
const leave = event => parent.classList.remove('child-hover');
child.addEventListener('mouseenter', enter);
child.addEventListener('mouseleave', leave);
#parent {
background: white;
border: solid black 1px;
padding: 2em;
max-width: 50%;
margin: auto;
}
#parent:hover:not(.child-hover) {
background: orange;
}
#child {
background: #aaa;
border: solid black 1px;
padding: 2em;
}
#child:hover {
background: green;
}
<div id="parent">
<div id="child"></div>
</div>
You can use this CSS Selector,
.post-item>:not(.rating-wrapper):hover {
background-color: white;
}
This will select all immediate children of .post-item which are not .rating-wrapper.
To change the block of the remaining items background color, you can enclose them in another div.
There is a css property called not property.The syntax is like:
:not(element) {
// CSS Property}
If you want to learn more, please visit this link:
https://www.geeksforgeeks.org/how-to-exclude-particular-class-name-from-css-selector/
The pointer-events CSS property sets under what circumstances (if any) a particular graphic element can become the target of pointer events.
try:
pointer-events: none
you can read more here: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events
I'm still new to styling with CSS. Here is my situation, I have three elements I want to one style. But each one needs small adjustments. So I gave each element the class of plan-price and then I gave them each a unique second class. Then I'm trying to nest the second class within the first. But that approach is not working. I'll show my code for clarity.
HTML
<div class="price-plans private-eye">
<p>Select</p>
</div>
<div class="price-plans little-birdy">
<p>Select</p>
</div>
CSS
.plan-price {
float: right;
margin: 83px 20px 20px;
.private-eye {
margin: 40px;
}
.little-birdy {
margin: 50px;
}
}
As you can see my attempt is to nest the second class within the first. I realize now that this does not work. What is another way I can do this?
CSS by itself does not support nesting styles like this. You could just have the override styles after the "default" style and rely on the cascading nature of CSS to overwrite the margins.
.plan-price {
float: right;
margin: 83px 20px 20px;
}
.plan-price.private-eye {
margin: 40px;
}
.plan-price.little-birdy {
margin: 50px;
}
<div class="price-plans private-eye">
<p>Select
</p>
</div>
<div class="price-plans little-birdy">
<p>Select
</p>
</div>
To do nesting styles, take a look at a CSS pre-processor like LESS which lets you do exactly what you are after.
To differentiate the divs, give them id's. id = "whatever". Classes are used to make the divs have the same css styles when they are named the same class, but id's are used to style it individually. In your css file do #id { code }
<div id = "something" class="price-plans">
<p>Select</p>
</div>
<div id = "somethingElse" class="price-plans">
<p>Select</p>
</div>
#something{
code
}
#somethingElse{
code
}
.plan-price {
float: right;
margin: 83px 20px 20px;
}
.private-eye {
margin: 40px;
}
.little-birdy {
margin: 50px;
}
Asking here since I can't pass a proper search query with that.
Here's a code sample:
[class*="button_type"].state_2,
[class*="button_type"]:not(.state_2):hover{
background-color:#fff;
}
Furthermore what would be the use of the :not suffix?
I cannot understand why it isn't just:
.button_type.state_2,
.button_type:hover { etc..}
[class*="button_type"] is CSS class Selector (equivalent to CSS attribute selector) means that will select all elements whose class contains at least one substring "button_type".
take a look at this example:
[class*="button_type"] {
background: red;
width: 50px;
height: 50px;
display: inline-block
}
<div class="button_type"></div>
<span class="one_button_type"></span>
<article class="button_type_final"></article>
Regarding the :not() that means it will select everything but that selector which is inside the :not()
Take a look at this example:
[class*="button_type"] {
background: red;
width: 50px;
height: 50px;
display: inline-block
}
[class*="button_type"]:not(.state_2) {
border: black solid
}
<div class="button_type state_1"></div>
<span class="one_button_type state_2"></span>
<article class="button_type_final state_3"></article>
I made a quick template to explain what I am trying to achieve:
http://codepen.io/anon/pen/XJWrjO
As you can see, there is two classes ofelements. .one and .two
I want to group the following elements with each other via css. This will be a visual grouping; not a structural grouping.
Shortly, what I want to do is, to give margin-top to the first element for each class cluster, and margin-bottom to the last element of each cluster.
So, depending on my example here are the clusters:
1,2,3,4 - red cluster
5,6,7 - cyan cluster
8,9 - red cluster
10,11,12,13,14 - cyan cluster
15 - red cluster
16,17 - cyan cluster
So according to this structure, for instance, div5 would have a margin-top and div7 would have a margin-bottom.
Or, div5 would have a margin-top and div8 would have a margin-top (similar result with the previous statement)
Any kind of solution that allows visual grouping of the similar classed items that follow each other, is accepted.
No JS, only CSS.
Since you can't combine :last-child with .class selector, it's hard to assign margin-bottom to the last element of a cluster. But you can detect the switch to another cluster by using +:
.one + .two, .two + .one {
margin-top: 50px;
}
See the DEMO.
EDIT regarding comment asking for a general rule:
There's not a general rule like this I am aware of which would work right now, since CSS doesn't provide anything like :nth-of-class nor does it support back references to classes of previous selectors. So you can't do anything like
.{class-variable} + :not(.{class-variable})
but if you have a list of all possible classes, you could do something similar:
.one + :not(.one),
.two + :not(.two) {
margin-top: 50px;
}
You would need to repeat that for every class that is in the list. See DEMO 2 which has three different classes.
When generating the output, you would need to collect all classes in an array and could create an additional style element in your output to avoid to adapt your CSS every time. In PHP, this could look like
$style = '';
foreach ($classes AS $class) {
$style .= '.' . $class . ' + :not(.' . $class . '), ';
}
if ($style != '') {
$output = '<style>' . substr($style, 0, -2) . ' { margin-top: 50px; }</style>';
}
Just to show an alternative, you could order your clusters in the markup by assigning a data-cluster attribute:
<div class="two" data-cluster="red">6</div>
And then style it as you wish:
div[data-cluster="red"] {
background: red;
margin-top: 10px;
}
div[data-cluster="red"] + div[data-cluster="red"] {
margin-top: 0;
}
Demo
Just to supplement #Paul 's (excellent) answer, you could approach this problem the other way around by applying the top margin on all child elements, then override that margin when a child element is following by a child with the same class.
Like this:
div {
width: 100%;
margin: 2px;
margin-top: 50px;
}
.one + .one, .two + .two {
margin-top: 0;
}
UPDATED CODEPEN
One advantage of this approach is that the :not selector - which isn't supported by older browsers such as ie8 - isn't necessary.
Here's an example with 3 classes
div {
width: 100%;
margin: 2px;
margin-top: 50px;
}
.one + .one, .two + .two, .three + .three {
margin-top: 0;
}
CODEPEN 2
body {
padding: 64px;
margin: 0;
text-align: center;
font-size: 20px;
font-family: Arial;
line-height: 40px;
}
div {
width: 100%;
margin: 2px;
margin-top: 50px;
}
.one + .one,
.two + .two,
.three + .three {
margin-top: 0;
}
.one {
background-color: tomato;
}
.two {
background-color: aqua;
}
.three {
background-color: maroon;
}
<div class="one">1</div>
<div class="one">2</div>
<div class="three">3</div>
<div class="three">4</div>
<div class="two">5</div>
<div class="two">6</div>
<div class="two">7</div>
<div class="one">8</div>
<div class="one">9</div>
<div class="two">10</div>
<div class="two">11</div>
<div class="three">12</div>
<div class="three">13</div>
<div class="two">14</div>
<div class="one">15</div>
<div class="two">16</div>
<div class="two">17</div>
check it may be it helps you, what you achive :-
Demo
div:nth-child(1){margin-top:10px;color:green}
div:nth-child(17){margin-bottom:10px;color:yellow}
Is this what you are trying to achieve?
Check demo.
CSS:
.one-group div:last-child{
margin-bottom:15px;}
.two-group div:last-child{
margin-bottom:15px;}
I have this HTML code:
<div data-width="70"></div>
I want to set it's width in CSS equal to the value of data-width attribute, e.g. something like this:
div {
width: [data-width];
}
I saw this was done somewhere, but I can't remember it. Thanks.
You need the attr CSS function:
div {
width: attr(data-width);
}
The problem is that (as of 2021) it's not supported even by some of the major browsers (in my case Chrome):
You cant pass data attribute value directly in to css without pseudo type content.
Rather you can do this way.. CHECK THIS FIDDLE
<div data-width="a"></div><br>
<div data-width="b"></div><br>
<div data-width="c"></div>
CSS
div[data-width="a"] {
background-color: gray;
height: 10px;
width:70px;
}
div[data-width="b"] {
background-color: gray;
height: 10px;
width:80px;
}
div[data-width="c"] {
background-color: gray;
height: 10px;
width:90px;
}
Inline CSS variables are almost as declarative as data attributes, and they are widely supported now, in contrast to the attr(). Check this out:
var elem = document.getElementById("demo");
var jsVar = elem.style.getPropertyValue("--my-var");
function next() {
jsVar = jsVar % 5 + 1; // loop 1..5
elem.style.setProperty("--my-var", jsVar);
}
.d1 {
width: calc( var(--my-var) * 100px );
background-color: orange;
}
.d2 {
column-count: var(--my-var);
}
<button onclick="next()">Increase var</button>
<div id="demo" style="--my-var: 2">
<div class="d1">CustomWidth</div>
<div class="d2">custom columns number custom columns number custom columns number custom columns number custom columns number custom columns number custom columns number</div>
</div>
Another approach would be using CSS Custom Properties with style element to pass values from HTML to CSS.
div {
width: var(--width);
height: var(--height);
background-color: var(--backgroundColor);
}
<div
style="
--width: 50px;
--height: 25px;
--backgroundColor: #ccc;
"
></div>
<div
style="
--width: 100px;
--height: 50px;
--backgroundColor: #aaa;
"
></div>
CSS is static styling information about specific html element and not the other way around. If you want to use CSS to set the width of your div I suggest you do with the use of classes:
HTML:
<div class="foo"></div>
CSS:
.foo {
width: 70px;
}
jsFiddle
I'm just having fun with this, but a jQuery solution would be something like this:
HTML
<div class='foo' data-width='70'></div>
<div class='foo' data-width='110'></div>
<div class='foo' data-width='300'></div>
<div class='foo' data-width='200'></div>
CSS
.foo {
background: red;
height: 20px;
margin-bottom: 10px;
width: 0; /** defaults to zero **/
}
jQuery
$(document).ready(function(){
$('.foo').each(function(i) {
var width = $(this).data('width');
$(this).width(width);
});
});
Codepen sketch here: http://cdpn.io/otdqB
KIND OF AN UPDATE
Not what you're looking for, since you want to pass a variable to the width property. You might as well use a class in this case.
HTML
<div data-width='70'>Blue</div>
CSS
div[data-width='70'] {
width: 70px;
}
Sketch here: http://cdpn.io/jKDcH
<div data-width="70"></div>
use `attr()` to get the value of attribute;
div {
width: attr(data-width);
}
can you try this
$(function(){
$( "div" ).data( "data-width" ).each(function(this) {
$(this).width($(this..data( "data-width" )))
});
});