Multiple :selectors on one CSS element? - html

I am stylizing a CSS element, and I was wondering if I could use multiple :selectors on one CSS element.
For instance:
p:hover:after {
content: "Hello!";
}
Because, when I want the p to be hovered over, I want the :after selector to also be called.

That specific example is completely valid, it works as demonstrated here.
As of now, the main limitation(s) pertaining to pseudo elements, is that:
CSS3 Selectors - 7. Pseudo-elements (reference)
Only one pseudo-element may appear per selector, and if present it must appear after the sequence of simple selectors that represents the subjects of the selector. Note: A future version of this specification may allow multiple pseudo-elements per selector.
Thus, neither of the following selectors would work: p:hover:after:after, p:after:hover
There is no limit on the number of simple selectors that can be chained together within the selector. And as #BoltClock states in the comments, there can only be one type selector or universal selector.
CSS3 Selectors - 4. Selector syntax (reference)
A sequence of simple selectors is a chain of simple selectors that are not separated by a combinator. It always begins with a type selector or a universal selector.
Here is a relevantly long selector that works: (example)
#parent:first-of-type:first-child > .child:last-child p:not(#element):not(#otherelement):hover:after

Multiple dynamic pseudo-classes are permissible.
An example of combining dynamic pseudo-classes:
a:focus { background: yellow }
a:focus:hover { background: white }
The last selector matches A elements that are in pseudo-class :focus
and in pseudo-class :hover.
Illustration: http://jsfiddle.net/BhKuf/ (remember to hover)

Related

How is css specificity determined for elements with the same selector? [duplicate]

