I completely understand that you cannot group animation keyframes selectors such as
#keyframes,
#-moz-keyframes,
#-webkit-keyframes { /*do something*/ }
and that you absolutely MUST do
#keyframes { /*do something*/ }
#-moz-keyframes { /*do something*/ }
#-webkit-keyframes { /*do something*/ }
I know there are pre-processors that can do all this for me. But I am more interested in the reason behind why this is the case?
My google-fu is failing me. It seems to always direct me to a stackoverflow page telling someone they 'cannot' do it and they must separate them all out, or telling people about the pre-processors -or- I get sent to that horrible about.com and read stuff like
Any Selector Can be Grouped ~about.com
Which obviously is not true in this case. If someone can direct me to an article, or explain to me why it cannot be grouped it would be most helpful.
Keep in mind that at-rules and selectors are completely different things.
At-rules are covered in this section of CSS2.1 spec, which says that an at-rule consists of exactly one at-keyword followed by some statement (be it a semicolon-terminated statement, or a block). As far as the CSS parser is concerned, what you have is a set of three separate at-rules, one prefix for each vendor and one unprefixed rule for the standard.
The more appropriate counterpart to at-rules would be rule sets, or style rules, described here. A rule set consists of a selector and a declaration block (containing style declarations). This is analogous to the contents of an at-rule as described above. It also means that the selector is just one part of a rule set.
Certain at-rules do allow comma-separated values in their preludes, such as #media:
#media screen, projection {
/* Styles for both screen and projection media */
}
But instead of grouping the at-rules in entirety, the grouping happens within the value that comes after the at-keyword in the beginning of the rule.
This #media rule can be expanded into two separate rules like so:
#media screen {
/* Styles for screen media */
}
#media projection {
/* Styles for projection media */
}
Notice that each rule has its own #media at-keyword.
Similarly, when you group multiple selectors into a single rule, what you have is one style rule. The part that is grouped is the selector; everything in the declaration block that follows applies to all the selectors that are listed in the group:
.foo, .bar {
/* Styles that apply to both .foo and .bar elements */
}
And when you expand it, it becomes two rule sets:
.foo {
/* Styles that apply to .foo elements */
}
.bar {
/* Styles that apply to .bar elements */
}
Because of
When a user agent cannot parse the selector (i.e., it is not valid CSS 2.1), it must ignore the selector and the following declaration block (if any) as well.
found at http://www.w3.org/TR/CSS21/syndata.html#rule-sets
So each vendor prefix makes the whole rule un-parseable for all the other vendors.
Related
Is it possible to select elements in CSS by their HTML5 data attributes (for example, data-role)?
If you mean using an attribute selector, sure, why not:
[data-role="page"] {
/* Styles */
}
There are a variety of attribute selectors you can use for various scenarios which are all covered in the document I link to. Note that, despite custom data attributes being a "new HTML5 feature",
browsers typically don't have any problems supporting non-standard attributes, so you should be able to filter them with attribute selectors; and
you don't have to worry about CSS validation either, as CSS doesn't care about non-namespaced attribute names as long as they don't break the selector syntax.
It's also possible to select attributes regardless of their content, in modern browsers
with:
[data-my-attribute] {
/* Styles */
}
[anything] {
/* Styles */
}
For example: http://codepen.io/jasonm23/pen/fADnu
Works on a very significant percentage of browsers.
Note this can also be used in a JQuery selector, or using document.querySelector
It's worth noting CSS3 substring attribute selectors
[attribute^=value] { /* starts with selector */
/* Styles */
}
[attribute$=value] { /* ends with selector */
/* Styles */
}
[attribute*=value] { /* contains selector */
/* Styles */
}
You can combine multiple selectors and this is so cool knowing that you can select every attribute and attribute based on their value like href based on their values with CSS only..
Attributes selectors allows you play around some extra with id and class attributes
Here is an awesome read on Attribute Selectors
Fiddle
a[href="http://aamirshahzad.net"][title="Aamir"] {
color: green;
text-decoration: none;
}
a[id*="google"] {
color: red;
}
a[class*="stack"] {
color: yellow;
}
Aamir
<br>
Google
<br>
stack
Browser support:
IE6+, Chrome, Firefox & Safari
You can check detail here.
[data-value] {
/* Attribute exists */
}
[data-value="foo"] {
/* Attribute has this exact value */
}
[data-value*="foo"] {
/* Attribute value contains this value somewhere in it */
}
[data-value~="foo"] {
/* Attribute has this value in a space-separated list somewhere */
}
[data-value^="foo"] {
/* Attribute value starts with this */
}
[data-value|="foo"] {
/* Attribute value starts with this in a dash-separated list */
}
[data-value$="foo"] {
/* Attribute value ends with this */
}
Is it possible to select elements in CSS by their HTML5 data attributes? This can easily be answered just by trying it, and the answer is, of course, yes. But this invariably leads us to the next question, 'Should we select elements in CSS by their HTML5 data attributes?' There are conflicting opinions on this.
In the 'no' camp is (or at least was, back in 2014) CSS legend Harry Roberts. In the article, Naming UI components in OOCSS, he wrote:
It’s important to note that although we can style HTML via its data-*
attributes, we probably shouldn’t. data-* attributes are meant for
holding data in markup, not for selecting on. This, from the HTML
Living Standard (emphasis mine):
"Custom data attributes are intended to store custom data private to
the page or application, for which there are no more appropriate
attributes or elements."
The W3C spec was frustratingly vague on this point, but based purely on what it did and didn't say, I think Harry's conclusion was perfectly reasonable.
Since then, plenty of articles have suggested that it's perfectly appropriate to use custom data attributes as styling hooks, including MDN's guide, Using data attributes. There's even a CSS methodology called CUBE CSS which has adopted the data attribute hook as the preferred way of adding styles to component 'exceptions' (known as modifiers in BEM).
Thankfully, the WHATWG HTML Living Standard has since added a few more words and even some examples (emphasis mine):
Custom data attributes are intended to store custom data, state,
annotations, and similar, private to the page or application, for
which there are no more appropriate attributes or elements.
In this example, custom data attributes are used to store the result
of a feature detection for PaymentRequest, which could be used in CSS
to style a checkout page differently.
Authors should carefully design such extensions so that when the
attributes are ignored and any associated CSS dropped, the page is
still usable.
TL;DR: Yes, it's okay to use data-* attributes in CSS selectors, provided the page is still usable without them.
I've created a custom userContent.css file for Firefox 26 running on Fedora 19.
I trying to figure out the precedence order to #-moz-document rules.
What I would like to do is to have a set of rules for the community pages and another set if rules for all other pages on the site.
I tried...
#-moz-document
url-prefix(https://discussions.apple.com/community/)
{/* rules for this page */}
#-moz-document
domain(discussions.apple.com)
{ /* different rules for all other pages in domain. */}
What I found was that my url-prefix rules were ignored.
Well if you have identical attributes in both rules, then the latter are going to overwrite the former because CSS when all thing are considered equal applies rules from top to bottom, so since https://discussions.apple.com/community/ also matches discussions.apple.com the rules from the latter will apply, if you want you can swap the order and this should help.
/*
Where to place a new css tag?
Find the conditional code, "the if statements".
The conditional code starts with #.
In some ways, you can think that all the css rules
are applied that in parallel.
In the case you add a new rule with with an attribute that you haven't used
before, the rule can be place anywhere in the conditional block that applies.
In case of conflicting attributes, the last
seen attribute is used.
*/
/* if the domain of the web page is any of these,
apply the css below, between the matching {}. */
#-moz-document
domain(discussions.apple.com),
domain(communities.apple.com),
domain(discussionsjapan.apple.com),
domain(discussionskorea.apple.com)
{
... lots of css ...
/* for pages from all devices and the width of the page
is larger than 1265px, apply the css.
Remember, we are inside of the #-moz-document conditional.
So the #media rule, only see pages that of passed #-moz-document
conditional. */
#media all and (min-width: 1265px)
{
/* styles for a large browser window */
... lots of css ...
}
/* for pages from all devices and the width of the page
is less than or equal to 1265px, apply the css. */
#media all and (max-width: 1265px)
{
/* styles for narrow browsers window */
... lots of css ...
}
} /* end of #-moz-document */
/* another conditional. The style rules will be applied
to any page with an URL starting with. Note, this
#-moz-document rules is applied separately from the
prior #-moz-document conditional. */
#-moz-document
url-prefix(https://discussions.apple.com/people/),
url-prefix(https://discussions.apple.com/welcome),
url-prefix(https://discussionsjapan.apple.com/people/),
url-prefix(https://discussionsjapan.apple.com/welcome/),
url-prefix(https://discussionskorea.apple.com/people/),
url-prefix(https://discussionskorea.apple.com/welcome/)
{
/* These rules get applied on the pages that match.
Remember, the last setting of the attribute wins. */
... lots of css ...
} /* end of #-moz-document */
Several answers tagged css discourage the use of !important in favor of specificity. Why?
There is actual math you can use to predict, control, and reverse-engineer the impact of CSS rules. By using !important you're breaking that. Look at this JS fiddle for example, which doesn't use !important: http://jsfiddle.net/hXPk7/
If you use Firebug or Chrome dev tools to inspect the title element where it says "Richard", you should see these rules, in this order:
/**************************/
/* /hXPk7/show/ (line 20) */
/**************************/
#myExample #title .name {
color: yellow;
}
/********************************************************/
/* /hXPk7/show/ (line 14) - Inherited fromdiv#myExample */
/********************************************************/
#myExample {
color: blue;
}
Note that this is not the order in which they appear in the CSS stylesheet - instead they are ordered in decreasing order of their specificity. The ones which take precedence are listed first, and the others (whose rules are overridden by more specific rules) probably have a property crossed out. This demonstrates that specificity makes it easy to trace (debug?) where an element is getting its CSS properties from.
Now, compare with this JS fiddle - which is effectively the same, but has a single new rule which now uses !important: http://jsfiddle.net/hXPk7/1/
Inspect the same element using Firebug or Chrome dev tools, and you'll see something like this:
/**************************/
/* /hXPk7/1/show/ (line 20) */
/**************************/
#myExample #title .name {
color: yellow;
}
/**************************/
/* /hXPk7/1/show/ (line 26) */
/**************************/
span {
color: black !important;
}
/********************************************************/
/* /hXPk7/1/show/ (line 14) - Inherited fromdiv#myExample */
/********************************************************/
#myExample {
color: blue;
}
Again, the rules are ordered according to their specificity - but note that this time, while the most specific rule which is listed first specifies a color of yellow, the browser instead renders the text as black! This is because the !important declaration has broken the normal behavior of specificity, taking precedence in a way which can be challenging to trace. Imagine a more realistic web site, with potentially hundreds of rules, and the one controlling the color isn't obvious to find, or to change.
Now, maybe this is a problem with the developer tools, but I think it reflects the fact that !important takes a normally easy-to-predict system of precedence and makes it more challenging. Maybe there are times to use it, but it should not be the first tool you reach for when writing CSS.
I'm currently elaborating a variation on Nicole Sullivan's OOCSS grids module that only requires a single container class to determine the layout of immediate descendants. I'm aware this bears the caveats of only working in CSS3 supporting browsers.
Here's an example of the difference:
Vanilla OOCSS grids rule:
.unit1of4 {
width: 25%;
}
My reduced grids rule:
.line > :nth-child(1):nth-last-child(4),
.line > :nth-child(2):nth-last-child(3),
.line > :nth-child(3):nth-last-child(2) {
width:25%;
}
Another significant caveat is the assumption that an element's fractional size is determined exclusively by its number of siblings — whereas that's the essential point of this code (to enable leaner HTML without explicit sizes all over the place), there will be exceptions where one might wish to have disproportionate widths.
Because of the specificity of my selectors, I can't simply stick the OOCSS module back in: specifying a unitXofY class in the HTML would be done specifically to supersede the default assumption, but in practice my selectors are stronger and would always override the specified class.
What I'm looking for is the tersest or most elegant way to supersede these selectors without limiting the practical effect of the specificity. That is to say, it must not make any assumptions about the selected element other than its class that will not always be correct.
The best I can come up with is :nth-child(n), in that it resolves to a meaningless statement which translates into plain English as 'a child element', which will always be the case of nested fractions. The code to implement this looks like this:
.line > :nth-child(1):nth-last-child(4),
.line > :nth-child(2):nth-last-child(3),
.line > :nth-child(3):nth-last-child(2),
.size1of4:nth-child(n):nth-child(n):nth-child(n) {
width:25%;
}
The selector is specified 3 times over such that it trumps the previous selectors by 1, meaning it can also trump the next rule governing .size1of5.
As a SASS mixin:
Because this is a verbose hack, I've packaged it up as a SASS mixin:
#mixin increase-specificity( $depth: 1 ) {
$sel : '';
#while($depth > 0) {
$sel : $sel + ':nth-child(n)';
$depth : $depth - 1;
}
&#{$sel} {
#content;
}
}
You can repeat the class-name as many times as you like to increase specificity, as long as there's no space between the repetitions of .className, it's assumed to apply to the same element. According to the w3c spec, "Repeated occurrances of the same simple selector are allowed and do increase specificity"
So you could, for example, use:
.size1of4.size1of4.size1of4.size1of4{/*some styles*/}
...and this will apply to any element with just size1of4 in the class attribute, overiding another declaration with only 3 class-names or pseudo-classes in its selector.
As mentioned, an element on a canvas jumps after the canvas itself is dragged. I'm using -webkit-transform: translate(x,y) to drag the canvas around. Any ideas on what to look into for this problem?
Look for changes that cause a reflow in CSS:
visibility:hidden/visible
display:none
:hover
and JavaScript:
offsetWidth or offsetHeight
scroll event
The sad truth about CSS3 selectors is that they really shouldn’t be used at all if you care about page performance. Decorating your markup with classes and ids and matching purely on those while avoiding all uses of sibling, descendant and child selectors will actually make a page perform significantly better in all browsers.
With parent selectors it becomes extremely easy to accidentally cause a document-wide grovel. People can and will misuse this selector. Supporting it is giving people a whole lot of rope to hang themselves with.
The complete profile is appropriate for contexts which aren't extremely performance sensitive. For example, implementations of the Selectors API specification [SELECTORS-API] should use the ‘complete’ profile. It includes all of the selectors defined in this document.
CSS implementations conformant to Selectors Level 4 must use the ‘fast’ profile for CSS selection.
The fast profile is appropriate for use in any context, including dynamic browser CSS selector matching. It includes every selector defined in this document, except for:
Combinators within :matches(), :not(), :nth-match(), and :nth-last-match().
The reference combinator
The subject indicator
In particular, in the situation the browser is looking at most of the selectors it's considering don't match the element in question. So the problem becomes one of deciding that a selector doesn't match as fast as possible; if that requires a bit of extra work in the cases that do match you still win due to all the work you save in the cases that don't match.
Use browser specific selectors to target the document itself:
#-moz-document url-prefix()
{
#media all
{
.foo { color: red } /* Firefox */
}
}
*::-ms-backdrop, .foo { color: red } /* IE11 */
*:-webkit-any-link, .foo { color: red } /* Webkit */
If you want to reference a child element based on its context, use the XML serialization of HTML5 and CSS3 namespaces:
#namespace m "http://www.w3.org/1998/Math/MathML/";
m|math { border: 1px solid blue; }
If you want to display a child element based on a parent pseudo class, you can define the default state of the child element, then redefine it for each state change of the parent:
li:hover > a * { display: none; }
li:hover > a:hover * { display: block; }
References
XHTML5 + CSS Namespaces
CSS Selectors: Should You Optimize Them To Perform Better?
Performance Impact of CSS Selectors
Why do browsers match CSS selectors from right to left?
List of suggested extensions to CSS
Force Element to Self-Clear its Children
The IE8 “hover” Bug: The Most Awesome IE Bug Ever?
MDN: #document
Issues for CSS Selectors Level 4
Reflows and Repaints: CSS Performance making your JavaScript Slow
How Browsers Work