How style the element before specified one - css

We all know how the adjacent selector works (p+p), but I wonder if there's an option to style an element that appears just before the specified one? For example:
<p id="one"></p>
<p id="two"></p>
I would like to style the first element that appears just before the p#two. How to do this without JS?

In CSS4 it will be possible to specify the element to which the style applies (not just the last the last element in a selector). CSS Selector Level 4 So in the future this should work:
p! + p { /* your styles here */ }
However, as far as i know, no browser does support them right now.

Related

Is the CSS :not() selector supposed to work with distant descendants?

Here is the official documentation for the CSS3 :not() pseudo-class:
http://www.w3.org/TR/css3-selectors/#negation
and the proposed CSS Selectors Level 4 enhancement:
http://dev.w3.org/csswg/selectors4/#negation
I've been searching the implementation and browser support for :not(), but the only examples I found were with a single element or with a direct child of an element, e.g.:
div *:not(p) { color: red; }
The example above works when <p> is a direct child of <div>, but it does not work when <p> is a more distant descendant of <div>.
div :not(p) {
color: red;
}
<div>
<ul>
<li>This is red</li>
</ul>
<p>This is NOT</p>
<blockquote><p>This is red but is not supposed to be!</p></blockquote>
</div>
If the answer is in the official documentation above, then I didn't find/understand it. As I said, I have searched this site and the web but couldn't find any discussion about the support or lack thereof of :not() as grand-children of another element.
Is this supposed to work like I think it should?
Is this supposed to work like I think it should?
No, the behavior you're seeing is correct.
In your last example, although the <blockquote> contains a <p>, it's the <blockquote> itself that's matching *:not(p), as well as the condition that it must be a descendant of the <div>, which it is. The style is applied only to the <blockquote>, but it is then inherited by the <p> inside it.
The <p> element itself still counts against the negation, so the <p> itself is still being excluded from your selector. It's just inheriting the text color from its parent, the <blockquote> element.
Even if none of its relatively close ancestors matched the selector, you have elements like html and body to worry about as well — although you could probably just tack on a body selector in the very beginning:
body div...
This is why I often strongly advise against using the :not() selector for filtering descendants, especially when not qualified with a type selector (like div in your example). It doesn't work the way most people expect it to, and the use of inherited properties like color only serves to compound the problem, on top of making it even more confusing for authors. See my answers to these other questions for more examples:
Why doesn't this CSS :not() declaration filter down?
CSS negation pseudo-class :not() for parent/ancestor elements
The solution to the problem described is to simply apply a different color to <p> elements. You won't be able to simply exclude them with a selector because of inheritance:
/* Apply to div and let all its descendants inherit */
div {
color: red;
}
/* Remove it from div p */
div p {
color: black;
}
On Selectors Level 4: yes, :not() has indeed been enhanced to accept full complex selectors that contain combinators. Essentially, this means (once browsers begin implementing it) you will be able to write the following selector and have it do exactly what you want:
p:not(div p) {
color: red;
}
In case anyone is interested, this works in jQuery today.
The color is assigned to the blockquote, and is then inherited by the p.
:not(p) just makes it so that the styles are not directly applied. They are still inherited though.

Css selection dependent on different selector's condition

Is it possible to define css class behaves dependent to an other css class?
For example; when
a:hover
Then I want to set
p {background:#fff;}
Is this possible with pure css?
Edit: Assume that no nested relation exist.
If you mean you want all p to have that style when a:hover regardless of where they are in the DOM, then no, you can't do that. You'll need to use a script to apply the style (or some class containing that style) to the p elements when a receives a hover.
if you have a structure like this:
<a><p>...</p></a>
then this:
a:hover p {background: #fff;}
will work. However, block elements should not be placed inside inline elements (in this case, no <p> inside <a>
if your markup is valid, and looks like this:
<p><a>...</a></p>
then you could have
p:hover {background: #fff;}
but a descendant can't affect the parent css (unless you use javascript) while the opposite is true (parent css affects descendants)
I do not see why you would be limited to these restrictions with a littl creativity. if you use fixed positioning the descendant can overlap its parent. and still respond like a descendant.
If the <p> tag immediately follows the <a> tag then you could use the adjacent sibling selector e.g.
a:hover+p{
background:#fff;
}
This is supported in IE8+

How to style parent when parent contains specific child?

I have some html that looks like this:
<div id="parent">
<div id="child"></div>
</div>
I want to apply a default background color to #parent except for when it contains a #child.
So the CSS should end up looking something like this:
#parent {
background: red
}
#parent:contains(#child) {
background: none
}
However, I can't get the :contains pseudo selector to work that way. Is there a way to achieve this?
:contains() was only intended to match elements containing certain text, not elements containing certain other elements. It is because of the complications associated with matching elements by text that there were almost no browser implementations, leading to :contains() being dropped from the spec.
Since there is no parent selector in CSS, and :has() (which does look at elements) only exists in jQuery, you won't be able to achieve this with CSS yet.
For the record, jQuery implements :contains() as well, but it does so according to the old spec, so it uses the name :has() for elements instead.
With jquery
if($("#child").length>0) $("#parent").css("backgroundColor","#fff");
Its not possible with pure css.

CSS: Using two adjacent selectors to select element after adjacent element

How can I do something like this?
element + adjacent_element + element_to_style {
/* somestyle */
}
I want to style an element that's adjacent to the adjacent element.
EDIT:
This code works properly, I just forgot the . before the classnames. That's why it didn't work.
There is ~ general sibling selector. But is css3 so the browser support is limited.

What is appropriate ordering of css selector? eg p.class or .class p

While debugging some css i noticed there is a difference between this order of declaration. The first caused headings inside anchors to display inline as desired, the second seems not to:
1/ a.aname { display:inline; margin:0px;}
2/ .aname a { display:inline; margin:0px;}
<a name="download" class="aname"><h2>Download</h2></a>
I have mostly been using the second form to apply class styles.
What is the difference in how these are applied, and are there any guide rules when to use each? (to avoid the css-puzzlement which arises when it's done wrong)
Basic solution from answers:
Use "direct selection" elementtype.class{} or elementtype#id{} to apply style to elements directly. For styling which is intended to affect once each time the rule is used eg. a margin change, a display change, a noninheriting font change. Direct selection does not inherit to child elements, it is applied to parent element only.
Use "descendant selection" .class elementtype{} or #id elementtype to apply style to type descendants/children of the named or classed element. For styling which is intended to change appearance of elementtypes under an element/within a section of page where it is applied eg. inheriting font changes to text sections, inheriting format changes to paragraphs or list elements. Descendant selection applies to all child elements but never the parent.
NBself: learn about other selectors too asap ;)
The difference is the space between them, which is the descendant combinator in CSS.
The selector a.aname will match an anchor element with the class aname while the .aname a will match an anchor element that is a descendant of an element with the class aname:
<a class="aname">This matches the first rule</a>
<span class="aname"><a>This matches the second rule</a></span>
CSS combinators:
space = descendant combinator
> = child combinator (direct descendant)
+ = adjacent sibling combinator
The Selectutorial gives a pretty good overview or selectors and combinators.
If you use selectors where you can put identifiers together without combinators between them, the order doesn't matter. Example:
#id.class { ... }
.class#id { ... }

Resources