Simplifying long CSS selectors - css

I have the following CSS selector:
#AllContextMenus :not(.menu-iconic-left):not(.menu-accel):not(.menu-accel-left):not(.menu-accel-container):not(.menu-accel-container-left):not(.menu-iconic-accel):not(.menu-right)::before
For readability purposes, I like to keep all code lines under 100 characters.
Is there any way to simplify, optimize, or write this CSS selector without changing what it matches and without reducing performance?
For example, is there any type of "and" operator that can be used within :not()?

You generally can't simplify a selector without changing the semantics of what it matches.
But you can break a selector up into multiple lines at many points to meet maximum line length requirements. Just use a comment and put the line break inside the comment. Like this:
#AllContextMenus :not(.menu-iconic-left)/*
*/:not(.menu-accel)/*
*/:not(.menu-accel-left)/*
*/:not(.menu-accel-container)/*
*/:not(.menu-accel-container-left)/*
*/:not(.menu-iconic-accel)/*
*/:not(.menu-right)::before
#AllContextMenus :not(.menu-iconic-left)/*
*/:not(.menu-accel)/*
*/:not(.menu-accel-left)/*
*/:not(.menu-accel-container)/*
*/:not(.menu-accel-container-left)/*
*/:not(.menu-iconic-accel)/*
*/:not(.menu-right)::before {
color:red;
content:'TEST '
}
<section id="AllContextMenus">
<div class="a">A</div>
<div class="menu-iconic-accel">menu-iconic-accel</div>
</section>

Related

What does this CSS (|=) mean? What is it called?

I have some code that looks like
[class|="e"]
{
margin: 0 0 0 0;
}
What does this the |= mean? What should I be googling for?
I tried searching stackoverflow (which can find punctuation) and Google but its hard to search without a name.
That is known as an attribute selector. Specifically, the |= attribute selector looks for elements with the given attribute, whose value exactly matches the given value or starts with the given value immediately followed by a - (a prefix, if you will).
Your selector matches elements with a class attribute with a value that:
is exactly e, or
starts with e-.
It's equivalent to the combined result of the following two attribute selectors:
[class="e"], [class^="e-"]
Note that |= is typically used with language attributes such as hreflang and lang, although in the case of the latter, :lang() is often preferred — this answer explains the difference between the two.
You can use |= with any other attribute, but be careful when using it with the class attribute, because it ignores multiple space-separated class names — it always looks at the entire attribute value or the very beginning of the value, rather than each individual class name.
As an example, the following elements will match your selector because e and e-c occur at the very beginning of the attribute value:
<div class="e"></div>
<div class="e-c"></div>
<div class="e-c f"></div>
However, neither of these elements will match your selector, because the value starts with f:
<div class="f e"></div>
<div class="f e-c"></div>
If you need to match a class prefix on elements that can potentially have multiple classes, I recommend using a different set of attribute selectors instead:
[class^="e-"], [class*=" e-"]
This will match all of the .e-c elements listed above. See this other answer for an explanation.
[class|="e"]
{
margin: 0 0 0 0;
}
Selects all elements whose class attribute contains values that are exactly "e", or begin with "e-".
And some examples:
<div class="e"></div> MATCH
<div class="ea"></div> DOESN'T MATCH
<div class="e-a"></div> MATCH
<div class="ae-"></div> DOESN'T MATCH

How to convert complex xpath to css

I have a complex html structure. New to CSS. Want to change my xpath to css as there could be some performance impact in IE
Xpath by firebug: .//*[#id='T_I:3']/span/a
I finetuned to : //div[#id='Overview']/descendant::*[#id='T_I:3']/span/a
Now I need corresponding CSS for the same. Is it possible or not?
First of all, I don't think your "finetuning" did the best possible job. An element id should be unique in the document and is therefore usually cached by modern browsers (which means that id lookup is instant). You can help the XPath engine by using the id() function.
Therefore, the XPath expression would be: id('T_I:3')/span/a (yes, that's a valid XPath 1.0 expression).
Anyway, to convert this to CSS, you'd use: #T_I:3 > span > a
Your "finetuned" expression converted would be: div#Overview #T_I:3 > span > a, but seriously, you only need one id selection.
The hashtag # is an id selector.
The space () is a descendant combinator.
The > sign is a child combinator.
EDIT based on a good comment by Fréderic Hamidi:
I don't think #T_I:3 is valid (the colon would be confused with the
start of a pseudo-class). You would have to find a way to escape it.
It turns out you also need to escape the underscore. For this, use the techniques mentioned in this SO question: Handling a colon in an element ID in a CSS selector.
The final CSS selector would be:
#T\5FI\3A3 > span > a

