Is there a difference in CSS selectors `:enabled` vs `not(:disabled)` - css

Is there a difference in behaviour or browser support for using the CSS3 selectors :enabled or not(:disabled)?
I expect them to be functionally identical, and as they are both CSS3 selectors, browser support should be identical too.

Yes, there is a difference — :not(:disabled) can match elements that are neither :enabled nor :disabled. These are elements where enabled/disabled semantics simply don't apply, such as div, p, ul, etc.
The spec confirms this:
What constitutes an enabled state, a disabled state, and a user interface element is language-dependent. In a typical document most elements will be neither :enabled nor :disabled.
Interestingly, the same can't be said for :checked — there is no corresponding :unchecked pseudo-class, despite the fact that not all elements have checked/unchecked semantics either. See my answer to this question.
If you're qualifying these pseudo-classes with a type selector (such as input, select or textarea) or a class selector, you probably don't have to worry about this. Still, it makes more sense to use :enabled than :not(:disabled).
Browser support for the majority of level 3 pseudo-classes is indeed identical — there are no known browsers that support either :enabled or :disabled only. However, according to MDN it looks like Opera 9.0 and Safari 3.1 don't support :not(), although they do support :enabled and :disabled, and some other features like substring-matching attribute selectors and the general sibling combinator ~ are supported in IE7 with some issues and a little bit better in IE8.

Related

CSS `:disable` vs `[disabled]` [duplicate]

