Greedy css :not() selector - css

Is there a way to match an element that has no parent with specific selector ?
Specific use-case:
Theme is defined using 'theme' attribute.
It's required to have some part within the application with different theme.
So the DOM structure is something like:
<div theme="theme-A">
// ... theme-A content
<div theme="theme-B">
// ... theme-B content
</div>
// ... theme-A content
</div>
Components have a css for each theme, example:
[theme=theme-A] .my-component{...}
[theme=theme-B] .my-component{...}
My attempt of solving the problem was to prevent intermediate themes like so:
[theme=theme-A] :not([theme]) .my-component{...}
[theme=theme-B] :not([theme]) .my-component{...}
But this approach doesn't work because there are other elements without 'theme' attribute in the way.
I assume I need a kind of 'greedy' :not selector, which means "no elements at all matching the condition".
Is there such a selector or trick ?
Any other suggestions / directions to try ?
Thanks

Related

CSS BEM syntax without element class name

I have to create a primary heading component, below is my markup along with CSS classes. I'm following BEM naming convention for class name.
I have h1 element consists of two spans. One span for main heading text, and second span for sub heading text. The main and sub are variations of my heading.
I have not specified the Element class (Which could be heading-primary__text ) and i have directly attached modifier classes to span elements.
<h1 class="heading-primary">
<span class="heading-primary--main">Video Background Option</span>
<span class="heading-primary--sub">One Page Parallax</span>
</h1>
Is that a right way to follow BEM methodology without specifying Elements classes & attaching Block's modifiers classes to Elements(span)? Because i don't need elements classes.
Is there any alternate?
While this is subjective, and as per the convinience of the project . i'd recommend doing something like this- as you already have a header-primary_text element class
<h1 class="heading-primary">
<span class="heading-primary_text">Video Background Option</span>
<!--create a modifier -->
<span class="heading-primary_text--sub">One Page Parallax</span>
</h1>
In this way you can make the sub a modifier class for the subtext.
More info can be seen here https://en.bem.info/methodology/quick-start/#modifier
Hope this helps :)
I think there is a much simpler way to do this just using basic HTML. You only want to have one h1 per page and since you said that your second span of your h1 is a "subheading" I feel like you would be way better off marking that one as an h2 instead of two spans of different context within one h1 heading! Always good to use the built in benefits of HTML first if you can.
No, it is not the right way. You cannot use block (or element) modifier alone on the HTML tag without specifying the block (or element) class itself.
Please refer to BEM documentation here: https://en.bem.info/methodology/quick-start/#modifier
A modifier can't be used alone From the BEM perspective, a modifier
can't be used in isolation from the modified block or element. A
modifier should change the appearance, behavior, or state of the
entity, not replace it.
Here is a code example from the docs:
<!-- Correct. The `search-form` block has the `theme` modifier with the value `islands` -->
<form class="search-form search-form_theme_islands">
<input class="search-form__input">
<button class="search-form__button">Search</button>
</form>
<!-- Incorrect. The modified class `search-form` is missing -->
<form class="search-form_theme_islands">
<input class="search-form__input">
<button class="search-form__button">Search</button>
</form>
You mentioned that you don't need an element class, this topic is also covered in BEM docs
https://en.bem.info/methodology/faq/#why-include-the-block-name-in-modifier-and-element-names
semuzaboi's suggestion sounds as a good alternative to me.
First of all, elements are specified after two __ like block__element_modifier.
Secondly, yes. Blocks may not have any elemenets inside, but rather have modifiers (most common case a block with lang modifiers for Internationalization (block_lang_ru))
PS as well as element may not have any modifiers inside. But block can not be nested inside another one. They should be placed inside one directory on the same level.

Select elements with same attribute value

