I have a quite interesting problem here.
I want to target elements that match two conditions at the same time, but I can not find the way
<div class='redLink'>
<!-- ... ... ... -->
<a href='#'>Link</a>
<!-- ... ... ... -->
</div>
<div>
<!-- ... ... ... -->
<a href='#' class='redLink'>Link</a>
<!-- ... ... ... -->
</div>
My ideal CSS would be
[*:not(.redLink) a] AND [* a:not(.redLink)] {
color:green;
/* i.e., color NOT red */
}
However, the operand , is just an OR (and, when it doesn't match one condition, it matches the other...!).
And the only AND I can find is the logical concatenation div#myDivId.someClass, though what I would like is something like [div#myDiv a].[div.someClass a]
My goal is to target ONLY those anchors <a/> that don't have the class .redLink and have no parents with the .redLink class eiher.
And, very important, the only thing I want to target is the final anchor, not the whole div or the whole element.redLink...
Thank you!
Unfortunately, you can't achieve this using a CSS selector with a single rule. Currently you can only target a elements without the class using a:not(.redLink).
It is not possible to target a elements that do not have any .redLink ancestors, because the :not() pseudo-class doesn't accept combinators (otherwise you would do a:not(.redLink a)). A selector like :not(.redLink) a wouldn't work either, because that targets a elements with at least one ancestor without the class, which is not the same as a elements that have no ancestors with the class.
For example if your structure looked like this:
<div class='redLink'>
<p>
<a href='#'>Link</a>
</p>
</div>
That p doesn't have the class, so :not(.redLink) a would match.
If you happen to have the option of using jQuery, though, $('a:not(.redLink, .redLink a)') will work, because :not() is much more permissive in jQuery than in CSS.
If you need to do this using CSS only, the easiest solution is to make all a elements green, then override it:
a {
color: green;
}
a.redLink, .redLink a {
color: red;
}
Maybe you can reverse the logic like this. Make every link green (if that is possible in your site) and make the specific links red again.
a {
color: green;
}
a.redlink,
.redlink a {
color: red;
}
Of course it depends on the structure and complexity of your site and the existance of other styling that might collide with this, but I would prefer a CSS-only solution like this over JQuery if it is reasonably possible.
Related
In the context of .NET MVC (but that could also apply to other similar technologies), let :
A tree of views, e.g the page view FileUploadPage and its child partial view FileDropZone that would have a class identifying their view "type" on their root node :
FileUploadPage.cshtml :
<div class="view-fileuploadpage">
<h2>File upload page view</h2>
#Html.Partial("FileDropZone")
</div>
FileDropZone.cshtml :
<div class="view-filedropzone">
File drop zone partial view
</div>
Some CSS rules which I would like to apply only to the view's own elements instead of globally :
Like this :
.view-fileuploadpage h2 {
/* Spécific to the view FileUploadPage */
}
But NOT like this :
h2 {
/* Global, not what I want */
}
I like this way of doing things, because it prevents interferences from other pages in the CSS due to needlessly global selectors.
However there is a problem with that : the view-specific CSS rules apply to the view's own elements, but also to any other view that is being included as a child view. In the example above, the view FileDropZone inherits the rules that are supposed to be specific to the view FileUploadPage, which is an undesired consequence.
So my question is : how can I make the CSS rules that are supposed to be specific to my views own elements NOT apply to the child views as well ?
I could use the "direct child" opeartor in my selectors to specify the full "path" to the elements I want to style, like so :
.view-fileuploadpage > h2 {
/* Applies to the h2 of the view FileUploadPage */
/* DOes NOT apply to any h2 that would exist in a child view of FileUploadPage */
}
But this would make the code hard to maintain, because the selectors would have to be updated everytime a piece of markup gets moved or modified within a view.
I'm having the exact same problem with JavaScript and query selectors, but I guess finding a solution for CSS would also solve the JavaScript problem.
Thank you.
You can use the :not() pseudo-class to deselect grandchildren within a particular child.
.view-fileuploadpage h2:not(.file-drop-zone *):not(.more-children *){
color: #f00;
}
This assigns the color to all h2 elements excluding those in the stated classes within the :not() selector.
The CSS file will need to be updated with the classes of new children if any.
The best solution will be to wrap all the contents of the view-fileuploadpage or parent div that should not get the styling and use the class of this wrapper as a single selector. This way, the file will not need constant updating all future children and grandchildren are added within the wrapper.
Hence, instead of having:
<div class='view-fileuploadpage-one'>
<h2>Container</h2>
<p>...</p>
<div class='file-drop-zone'>
<h2>file drop zone</h2>
...
</div>
<div class='more-children'>
<h2>More children</h2>
...
</div>
</div>
You can opt for:
<div class='view-fileuploadpage-two'>
<h2>Container</h2>
<p>...</p>
<div class='content-wrapper'>
<!-- this wrapper will contain everything else -->
<div class='file-drop-zone'>
...
</div>
<div class='more-children'>
...
</div>
</div>
</div>
</div>
Which will be more or less:
<div class='view-fileuploadpage-two'>
...
<div class='content-wrapper'>
...
</div>
</div>
Kindly see my idea on this pen.
The question I want to ask is, "Is it possible/good practice to refer to a child of an element that is not a direct child?"
For instance, if you have HTML like this:
<form class="formation">
<p>
<span>
<input class="phone input">
</span>
</p>
<p>
<span>
<input class="text input">
</span>
</p>
</form>
And you want to refer in CSS to the inputs only in that particular form, so you call the class of the form followed by the class of the inputs without referring to the elements in between, like this:
.formation .input {
width: 10px;
}
will this work properly?
I tend to think I've done this already on projects and it has worked properly but usually I refer to all the children in between (because I don't go that deep). But I'm currently working on a media query for a wordpress site that doesn't seem to be respecting this rule. Is this bad practice? Or is this downright incorrect? Thanks for all your help!
Yes, it is not only possible but also advisable to do so. Choose your selectors for your css rules as lean as needed to reduce dependency on your markup structure. This is not only wise for performance reasons, it also saves you quite some work in case your markup should ever change, e.g. later on you notice the span is not needed any longer and you remove it to keep your markup as clean as possible. In case you used the full DOM path to your .input you will then also have to adjust your css selectors. Same if for any reason in the future your <p> should become a <div>.
Just make sure you give the rules as much DOM context as necessary to not apply your rules to the same classed element in other contexts (if you have any at all, and if you want to apply a different set of style rules for it).
Yes, it'll work fine. What youv'e got with .form .input allows for any number of intermediate nodes between the two classes.
If you'd had .form > .input, then your CSS wouldn't match at all. > is the "immediate descendant" selector, so
.form .input { color: green }
.form > .input { color: red }
<div class="form">
<div class="input">This is red</div>
<div class="whatever">
<div class="input">This is green</div>
</div>
</div>
HTML:
<p class=menu_top>Title</p>
<p class=menu_top>Order</p>
<p class=menu_top>Position</p>
<p class=menu_top>Number</p>
How can I target just the first element?
Use the :first-child pseudo-class.
.menu_top:first-child {
your: rules;
}
http://jsfiddle.net/uKJcK/1/
Just as a point of note, the way you're structuring is going to cause you more work in the future, as well. It would be far better to have something like this:
<div class="menu_top">
<p>Title</p>
<p>Order</p>
<p>Position</p>
<p>Number</p>
</div>
(and more semantically-correct would be to make it an unordered list)
The repetition is not necessary, when you can simply spec in CSS like so:
.menu_top p {
//all my basic styles for each menu item
}
.menu_top p:first-child {
// specific styles for just the first menu item
}
Over-classing causes a load of rework in the future, and muddies the code. Use the cascade to your advantage; it cuts down on repetitive code, and makes it easier to override only the outliers.
I'm trying to apply background-color when a user mouse hover the element whose class name is "reMode_hover".
But I do not want to change color if the element also has "reMode_selected"
Note: I can only use CSS not javascript because I'm working within some sort of limited environment.
To clarify, my goal is to color the first element on hover but not the second element.
HTML
<a href="" title="Design" class="reMode_design reMode_hover">
<span>Design</span>
</a>
<a href="" title="Design"
class="reMode_design reMode_hover reMode_selected">
<span>Design</span>
</a>
I tried below hoping the first definition would work but it is not. What am I doing wrong?
CSS
/* do not apply background-color so leave this empty */
.reMode_selected .reMode_hover:hover
{
}
.reMode_hover:hover
{
background-color: #f0ac00;
}
One way is to use the multiple class selector (no space as that is the descendant selector):
.reMode_hover:not(.reMode_selected):hover
{
background-color: #f0ac00;
}
<a href="" title="Design" class="reMode_design reMode_hover">
<span>Design</span>
</a>
<a href="" title="Design"
class="reMode_design reMode_hover reMode_selected">
<span>Design</span>
</a>
In modern browsers you can do:
.reMode_hover:not(.reMode_selected):hover{}
Consult http://caniuse.com/css-sel3 for compatibility information.
Method 1
The problem with your code is that you are selecting the .remode_hover that is a descendant of .remode_selected. So the first part of getting your code to work correctly is by removing that space
.reMode_selected.reMode_hover:hover
Then, in order to get the style to not work, you have to override the style set by the :hover. In other words, you need to counter the background-color property. So the final code will be
.reMode_selected.reMode_hover:hover {
background-color:inherit;
}
.reMode_hover:hover {
background-color: #f0ac00;
}
Fiddle
Method 2
An alternative method would be to use :not(), as stated by others. This will return any element that doesn't have the class or property stated inside the parenthesis. In this case, you would put .remode_selected in there. This will target all elements that don't have a class of .remode_selected
Fiddle
However, I would not recommend this method, because of the fact that it was introduced in CSS3, so browser support is not ideal.
Method 3
A third method would be to use jQuery. You can target the .not() selector, which would be similar to using :not() in CSS, but with much better browser support
Fiddle
I have a menu with links in the following form, in which I am trying to highlight the current menu item. I can't seem to get it working. Please advice as to what I am doing wrong
HTML
<body id="home">
<div id="topMenu">
<div class="nav-home" id="topMenuBlock"><p>Home</p></div>
<div id="nav-about"><p>About</p></div>
<div id="nav-rates"><p>Rates</p></div>
<div id="nav-faq"><p>FAQ</p></div>
<div id="nav-contact"><p>Contact</p></div>
<div id="nav-careers"><p>Careers</p></div>
</div>
<div id="rightTopMenu"></div>
</div>...other stuff</body>
Then for the CSS I have the following:
#home a.nav-home{ border-bottom:2px solid white; }
Do the links HAVE to be in a List, or can I leave them in div's, and if so, how can I make this work?
Thanks.
You've a little bit of a mess here.
Do the links HAVE to be in a List, or can I leave them in div's?
They don't have to be, but they probably should be. There's not good reason to use the strange markup you have chosen, you should definitely consider switching to a list and <li> tags.
Problem with duplicate ids
You have <body id="home"> and <a href="" id="home">
You also have several instances of id="topMenuBlock" (I see you fixed this in your edit.)
You cannot have more than one element with the same id. id attributes must be unique, always. Use class names instead, if anything.
You are using this selector: #home a.nav-home {} but it doesn't match anything. There is no <a class="nav-home">. You can use something like:
#home {} because that's the id of the <a> element you want
.nav-home a {} - Selects the <a> inside an element with class="nav-home"
Perhaps you have the concept of ids and classes mixed up. Ids are supposed to uniquely identify HTML elements, whereas classes can be used as many times as you like. Right now you have 6 elements with the id #topMenuBlock. You should make a .topMenuBlock class instead. I would also make a #nav-home id instead of a class since there should only be one such element on each page.
Secondly, there is no need for the <p> tags you have within your <a> tags. In fact, it's against HTML standards to do so since anchors are inline elements and paragraphs are block-level elements.
Lastly, your CSS selector that sets the border is incorrect because the .nav-home div is not contained within an <a> element. Use this CSS instead (assuming you change nav-home to be an id rather than a class):
#nav-home{ border-bottom:2px solid white; }
Fix these issues and then see what happens. If you're new to HTML and CSS, I would recommend going through some tutorials, such as the ones found at http://www.w3schools.com/.
Your class identifier should be in the <a /> tag
You have
<div class="nav-home" id="topMenuBlock"><p>Home</p></div>
but you want
<div class="something" id="topMenuBlock"><a class = "nav-home" href="" id="home"><p>Home</p></a></div>
Modify your CSS class accordingly.