I'm trying to figure out why one of my css classes seems to override the other (and not the other way around)
Here I have two css classes
.smallbox {
background-color: white;
height: 75px;
width: 150px;
font-size:20px;
box-shadow: 0 0 10px #ccc;
font-family: inherit;
}
.smallbox-paysummary {
#extend .smallbox;
font-size:10px;
}
and in my view I call
<pre class = "span12 pre-scrollable smallbox-paysummary smallbox ">
The font (The overlapping element) shows up as 10px instead of 20 - could someone explain why this is the case?
There are several rules ( applied in this order ) :
inline css ( html style attribute ) overrides css rules in style tag and css file
a more specific selector takes precedence over a less specific one
rules that appear later in the code override earlier rules if both have the same specificity.
A css rule with !important always takes precedence.
In your case its rule 3 that applies.
Specificity for single selectors from highest to lowest:
ids (example: #main selects <div id="main">)
classes (ex.: .myclass), attribute selectors (ex.: [href=^https:]) and pseudo-classes (ex.: :hover)
elements (ex.: div) and pseudo-elements (ex.: ::before)
To compare the specificity of two combined selectors, compare the number of occurences of single selectors of each of the specificity groups above.
Example: compare #nav ul li a:hover to #nav ul li.active a::after
count the number of id selectors: there is one for each (#nav)
count the number of class selectors: there is one for each (:hover and .active)
count the number of element selectors: there are 3 (ul li a) for the first and 4 for the second (ul li a ::after), thus the second combined selector is more specific.
A good article about css selector specificity.
Here's a compilation of CSS styling order in a diagram, on which CSS rules has higher priority and take precedence over the rest:
Disclaimer: My team and I worked this piece out together with a blog post (https://vecta.io/blog/definitive-guide-to-css-styling-order) which I think will come in handy to all front-end developers.
What we are looking at here is called specificity as stated by Mozilla:
Specificity is the means by which browsers decide which CSS property
values are the most relevant to an element and, therefore, will be
applied. Specificity is based on the matching rules which are composed
of different sorts of CSS selectors.
Specificity is a weight that is applied to a given CSS declaration,
determined by the number of each selector type in the matching
selector. When multiple declarations have equal specificity, the last
declaration found in the CSS is applied to the element. Specificity
only applies when the same element is targeted by multiple
declarations. As per CSS rules, directly targeted elements will always
take precedence over rules which an element inherits from its
ancestor.
I like the 0-0-0 explanation at https://specifishity.com:
Quite descriptive the picture of the !important directive! But sometimes it's the only way to override the inline style attribute. So it's a best practice trying to avoid both.
The order in which the classes appear in the html element does not matter, what counts is the order in which the blocks appear in the style sheet.
In your case .smallbox-paysummary is defined after .smallbox hence the 10px precedence.
First of all, based on your #extend directive, it seems you're not using pure CSS, but a preprocessor such as SASS os Stylus.
Now, when we talk about "order of precedence" in CSS, there is a general rule involved: whatever rules set after other rules (in a top-down fashion) are applied. In your case, just by specifying .smallbox after .smallbox-paysummary you would be able to change the precedence of your rules.
However, if you wanna go a bit further, I suggest this reading: CSS cascade W3C specification. You will find that the precedence of a rule is based on:
The current media type;
Importance;
Origin;
Specificity of the selector, and finally our well-known rule:
Which one is latter specified.
Also important to note is that when you have two styles on an HTML element with equal precedence, the browser will give precedence to the styles that were written to the DOM last ... so if in the DOM:
<html>
<head>
<style>.container-ext { width: 100%; }</style>
<style>.container { width: 50px; }</style>
</head>
<body>
<div class="container container-ext">Hello World</div>
</body>
...the width of the div will be 50px
AS is state in W3:
W3 Cascade CSS
the orden that different style sheet are applied is the following (quote from W3 cascading section):
user agent declarations
user normal declarations
author normal declarations
author important declarations
user important declarations
More information about this in the referred W3 document
Element, Pseudo Element: d = 1 – (0,0,0,1)
Class, Pseudo class, Attribute: c = 1 – (0,0,1,0)
Id: b = 1 – (0,1,0,0)
Inline Style: a = 1 – (1,0,0,0)
Inline css ( html style attribute ) overrides css rules in style tag and css file
A more specific selector takes precedence over a less specific one.
Rules that appear later in the code override earlier rules if both have the same specificity.
In a simple and short way, one should keep in mind the two things below:
Inline CSS has a higher priority than embedded and external CSS.
So final Order is: Value defined as Important > Inline > id nesting > id > class nesting > class > tag nesting > tag

Using custom CSS when there is no div ID

I'm running a website on Wordpress. Whenever I have to do CSS, I go onto Appearance > Custom CSS. To find the element I want to target I use the Inspect tool.
However on this instance there is no element ID. As this a small browser window for allowing card payment, I cannot find the div ID using Inspector.
IMAGES
Not OK to CSS
OK to CSS
You may want to give the CSS Selector documentation a read. There are many ways to select an element without a distinct Class or ID, including by attribute, type, and even Combinators (which are probably the best way to solve this problem you're having).
You can start be selecting an ancestor of the element you want, such as the.woocommerce wrapper.
You could then use the Direct Child Combinator: > and select the .order_details element.
Now you can use the Adjacent Sibling Combinator: + to select the div that is its adjacent sibling.
(Note that the adjacent sibling combinator is used here, not the General Sibling Combinator: ~, otherwise it would select all divs that are a later sibling of .order_details.
The following selector would probably be more than sufficient, and perhaps even a bit more specific than it needs to be (you may not need the >, but I put it in there for good measure - when using combinators on elements with no id or class, adding another layer of specificity usually doesn't hurt)
.woocommerce > .order_details + div { /* Styles here*/ }
If you're trying to override any of the inline styles on that div, you'll need to be more careful about the Specificity of the selector. Generally speaking there are 4 levels of specificity:
inline - ID - class - element
The Selector I gave you above has a specificity of 0021 (no inline, no ID, 2 classes, 1 element). However after your comment, it looks like you're trying to overwrite an inline style which has a gargantuan specificity of 1000. So if you apply any CSS that's not already defined inline, it should handily take effect. If you're changing any of the inline styles themselves, you'll need to make use of the _generally, but not always, bad-practice: !important Exception. Using !important will actually add a fifth order of magnitude to your specificity:
!important - inline - ID - class - element
So, if you're trying to change your inline background color, using the following:
.woocommerce > .order_details + div { background-color: #0095ee !important; }
Will give your blue background color an astounding 10021 specificity, which is higher than the inline grey's 01000.
Be very careful not to overuse !important - it's a tool that should be reserved for situations like this, and not just because you have a few CSS rules above that are slightly more specific.
Here's a handy CSS Specificity list, and a handy CSS Specificity calculator.

CSS selector :not() don't work as espected in selecting the children [duplicate]

Here is the official documentation for the CSS3 :not() pseudo-class:
http://www.w3.org/TR/css3-selectors/#negation
and the proposed CSS Selectors Level 4 enhancement:
http://dev.w3.org/csswg/selectors4/#negation
I've been searching the implementation and browser support for :not(), but the only examples I found were with a single element or with a direct child of an element, e.g.:
div *:not(p) { color: red; }
The example above works when <p> is a direct child of <div>, but it does not work when <p> is a more distant descendant of <div>.
div :not(p) {
color: red;
}
<div>
<ul>
<li>This is red</li>
</ul>
<p>This is NOT</p>
<blockquote><p>This is red but is not supposed to be!</p></blockquote>
</div>
If the answer is in the official documentation above, then I didn't find/understand it. As I said, I have searched this site and the web but couldn't find any discussion about the support or lack thereof of :not() as grand-children of another element.
Is this supposed to work like I think it should?
Is this supposed to work like I think it should?
No, the behavior you're seeing is correct.
In your last example, although the <blockquote> contains a <p>, it's the <blockquote> itself that's matching *:not(p), as well as the condition that it must be a descendant of the <div>, which it is. The style is applied only to the <blockquote>, but it is then inherited by the <p> inside it.
The <p> element itself still counts against the negation, so the <p> itself is still being excluded from your selector. It's just inheriting the text color from its parent, the <blockquote> element.
Even if none of its relatively close ancestors matched the selector, you have elements like html and body to worry about as well — although you could probably just tack on a body selector in the very beginning:
body div...
This is why I often strongly advise against using the :not() selector for filtering descendants, especially when not qualified with a type selector (like div in your example). It doesn't work the way most people expect it to, and the use of inherited properties like color only serves to compound the problem, on top of making it even more confusing for authors. See my answers to these other questions for more examples:
Why doesn't this CSS :not() declaration filter down?
CSS negation pseudo-class :not() for parent/ancestor elements
The solution to the problem described is to simply apply a different color to <p> elements. You won't be able to simply exclude them with a selector because of inheritance:
/* Apply to div and let all its descendants inherit */
div {
color: red;
}
/* Remove it from div p */
div p {
color: black;
}
On Selectors Level 4: yes, :not() has indeed been enhanced to accept full complex selectors that contain combinators. Essentially, this means (once browsers begin implementing it) you will be able to write the following selector and have it do exactly what you want:
p:not(div p) {
color: red;
}
In case anyone is interested, this works in jQuery today.
The color is assigned to the blockquote, and is then inherited by the p.
:not(p) just makes it so that the styles are not directly applied. They are still inherited though.

Is this CSS selector incorrect .my-class *:not(input[type="text"])

I want to select all elements except input of type text inside the DOM element with class "my-class".
So, I have CSS selector like this
.my-class *:not(input[type="text"]) {
// Some CSS poperties here
}
Is this incorrect ? It doesn't seem to work!
:not() is a CSS negation pseudo-class selector. It is a functional
pseudo-class selector that takes a simple selector as an argument, and
then matches one or more elements that are not represented by the
argument.
More info here and here.
You can only use simple selectors with the :not negation pseudo-class selector.
Use the following to achieve what you want:
.my-class :not([type='text']) {
//CSS properties here
}
Since there is no other HTML element that uses the attribute [type="text"] you can lose the input selector and then you'll be all set with the attribute simple selector. Also you do not need to use the * as a selector, it already matches every element.
jsFiddle
CODE SNIPPET:
.my-class :not([type='text'])::after {
content: "selected";
border: 1px solid red;
}
<div class="my-class">
<input type="text">
<input type="checkbox">
<input type="radio">
<div class="element">Div</div>
<section>Section</section>
<h1>H1</h1>
</div>
You may ask why it only accepts simple selectors, it's a matter of performance.
Fast vs Complete Selector Profiles
It is possible that in level four selectors they lift this restriction. It's under consideration.
.my-class input:not([type=text]), .my-class *:not(input)
The negation pseudo-class, :not(X), is a functional notation taking a
simple selector (excluding the negation pseudo-class itself) as an
argument. It represents an element that is not represented by its
argument.
Negations may not be nested; :not(:not(...)) is invalid. Note also
that since pseudo-elements are not simple selectors, they are not a
valid argument to :not().
See W3C's pseudo negation

CSS Selector for Class without Specific ID

I have a series of elements with the class .tab-pane attached to it. They also each have their own unique ID. I am trying to select every .tab-pane that does not have the id #home. I have tried .tab-pane:not#home{...} but it did not work. Any suggestions?
Sample HTML
<div id="home" class="tab-pane">...</div>
<div id="myself" class="tab-pane">...</div>
<div id="contact" class="tab-pane">...</div>
<div id="resume" class="tab-pane">...</div>
Try instead:
.tab-pane:not(#home) {
color: red;
}​
JS Fiddle demo.
The thing that you're not-selecting appears within the parentheses of the :not() selector, rather than appearing as a 'chained' pseudo-selector.
In this specific case, since the element you want to have not-styled is the first element, you could also use the general-sibling combinator ~ to style subsequent siblings differently:
#home ~ .tab-pane {
color: red;
}​
JS Fiddle demo.
But this would, and could, only work if the differently-styled (or un-styled) element is the first, since CSS can only select elements that appear later in the DOM, either as subsequent siblings, or descendants, of earlier elements.
References:
Selectors Level 3, negation :not() pseudo-class.
Maybe you meant to do this:
.tab-pane:not(#home)
You can access each of the individual classes by either using .tab-pane:eq(noOfClass) selector
Check examples here
OR You can also use :not selector .tab-pane:not(#home)
You can also try this (this is just like regular expressions)
.tab-pane:not([id^='home'])
{/*your code*/}
If you want to not include the id's which start with letter "h" then try the below one:
.tab-pane:not([id^='h'])
{/*your code*/}