I'm trying to style a disabled input. I can use:
.myInput[disabled] { }
or
.myInput:disabled { }
Is the attribute selector the modern CSS3 way and the way to go forward? I used to use the pseudo-class, but I can't find any info on whether they are the old way and won't be supported or whether they're both equal and you can use whatever you like best.
I have no need to support older browsers (it's an intranet application), so is it:
attribute is newer and better
pseudo-class is still the way to go
whichever you like best
there's a technical reason to use one over the other
Is the attribute selector the modern CSS3 way and the way to go forward?
attribute is newer and better
No; actually, attribute selectors have been around since CSS2, and the disabled attribute itself has existed since HTML 4. As far as I know, the :disabled pseudo-class was introduced in Selectors 3, which makes the pseudo-class newer.
there's a technical reason to use one over the other
Yes, to some extent.
With an attribute selector, you're relying on the knowledge that the document you're styling makes use of a disabled attribute to indicate disabled fields. Theoretically, if you were styling something that wasn't HTML, disabled fields might not be represented using a disabled attribute, e.g. it might be enabled="false" or something like that. Even future editions of HTML could introduce new elements that make use of different attributes to represent enabled/disabled state; those elements wouldn't match the [disabled] attribute selector.
The :disabled pseudo-class decouples the selector from the document you're working with. The spec simply states that it targets elements that are disabled, and that whether an element is enabled, disabled, or neither, is defined by the document language instead:
What constitutes an enabled state, a disabled state, and a user interface element is language-dependent. In a typical document most elements will be neither :enabled nor :disabled.
In other words, when you use the pseudo-class, the UA automatically figures out which elements to match based on the document you're styling, so you don't have to tell it how. Conversely, the attribute selector would match any element with a disabled attribute, regardless of whether that element actually supports being enabled or disabled, such as div. If you're using one of the many modern frameworks that rely on such non-standard behavior, you may be better served by using the attribute selector.
In terms of the DOM, I believe setting the disabled property on a DOM element also modifies the HTML element's disabled attribute, which means there's no difference between either selector with DOM manipulation. I'm not sure if this is browser-dependent, but here's a fiddle that demonstrates it in the latest versions of all major browsers:
// The following statement removes the disabled attribute from the first input
document.querySelector('input:first-child').disabled = false;
You're most likely going to be styling HTML, so none of this may make any difference to you, but if browser compatibility isn't an issue I would choose :enabled and :disabled over :not([disabled]) and [disabled] simply because the pseudo-classes carry semantics that the attribute selector does not. I'm a purist like that.
It turns out that Internet Explorer 10 and 11 fail to recognize the :disabled pseudoclass on some elements and only work fine with the attribute selector syntax.
#test1:disabled { color: graytext; }
#test2[disabled] { color: graytext; }
<form>
<fieldset id="test1" disabled>:disabled</fieldset>
<fieldset id="test2" disabled>[disabled]</fieldset>
</form>
The code snipped above renders in IE like this:
As long as you're only styling input elements, you should be fine either way. Still it's a good advice to test the final result in all browsers you wish to support.
Apparently, you can only select and style input elements with ":(pseudoclass)" / ":disabled" , but other elements, such as DIVs, must instead use [disabled].
I often run into this issue when writing SCSS / SASS and try to select a disabled element.
See
CSS selector for disabled elements

CSS pseudo class :link not supported. Is there any equivalent?

I'm new to CSS, and I was wondering, is there another way to write an equivalent to pseudo class :link , in case :link is not supported?
Theoretically, in selectors-4 you can write :any-link:not(:visited), but you are going to be hard-pressed to find any browsers that support :visited but not :link, let alone :any-link, browser regressions notwithstanding.
A slightly more widely-supported selector requires knowledge of the document language since the link pseudo-classes themselves match different elements based on document semantics. In HTML, :link can be expressed as the following level 3 selector-list:
a[href]:not(:visited), area[href]:not(:visited), link[href]:not(:visited)
The same caveat applies.
If you're asking about browsers that support neither of the link pseudo-classes, remove the :not(:visited) from the above selector-list. If you're asking how to match links based on their visitedness in browsers that support neither pseudo-class, then it becomes impossible. But there are no known browsers that lack support for the link pseudo-classes, so this will never be a problem if you're making websites.
Note that CSS1 and CSS2.1 define :link and :visited to apply only to a elements — the standalone Selectors standard (level 3 and up) instead defers to the document language, and in the case of HTML, the current definition above is provided by HTML5. What this means in theory is that browsers up to and including IE6 (not sure about IE7) don't support the link pseudo-classes on elements other than a[href], and that's because IE6 was designed to be CSS1-compliant, not CSS2-compliant.
What this means in practice depends on whether or not you use the link pseudo-classes to match area or link elements, and whether or not you support browsers dating back to IE7, in the first place. If you're like 99.9% of authors who don't use them with area or link elements, then this means absolutely nothing to you in practice.
The a {} selector ({} added since it's so short) will apply to all pseudo classes though a:link will override specific styling for URLs the user has not yet visited.
Someone mentioned an exceptionally old version of Internet Explorer. If you're new to CSS you should first concentrate on current browsers. If you're learning at this point the oldest version of IE that you'll be supporting is IE11 if working with CSS will become a part of your future career.

Should I use CSS :disabled pseudo-class or [disabled] attribute selector or is it a matter of opinion?

I'm trying to style a disabled input. I can use:
.myInput[disabled] { }
or
.myInput:disabled { }
Is the attribute selector the modern CSS3 way and the way to go forward? I used to use the pseudo-class, but I can't find any info on whether they are the old way and won't be supported or whether they're both equal and you can use whatever you like best.
I have no need to support older browsers (it's an intranet application), so is it:
attribute is newer and better
pseudo-class is still the way to go
whichever you like best
there's a technical reason to use one over the other
Is the attribute selector the modern CSS3 way and the way to go forward?
attribute is newer and better
No; actually, attribute selectors have been around since CSS2, and the disabled attribute itself has existed since HTML 4. As far as I know, the :disabled pseudo-class was introduced in Selectors 3, which makes the pseudo-class newer.
there's a technical reason to use one over the other
Yes, to some extent.
With an attribute selector, you're relying on the knowledge that the document you're styling makes use of a disabled attribute to indicate disabled fields. Theoretically, if you were styling something that wasn't HTML, disabled fields might not be represented using a disabled attribute, e.g. it might be enabled="false" or something like that. Even future editions of HTML could introduce new elements that make use of different attributes to represent enabled/disabled state; those elements wouldn't match the [disabled] attribute selector.
The :disabled pseudo-class decouples the selector from the document you're working with. The spec simply states that it targets elements that are disabled, and that whether an element is enabled, disabled, or neither, is defined by the document language instead:
What constitutes an enabled state, a disabled state, and a user interface element is language-dependent. In a typical document most elements will be neither :enabled nor :disabled.
In other words, when you use the pseudo-class, the UA automatically figures out which elements to match based on the document you're styling, so you don't have to tell it how. Conversely, the attribute selector would match any element with a disabled attribute, regardless of whether that element actually supports being enabled or disabled, such as div. If you're using one of the many modern frameworks that rely on such non-standard behavior, you may be better served by using the attribute selector.
In terms of the DOM, I believe setting the disabled property on a DOM element also modifies the HTML element's disabled attribute, which means there's no difference between either selector with DOM manipulation. I'm not sure if this is browser-dependent, but here's a fiddle that demonstrates it in the latest versions of all major browsers:
// The following statement removes the disabled attribute from the first input
document.querySelector('input:first-child').disabled = false;
You're most likely going to be styling HTML, so none of this may make any difference to you, but if browser compatibility isn't an issue I would choose :enabled and :disabled over :not([disabled]) and [disabled] simply because the pseudo-classes carry semantics that the attribute selector does not. I'm a purist like that.
It turns out that Internet Explorer 10 and 11 fail to recognize the :disabled pseudoclass on some elements and only work fine with the attribute selector syntax.
#test1:disabled { color: graytext; }
#test2[disabled] { color: graytext; }
<form>
<fieldset id="test1" disabled>:disabled</fieldset>
<fieldset id="test2" disabled>[disabled]</fieldset>
</form>
The code snipped above renders in IE like this:
As long as you're only styling input elements, you should be fine either way. Still it's a good advice to test the final result in all browsers you wish to support.
Apparently, you can only select and style input elements with ":(pseudoclass)" / ":disabled" , but other elements, such as DIVs, must instead use [disabled].
I often run into this issue when writing SCSS / SASS and try to select a disabled element.
See
CSS selector for disabled elements

Chained pseudo-selectors in IE8

Chained pseudo-selectors do not seem to work in IE8 on Windows XP. Is there any documentation about this?
I'm developing a website using Selectivizr in order to use CSS3 selectors, but a style such as this doesn't work in IE8, whereas it works everywhere else (unsurprisingly):
span:last-child:after {content: "foobar";}
This is not a bug, it's due to the fact the the selector doesn't match natively.
A simple selector is either a type selector or universal selector followed immediately by zero or more attribute selectors, ID selectors, or pseudo-classes, in any order. The simple selector matches if all of its components match.
The simple selector in this case is either span:first-child, which matches natively in IE8, or span:last-child, which does not.
One pseudo-element may be appended to the last simple selector in a chain, in which case the style information applies to a subpart of each subject.
Appending :after to span:first-child is a match, while appending it to span:last-child is not, and since Selectivizr is a post-processor, it comes too late to save the day. Perhaps a pre-processor would have better luck.

:after vs. ::after

Is there any functional difference between the CSS 2.1 :after and the CSS 3 ::after pseudo-selectors (other than ::after not being supported in older browsers)? Is there any practical reason to use the newer specification?
It's pseudo-class vs pseudo-element distinction.
Except for ::first-line, ::first-letter, ::before and ::after (which have been around a little while and can be used with single colons if you require IE8 support), pseudo-elements require double colons.
Pseudo-classes select actual elements themselves, you can use :first-child or :nth-of-type(n) for selecting the first or specific <p>'s in a div, for example.
(And also states of actual elements like :hover and :focus.)
Pseudo-elements target a sub-part of an element like ::first-line or ::first-letter, things that aren't elements in their own right.
Actually, better description here: http://bricss.net/post/10768584657/know-your-lingo-pseudo-class-vs-pseudo-element
Also here: http://www.evotech.net/blog/2007/05/after-v-after-what-is-double-colon-notation/
CSS Selectors like ::after are some virtual elements not available as a explicit element in DOM tree. They are called "Pseudo-Elements" and are used to insert some content before/after an element (eg: ::before, ::after) or, select some part of an element (eg: ::first-letter). Currently there is only 5 standard pseudo elements: after, before, first-letter, first-line, selection.
On the other hand, there are other types of selectors called "Pseudo-Classes" which are used to define a special state of an element (like as :hover, :focus, :nth-child(n)). These will select whole of an existing element in DOM. Pseudo classes are a long list with more than 30 items.
Initially (in CSS2 and CSS1), The single-colon syntax was used for both pseudo-classes and pseudo-elements. But, in CSS3 the :: syntax replaced the : notation for pseudo-elements to better distinguish of them.
For backward compatibility, the old single-colon syntax is acceptable for pseudo-elements like as :after (browsers still all support the old syntax with one semicolon). Only IE-8 doesn’t support the new syntax (use single-colon if you want to support IE8).

Resources