Is there any way to select elements with same attribute value which I don't exactly have access to? I imagine doing it in way like this:
.first[attribute=.second[attribute]]
I want to use ONLY pure CSS.
no, there is no way to achieve this using css
however, if you need to do something like this you should consider changing your markup (ex. using additional classes) - css is not a programming language
CSS cannot do that. For comparing two elements you need to have access to DOM.
We cannot achieve this through css but this can be done by JavaScript:
window.onload=function(){
var attr = 'elementValue',
elements=document.querySelectorAll('.first, .second');
console.log(
elements[0].getAttribute(attr) ===
elements[1].getAttribute(attr)
);
}
<div class="first" elementValue="1">hello</div>
<div class="second" elementValue="1">hello</div>
Hope this helps

How can I select an element by an attribute set on its parent using CSS 2.0 selectors?

I have a HTML like this in my QWebView
<div class='a' id='root'>
<div id='x'>...</div>
<p> ...
<p>
...
<div id='x2'>...</div>
<div>
<a href='go/xxxx'>go</a>
</div>
</div>
How do I select the a? I tried this selectores:
div[id='root'].a
div[id='root'] + a
but it didn't worked. Code:
QWebFrame* frame = webView->page()->mainFrame();
QWebElement button = frame->documentElement().findFirst("div[id='root'].a");
assert(!button.isNull()); // gets executed
Your selector is selecting the div with id='root' and class='a'. If you want to select the a tag inside of that div, you need to make your selector:
div[id='root'].a a
The additional 'a' at the end of the selector tells jquery to select the a inside of the div.
You can switch to using XPath 2.0 in Qt to have more expressive freedom, but then you need to process your HTML as XML.
To resolve, add a descendant selector1 for a. I.e., change this div[id='root'].a into this:
div[id=root].a a
As an alternative, if there's a bug in Qt, try:
div[id=root][class=a] a
Or (which is potentially a bit wider):
div[id~=root][class~=a] a
These last two are just alternatives in case for some reason the original fix to your code (adding the a descendant selector) didn't work.
The code snippets above doesn't use quoted strings, this is optional.
1 adding a was seen in stevenc4's answer), after my original (wrong) solution. Kudos to him :)

Applying css parent div

I tried searching for option to apply css to parent div but failed to achieve it. I finally implemented the same with jquery. Do we have any option for the below jquery line to implement with css
$('.description').parent().prev().closest('div').css('padding-top', '10px');
Currently no, there is not. This is similar to a previous thread -
Is there a CSS parent selector?
However, you could just apply a class or id to your parent and select it in CSS using that newly set class/id.
Assuming your html looks a bit like this:
<div>
<div class="description">
............
</div>
</div>
Then the jQuery to target the parent of 'description' would be:
$('.description').parent().css('paddingTop', '10px');
Fiddle here: http://jsfiddle.net/EFmf8/
(changes colours instead of padding to better illustrate)
Pity there's no CSS selector for this . . .

Substring Matching within a paragraph using CSS

I have a <p>Example string</p> With some text inside. I want to use css to search for a word within that paragraph.
I know this is possible if you have e.g. All you have to do then is:
a[href*="test"]{}
But when I try to do this with my paragraph I can't seem to get it to work. I've tried:
[p*="string"]{}
p[*="string"]{}
The short answer is NO, this is not possible using CSS only, what you are using is element[attr=val] selector which only selects elements with that particular attribute with that specific values. You need to use jQuery or Javascript with a regex to track the pattern and apply styles to its elements.
On the other hand you can create custom attributes with a prefix of data- so for example you can do something like
<p data-custom="Holder Text">Want to change this</p>
<p data-custom="Holder Text">Want to change this</p>
<p data-custom="Holder Text 2">Dont Touch This</p>
p[data-custom="Holder Text"] {
color: red;
}
Demo
But again, this won't make sense here, you can simply assign the classes if you are aware what elements need to be changed.
You cannot this using CSS only, however you can check this blog post about how to achieve this using jQuery.
Basically you should use :contains selector:
$("p:contains('John')")

Resources