Since this function is implemented in IE8, I wanted to see exactly what I could do with it, but I'm having trouble getting it to work anywhere other than the :before and :after css pseudo-elements. Should the following be allowed?
span[color] { color: attr(color); }
I tried it in Google Chrome too, but it didn't work. Also, what about more dynamic things like:
input[value=attr(default)] { color: gray; }
In CSS 2.1 (which is what should be used these days) the attr function is a little limited in what it can do. The only place where it can appear is in a content property on :before and :after pseudo-elements. So its sole purpose is generated content.
In CSS 3 this changed a bit, in that attr() may return other types than only strings and it can be used for other properties as well.
But bear in mind that most of CSS 3 is still a Working Draft with very few features (not including Values and Units) being a Candidate Recommendation. Support by User Agents for CSS 3 features varies currently between limited and next to non-existent. Mostly browser vendors seem to fight boredom by implementing "cool stuff" like rounded borders, text shadow, etc. which doesn't mean much work supporting it. But what you were looking at here is definitely beyond that and the WD status won't change in the near future. So don't expect it to be implemented anywhere.
Just use
span.red {}
for any different color, i don't think you need all combinations :)
Or just use
span[color="red"] {}
Related
In this question I'm looking for the cleanest possible solution for the problem below, along with urging the browsers' coders to catch up with the spec, especially :dir() one!!
The problem and it's current best known to me solution:
I'd like to style the image below based on directionality, flipping it, for example, when in RTL mode. The image resides in a shadow DOM. As of now, I'm achieving that with the styling below.
::shadowRoot
<style>
.directed-image:dir(rtl) { transform: rotateY(180deg); } -- Firefox only as of now
:host-context([dir=rtl]) { transform: rotateY(180deg); } -- Chromium only as of now
</style>
<img class="directed-image" src="..." />
Issues yet to be solved:
None of the styles above helping Safari: it has not yet implemented :dir() pseudo class and it's people seems to have a strong objection to :host-context()
I'm really not fan of those double-done solutions for a platform's diversity; would like to get rid of those, but this is only a secondary concern
Solutions ?:
The best I'd wish to have is that :dir() will get wide cross browser support - it'll solve the Safari's issue as well as would provide a truly directionality context aware styling (downsides of [dir=ltr] are touched a bit in the WebKit's bug link above).
But given that
Chromium's bug on :dir() is staled from 2018
WebKit's bug on :dir() last touched at 2016!!!
Firefox's bug on :host-context() is staled from 2018 with some concerns about the spec
and unwillingness of WebKit to implement :host-context()
-- having all this: is there any other solution for the problem (looking to solve the Safari issue at first priority).
JS based solutions are interesting but much less preferred.
january 2020 answer:
As you said: the dir attribute on the body tag will (in most cases) be the only indication of a language change. Since CSS doesn't cascade (yet; as you said) the only option for now is for Elements to observe that attribute change. So I fear your only option is a MutationObserver (in the elements you own)
https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
// Options for the observer (which mutations to observe)
const config = { attributes: true, childList: false, subtree: false };
Not sure if this is what you are looking for, but you could use RTLCSS. It's a CSS framework that allows you to easily switch between and create RTL and LTR stylesheets, without having to do too much double work.
It also supports a couple of big CSS frameworks if you use those, like Bootstrap and Semantic-UI
Since both of the following have the same effect:
.class {
cursor:pointer;
}
.class:hover {
cursor:pointer;
}
Regarding best practices, which one should you use and why?
The two selectors are for distinctly separate purposes, despite the fact that- at least in practice they appear to accomplish the same thing.
I would tend to say it would be best practice to define the hover state using :hover (at least on non-touchscreen devices, see below), because:
It makes finding and understanding your styling more apparent in larger blocks of CSS
It utilizes a specifically designated selector (which may be extended in the spec at a later date, what would then happen to your functionality?)
If you later add to the default styling for .class your states are clearly separated appropriately
What happens if you hand over responsibility of your CSS to another individual? Having :hover specific functionality defined under the correct selector makes understanding code a heck of a lot easier.
If you have more complex CSS its likely you'll be using :hover elsewhere, so should use it for the purposes of consistency
The two selectors represent the same element but in different states, semantically you should use :hover
But hang on a minute.. you may notice that if you set the cursor style for an a element to default then the usual hand icon wont appear on hover...this indicates that there is baked-in prior evidence for not specifically styling :hover states (see this in action here)
In summary, there is no game breaking reason not to use simply .class in some circumstances- it certainly uses less bytes and if you have a fairly simple setup then only under development by you...then why not, but be wary it is probably best avoided if you want to adhere to the strict rules and better support ongoing development.
In addition..lets not forget touchscreen devices MDN makes an important point here
on touch screens :hover is problematic or impossible. The :hover
pseudo-class never matches, or matches for a short moment after
touching an element. As touchscreen devices are very common, it is
important for web developer not to have content accessible only when
hovering over it, as this content would be hidden for users of such
devices.
As such depending on your requirement, it may not be best to use :hover as if you have it in your CSS for a touch screen device it may bake in reliance on unsupported or flakey functionality.
IE6 and lower only recognises the :hover pseudo class on a tags. :hover on a div or other tag will not be interpreted by those browsers.
If compatibility is a consideration, use the :hover else I believe there is no difference.
First, for your "same effect", it depends on what do you apply to.
Because some elements by default have "cursor: pointer" property such as
anchor tag
While the following elements by default have "cursor: default"(no pointer)
input type: submit
Take stackoverflow.com "Post your answer" as an example, it is a submit button with "cursor:default" by default, user's perception might think a clickable object is displaying "pointer", so it is styled with "cursor:pointer"
As a quick conclusion with my experience, there is no best practice, but rather, depends on the purpose. For clickable object but it is not display as "pointer" by default, you may style them with "pointer".
When you disabled something, eg when you activate something then enable an anchor link, you may use something like
/* the a is only for illustrative purpose */
a.disabled{
cursor: default;
}
a.enabled{
cursor: pointer;
}
Because cursor is a matter of visual presentation, related to user experience design(UX).
This is a long shot, but is there a tool available that optimizes CSS selectors by removing unneeded specificity?
I find that when I write CSS, I deliberately make my selectors more specific than necessary to avoid conflicts and for quasi-documentation.
It would be great if there were a tool that could analyze a given group of rules, determine their "uniqueness" in terms of overlap with other rules, and then strip away any unnecessary specificity.
I can't even begin to imagine how a tool developer would approach all of the scenarios this would require, but I've been blown away by others' ingenuities in this area before and figured it was worth asking.
Update:
I've added a bounty to this question, and the more I think about it, the more I realize how valuable a CSS Specificity Filter would be.
For example, when working with Nested Rules/Selectors in Sass and LESS, excessive nesting is a common and well-known antipattern that can easily lead to overly specific selectors.
There's a good illustration of this in the excellent TutsPlus course Maintainable CSS with Sass and Compass:
body {
div.container {
p {
a {
color: purple;
}
}
}
}
Sass will follow these nesting instructions and produce the following CSS output, raising no objection to any unneeded specificity:
body div.container p a {
color: purple;
}
If a Specificity Filter did/does exist, however, it would create potential benefits for CSS developers:
You could organize your stylesheets as a 1:1 mapping of the DOM, similar to what you see when you examine style rules in Firebug and Chrome Dev Tools. A smart editor/IDE could auto-populate styles for DOM elements with shared styles/classes. That redundancy would then, of course, be filtered out by the Specificity Filter/Optimizer.
Stylesheets could have their structure pre-populated by a tool that scans the DOM and translates it to CSS selectors/rules. This means a developer would only need to update the HTML; the CSS "tree" would be kept in sync to reflect the current state of the DOM. A smart editor would let you jump to the CSS definition for an element/class for styling -- or even make its style rules visible in a separate panel.
In a way, this almost seems like a step backward - like a feature you'd find in Dreamweaver or WebAssist to help newbs learn CSS. But the basic idea of a CSS selector optimization tool seems like a no brainer, and the type of workflow automation I've described would be the logical next step -- and the catalyst would be the Specificity Filter.
I looked into some of the better-known CSS editors and web IDEs, but haven't found anything offering this type of functionality beyond targeting a single element and generating a selector for it.
Update 2: CSS Selector Performance
In response to Spliff's comment, here are two great articles on CSS selector performance:
Performance Impact of CSS Selectors by Steve Souders
Efficiently Rendering CSS by Chris Coyier
Both agree that micro-optimizing CSS isn't worth the effort, but that over-qualified descendant selectors are "an efficiency disaster." I haven't benchmarked yet myself, but suspect that the kind of "DOM Mapping" approach I'm suggesting would cause a performance hit without an optimization step, either manual or automated.
Related Questions, Links, and Tools:
Points in CSS Specificity
Tool to See CSS Specificity
Tool for Cleaning Up CSS
Order by CSS Specificity
Top 5 Mistakes of Massive CSS
Google: Efficient CSS Selectors
Procssor
Clean CSS
CSS Tidy
You could attempt to take a different approach, try to write your selectors as small (low specificity) as possible. and only make them more specific when needed.
With that way of working you don't need a tool.
Just going to throw this out there-- it doesn't 'answer' your question,but it's a tool I like to spread the word about for people who do a lot of css programming: Firebug.
If you're not familiar with it, it's a tool for web browsers. You pull up your page once it's installed, right click and select 'Inspect Element.' It will show you all css affecting different elements on your page, and is useful for creating clean, precise css code. Also it makes it easier to see instant updates on what your page would look like with slight modifications. It will inform you of useless css code that's being overridden by other css code.
ALSO! Firebug now is available for almost all browsers. Not just Firefox. Personally, I'm partial to using it in Chrome.
We really can't do without specificity because it is the only thing that saves you when you have two or more rules colliding. Specificity brings sanity to the whole jumbled CSS rule, so it is more of a blessing than curse. Some of the stuff you talked about, like the CSS selector, can be done using Firefox/Firebug. I'm more disturbed by browser compatibility.
Actually there's a way you can do this using HTML5 and CSS3. The standard technique is to specify elements using the HTML 5 attribute "data-" and then do CSS selection for this attribute. This isn't the purpose of the attributes, but you can customly specify some elements that you can use to even switch the theme of a site.
So, for example, you can end up creating your specificity filters manually in CSS, by specifying
<b data-specificity=2>test</b>
where data-specificity only matches to parents above.
UPDATE:
Alright, so for example, let's say you have a paragraph class, but you want to specify which parent, or how many parents the paragraph can inherit properties from. You would use rules for each potential parent that can be inherited from:
p[data-specificity="1"]{
color:red;
font-family:verdana;
text-decoration:underline;
}
p[data-specificity="2"]{
color:black;
font-family:arial;
}
div.container > *[data-specificity="2"] {
font-family:impact;
color:blue;
text-decoration:underline;
}
So these rules mean that any p tag which is a direct child of the div container and has specificity 2, is allowed to inherit properties from the div container. The blue color of the div gets inherited by the p with data-specificity 2.
Here's a JSFiddle where you can see this!
The idea is that like this, using HTML5, you can control exactly which elements are allowed to inherit which properties. It's a lot of extra code to write (for both child and parent elements) but you can use this to get rid of some unnecessary specificity
I've never actually seen anyone use this method in practice, I pretty much just cooked it up for you, but I think it could be very useful, what do you think ?
I didn't see anything on here about it with a quick search, if there is let me know.
Here is an example of a CSS selector I'd write.
div#container div#h h1 { /* styles */ }
div#container div#h ul#navi { /* styles */ }
div#container div#h ul#navi li.selected { /* styles */ }
I write all my CSS like. This allows me to stop from having styles floating around and I can technically re-use the same class name easily. For instance, I might use .selected on multiple elements across the site.
I also specify the element type (div, ul, etc) before the class/id unless the style is used for multiple elements. I also specify the element before id's even though there will only ever be one id because it allows me to know the element easily when reading my CSS. For instance I'll know right off the bat that em#example will most likely have a font-style of italic.
This isn't a question about CSS formating, it's about writing selectors.
I'd love to hear opinions on this approach, as I've used it for years and I'm reevaluating my stying.
Although it's somewhat off topic I also write my selectors like this for selector libraries (like jQuery for instance). Although I haven't looked into jQuery's internals to see if there is performance issue with specifying the element with an ID.
I think it really depends on what the selector is for.
Almost every site has one or a few style sheets that "skin" the site - fonts, text colour, link colour/hover, line spacing, and so on, and you don't want these selectors to be very specific. Similarly, if you have a component or element that's reused in many pages and always needs to look the same - like let's say the tags right here on SO - then it's going to be a pain to maintain if you use selectors based on the ID.
I would always use the ID in the selector if it refers to a specific element on a specific page. Nothing's more frustrating than trying to figure out why your rules don't seem to be working because of a conflict with some other rule, which can happen a lot if everything is classes. On the other hand, I think that nesting the IDs as you are (#container #h) is redundant, because the purpose of an ID is to be unique. If you have more than one element with the same ID on the same page then you can end up with all sorts of problems.
It does make the CSS slightly easier to understand when your selectors provide some idea of the "structure" that's being represented, but, to be honest, I think that goes against the idea of separation of concerns. The #navi might be moved outside the #h for perfectly legitimate reasons, and now somebody has to update the style sheet for #navi, even though nothing about it has changed.
A bit subjective as Darrell pointed out but that's my two cents.
While the question is a little subjective I have to say I agree with your thinking. I think defining the element before the selector is clearer when reading the code and it is less error prone.
Should the following be shunned, or praised for its simplicity?
For the record, I use it in every site I build, but I've noticed it's not present in many main-stream CSS-reset frameworks — is there a reason they don't use it too?
* { margin: 0; padding: 0; }
Its best NOT to use it as it causes issues with form elements, especially input buttons and select boxes.
See christianmontoya.com
The universal selector can slow things down quite a bit, especially on some WAP browsers. Just think about it for a second: it matches every single element in the document tree.
Besides, for most elements, you'll go on and specify a margin/padding that is different from 0 anyway. As in, there's no point in resetting them for all elements to begin with.
Something you definitely don't want to do is use relative sizes with the universal selector. Things get weird really quick if you do. ;-)
For a good baseline to work from, I'd recommend a tried and tested reset stylesheet.
I once did some performance testing between the * {margin:0;padding:0}, Eric Meyer's reset, the YUI reset and no CSS at all. The performance difference was negligible.
That said, I now use Eric Meyer's reset so I don't lose the formatting on input buttons which actually makes buttons easier to style cross-browser.
If your intent is to set the padding and margin of every single element, then there should be no problem with that selector.
There's nothing particularly wrong with it. * is referred to as the "universal selector", and browser support for it is generally considered to be good, though IE does have some obscure bugs, as usual:http://reference.sitepoint.com/css/universalselector#compatibilitysection
I consider it an important first step in building my CSS layouts. It removes a lot of the troublesome default styling of different browsers and allows me to get more browser-independent results.
Of course I couple it with IE's conditional comments to write IE-version-specific divs around my whole page, and use those to work with IE's bugs (as FF et. al. tend to be more accurate to CSS spec).
EDIT - and I've never noticed any performance problems with it.