While the container and link colors for contextual links is well defined, the contextual links have specific selectors like "div.contextual-links-wrapper ul.contextual-links", which are hardly ever overwritten by accidental CSS declarations. However, the actual link color has "ul.contextual-links li a", which is easily overwritten by more specific link color specifications. In my case, those would be simple "#footer a" or "#header a", which by the virtue of ID selectors overwrite the class selectors used in contextual.css.
The effect is that because I have white colors in the header, the links in the contextual menu will be white as well:

If we make the link color important to sidestep this specificity problem, the links colors will be right, and I can use the contextual menu again.

It's a very simple patch.
| Comment | File | Size | Author |
|---|---|---|---|
| #14 | contextual-important.patch | 678 bytes | gábor hojtsy |
| #13 | contextual-important.patch | 591 bytes | robloach |
| #9 | 675608.patch | 749 bytes | robloach |
| #8 | 675608.patch | 103.81 KB | robloach |
| #3 | contextual-less-selectors.patch | 690 bytes | robloach |
Comments
Comment #1
gábor hojtsyAnother option could be to add classes to the links inside the ul.contextual-links, so we can improve the specificity of these selectors. I did not try that. (The links already have plenty of classes but none of which is on all of them).
Comment #2
David_Rothstein commentedComment #3
robloachIt is usually not recommended and bad practice to use !important. It's also not implemented in IE7. A way around it is to add more selectors for the overriding property, or remove some not needed selectors on the original CSS definition.
Here's an attached patch that removes some selectors on the original property that we don't really need so that the overriding property take precedence. This means that themes don't need to drill down as deep as four selectors to override the property.
Comment #4
dries commentedWould be great if Gabor could test Rob's patch.
Comment #5
gábor hojtsyRob did you try adding
#footer a { color: #fff; }into your theme and place a block in the footer? The problem is that#footer ais already more specific then the contextual.css selectors, so making those selectors less specific does not sound right.You seem to be advocating that themes fix this specificity problem, but why would they need to if we can provide more sensible defaults? As I've said, we could add one more class on all links and try to make the selector more specific with that.
Comment #6
gábor hojtsyRob?
Comment #7
ejort commentedI think the original approach from Gábor was correct. We want the contextual link styles to not be overridden in a way that makes the interface unusable in situations as common as adding a style such as
#footer a { color: #fff; }.While I agree that
!importantis generally evil, I think this is a valid use case. The !important declaration in the original patch should also work as expected in IE7 (and even IE6, its bugs with!importantdon't stop the rule taking effect in simple cases like this). It's also still possible to override an!importantstyle declaration from a theme by providing your own!importantstyle declaration with a higher specificity (for those who want to opt in to overriding these styles).Comment #8
robloachOkay, I have a better understanding now. The problem is that it is too easily over-ridable by the theme. It was the opposite direction that I thought it was going. If we add another selector to the contextual.css definition, then that one will take precedence over other definitions that have three or less selectors in it and we can avoid !important.
Thanks all!
Comment #9
robloachWhoops, created the patch incorrectly. Haven't had coffee yet.
Comment #10
ejort commentedHi Rob,
Unfortunately the last patch still doesn't fix the given problem with a selector such as
#footer a { color: #fff; }(which is a common example). The specificity of a CSS selector is calculated as: (number of elements) * 1 + (number of classes) * 10 + (number of ids) * 100.So,
.contextual-links-wrapper ul.contextual-links li ahas a specificity of 23, while#footer ahas a specificity of 101.We'd need to add 10 extra classes to the selector to equal the specificity provided by a single id. For this reason, and because it is undesirable to accidentally restyle these links I think
!importantis justified in this case. It can still be overridden easily by theme's if they want to, but protects against accidentally overriding the style and forcing theme developers to redeclare the contextual links styles throughout their themes.Comment #11
gábor hojtsy@ejort: does this mean RTBC for the first patch?
Comment #12
ejort commentedA short comment on the reason we're using
!importantin this place would be good as it can be a bit of a developer WTF. But other than that I think this is RTBC.Comment #13
robloachThat's a shame. I didn't know identifiers had such importance in the cascade. I thought it was just based on the number of selectors, but it seems I was wrong. Do you have any more information, or a link on how the weighting is made? Thanks!
Comment #14
gábor hojtsyHere is a version with a code comment as dicussed. It would be good to wrap this up and get it in :) We have bigger fish to fry.
Comment #15
robloachWorks with me! It's unfortunate that we have to have !important CSS in Drupal core, but if it helps the Drupal 7 Themer Experience, then I'm alright with that.... #D7TX? ;-)
Comment #16
dries commentedCommitted to CVS HEAD. Thanks.
Comment #17
xmacinfoOh my, this is the first instance I see where we really need to set !important either in Drupal core or any theme I do. :-)
Adding an ID to each "contextual-links-wrapper", like we do for blocks, would make things harder.
Comment #18
xmacinfooups
Comment #20
sun#730754: CSS coding standards: No !important in core/contrib modules, ONLY IN THEMES
So we've put an !important into core, just because someone wrote a buggy theme, which doesn't support the modules being installed?
Comment #21
eclipsegc commentedYes this definitely looks like it's the responsibility of the theme, not the module. Set it back, the theme author should just have a #footer ul.contextual-links li a {} selector in his css file, or better yet a #page ul.contextual-links li a {} selector that will overwrite ALL of these links.
#page ul.contextual-links li a has a specificity of 1,1,3
vs
#footer a of 1,0,1
So the first will win for ALL contextual-links in the entire system at ALL times unless someone does something more specific (which is unlikely).
Eclipse
Comment #22
jacineYeah, EclipseGc is right. There are a few ways to resolve this, and it belongs in the theme.
Comment #23
gábor hojtsyI'm glad people with better ideas came around. Patches are welcome :)
Comment #24
barraponto@EclipseGc: please don't. You can't rely that #page will be there in the first place, the theme can override that (although they could re-implement this declaration, but what if we apply this approach elsewhere?). We can't use #identifiers for the links since they wouldn't be unique, so I guess we are doomed.
Sanity check: why are we using #footer id in the first place? I know it is unique within the scope of the document, but it would make more sense to preserve ids for things like #node-1234, where I might use it to override the default .node properties.
So I guess this would be: #page .selector for D7, rethink the usage of ids for D8. Also, RobLoach approach is right: if the selector is not needed, remove it. In the end, they should look like:
I have just read the CSS Code Standards http://drupal.org/node/302199 and there's nothing about "removing unnecessary weight". So I don't know whether I should patch for that, even though the CSS file uses .contextual-links or ul.contextual-links randomly.
Comment #25
barrapontotypo.
Comment #26
barrapontoAdding DTX to avoid remember this bug even if it lingers until D8.
Comment #27
jessebeach commentedThis issue will be resolved in: #849926: links wrapped in .contextual-links-wrapper divs are not accessible at all via keyboard alone also problems with screen readers