Please what is the difference between [attribute~=value] and [attribute*=value]

cannot find the difference between these two selectors. Both seem to do the same thing i.e select tags based on a specific attribute value containing a given string.
For [attribute~=value] : http://www.w3schools.com/cssref/sel_attribute_value_contains.asp
For [attribute*=value] : http://www.w3schools.com/cssref/sel_attr_contain.asp
The first one ([attribute~=value]) is a whitespace-separated search...
<!-- Would match -->
<div class="value another"></div>
...and the second ([attribute*=value]) is a substring search...
<!-- Would match -->
<div class="a_value"></div>
W3Schools doesn't appear to make this distinction very clear. Use a better resource.
[attribute~="value"] selects elements that contain a given word delimited by spaces while [attribute*="value"] selects elements that contain the given substring.
For example, [data-test~="value"] would not match on the below div while [data-test*="value"] would.
<div data-test="my values go here"></div>

CSS, someClass:not(.foo):not(.bar)

In CSS I have to specify a specific class (e.g., .myClass) but exclude instances that have either one of two classes (e.g., not .foo nor .bar).
I looked into CSS3 new :not() syntax, but I am not sure how to specify the two classes that I don't want to use. I believe this is incorrect (it did not work for me). However, it seems like a concise way to show what I am trying to do:
.myClass:not(.foo):not(.bar) {
...
}
Just separate them with a comma:
.myClass:not(.foo, .bar){
...
}
Use a comma in-between them:
.myClass:not(.foo, .bar) {
...
}
Source: http://devsnippets.com/article/5-advanced-css-pseudo-class.html

handling css id and classes with spaces

I have a paragraph as
<p id="para one" class="paragraph one">Content</p>
How does one represent the id and class with spaces in the css
When I use
#para#one{
}
.paragraph.one{
}
It does not work with the css above.
Just came across this one myself (styling an existing page with no way to change the id).
This is what I used to style it by id:
p[id='para one']{
}
And, as said previously, .paragraph.one selects two classes - this means it will also select elements with class=" one paragraph" and class="not a paragraph this one".
Your class CSS is correct. You don't have a class with a space in it, you have two classes, "paragraph" and "one". Your CSS properly selects elements that have both of those classes:
.paragraph.one { color: red; }
This is a useful technique for splitting out facets of the element into separate classes that can be combined individually. Note also that <p class="one paragraph"> will match the same selector.
class="paragraph one"
actually represents two different classes
id="para one"
won't work, but you'll probably end up having an actual id of para
You can't have spaces in id values or class names. When you have spaces in the value of the class attribute it specifies multiple classes that apply to that element:
<p class="paragraph one"> <!--Has both "paragraph" and "one" class-->
As for id values, the rules (HTML4) state the following:
ID and NAME tokens must begin with a letter ([A-Za-z]) and may be
followed by any number of letters, digits ([0-9]), hyphens ("-"),
underscores ("_"), colons (":"), and periods (".").
As you can see, spaces are not valid. The HTML5 spec is more leniant, but spaces are still not allowed (emphasis added):
The id attribute specifies its element's unique identifier (ID). The
value must be unique amongst all the IDs in the element's home subtree
and must contain at least one character. The value must not contain
any space characters.
Modern browsers actually support id with spaces. So on Chrome 54 this works:
p#para\ one {
}
And modern browsers do not support the [id="..."] syntax, so
p[id='para one'] {
}
does not work in Chrome 54.
You simply can't have spaces. If you use a space it means you're using two different classes. One is para and the other one is one.

Resources