undetected Selenium
undetected Selenium

Reputation: 193108

How to write a CSS Selector selecting elements NOT having a certain attribute?

How to write a CSS Selector selecting elements NOT having a certain attribute?

I have 2 <div> nodes as follows:

I need to select the <div> (with the similar class) and each of them which have a similar descending <button> but without the style attribute.

XPath seems working fine as:

//div[@class and not (@style)]/button

I am looking for an equivalent CssSelector.

Trials:

div[class :not(style)]>button (doesn't works).

I have been through the following discussion but they seem to be discarding the class attribute as :not([class]) as in:

I was looking in similar lines ending with :not(attribute).

Upvotes: 13

Views: 11679

Answers (4)

Ratmir Asanov
Ratmir Asanov

Reputation: 6459

I think more accurate CSS Selector is:

div[class]:not([style])>button

because the button element is a child of div element.

Hope it helps you!

Upvotes: 18

John Fantastico
John Fantastico

Reputation: 316

I do not understand how the situation developed in the first place, where the structure of the page necessitates the CSS rules to be aware of whether "style=..." exists in the document itself. Or even why style=... is being used.

The style attribute is old-school now, pre-CSS I believe. It also takes precedence over anything in the CSS. That attribute does not accept CSS class names. It accepts only native html style properties like "width","height","font" - old-school stuff - ultimately those are what your CSS resolves to, no matter how fancy or obfuscated it is through frameworks: font, width, left, top, float.. and so on.

By use of the class attribute (instead of style) in the document you get infinite control from which to write smart selectors in your CSS.

You can put 3 classes in the class attribute of your div for example, if you want, and have your selectors apply styling to it if 2 of the classes are present but not if all 3 are there. Tonnes of flexibility, no need to override or use "style=..." in the document at all.

Upvotes: 3

Adam Genshaft
Adam Genshaft

Reputation: 824

That's the code you're looking for:

div:not([style]) button{
  background-color: red;
}

Now let's break it down. We have have four selectors in this example:

  1. div and button - these select html elements. We can replace it for example with a class selector like .weEq5.
  2. :not() - indicates that we want everything that does not qualify as the selector inside the brackets.
  3. [style] - an attribute selector which is very powerful. We can place inside the not any other css selector like html tag names (button or div), class names or ids.

The combination of div:not([style]) means that we want all divs that do not have a style attribute. After which we have a space and a button means that we want all the buttons that are inside the above selector.

Adding a > before the button div:not([style]) > button will only select button elements which are direct children of the selected div. It will exclude from selection buttons that are deeper inside the div.

Upvotes: 13

BoltClock
BoltClock

Reputation: 723688

Normally, you would write :not([style]) to match an element that does not have a style attribute, as described here which emphasizes the use of both () and [] brackets, in that order.

But if this isn't working in Selenium WebDriver, and worse still if :not(style) works exactly like how I would expect :not([style]) to, then that's a bug with its CSS selector parser, since :not(style) actually means "not a style element" which makes div:not(style) redundant as an element can only either be a div or a style but not both at the same time. Unless you absolutely require a selector, I strongly recommend using the XPath locator strategy instead of relying on quirks like this with Selenium WebDriver's CSS selector engine that force you to write selectors that are both incorrect and don't work anywhere else that accepts a selector.

Upvotes: 4

Related Questions