NOT first element with a given class - css

I have some code like this:
<span class="item multifilter-wrapper multifilter">
<span class="item multifilter multifilter-item">
<div></div>
</span>
<span class="item multifilter multifilter-item">
<div></div>
</span>
<span class="item multifilter multifilter-item hasdata">
<div>HELLO</div>
</span>
</span>
Any multifilter-item span could have content, if it has content I add the hasdata class, as in the last item.
I would like to add a separator in between 2 multifilter-item spans in case there is more than one with data, so I have this BEFORE rule:
.multifilter-wrapper .hasdata:not(:first-child)::before{
content: '|';
}
However it is adding the content in the example above with just 1 hasdata span.
Any ideas why?

without having to modify your markup, you can use the general sibling selector: ~ (http://www.w3.org/TR/css3-selectors/)
http://jsfiddle.net/ossx1v1k/
.multifilter-wrapper .hasdata ~ .hasdata::before{
content: '|';
}
please note that I've removed the div tags from inside the span tags in my jsfiddle example, because as Paulie_D remarked, it's invalid markup to have block elements inside inline ones.

This is because .has-data is not the the first child, so it matches as expected.
I think you are confused as to what :first-child does. It checks if it is the first child element for it's parent (which it is not as you have 2 other ones before it). It does not check if it's the first child that is also a .hasdata class.
Basically the logic is:
class is hasdata
AND is not the first child element
To which it matches these rules, which is why the content separator is added.
There is no way to identify classes that are the first child with a specific class name in only CSS, you cannot write a rule for "is not the first hasdata class". I suggest you modify the html to have something like notfirsthasdata to identify elements that are not the first ones with content.
There is first-of-type which is the type of logic you want, however I believe this only matches with the element type (in your case span) and not the class name.

Related

How to color first strong element within P tag one color and the rest another color?

I'm trying to get :first-of-type to work for the <strong> HTML element but it won't work.
There can be numerous (random number and placement, but within p tags) <strong> elements but I want the first one to have different text color than the rest.
Here I would expect Hello 1 to be blue and Hello 2 + Hello 3 to be yellow. But they're all blue.
.yolo p strong { color:yellow; }
.yolo p strong:first-of-type { color:blue; }
<div class="yolo">
<p>bla bla</p>
<p><strong>Hello 1</strong></p>
<p>bla bla</p>
<p><strong>Hello 2</strong></p>
<p>bla bla</p>
<p>bla bla</p>
<p><strong>Hello 3</strong></p>
</div>
JS fiddle
Any ideas?
Solution doesn't have to include :first-of-type as long as the HTML remains unchanged.
As mentioned, each <strong> element is the first of its element type in its own parent <p>, therefore both elements match the :first-of-type pseudo-class.
Unfortunately, in this case, you may be stuck. Since the first <strong> element may not necessarily appear in the first <p> element as shown in your markup, you won't be able to use something like .yolo p:first-of-type strong to target the first <strong>. Neither is there a way using CSS to target just the first element in such a structure, since the existing structural pseudo-classes only match the nth element among its siblings, and there is no parent selector so you can't write a selector finding "the first <p> element that contains a <strong> element".
Since your markup is produced by a CMS, you will have to either
tell the CMS to apply a class name either to the first paragraph containing a <strong> element or to the first <strong> element, or
use JavaScript to apply the class name if the behavior of the CMS cannot be modified
then target this class.
From css-tricks:
The :first-of-type selector in CSS allows you to target the first occurence of an element within its container. It is defined in the CSS Selectors Level 3 spec as a “structural pseudo-class”, meaning it is used to style content based on its relationship with parent and sibling content.
This means that this will work:
<div class="yolo">
<p><strong>Strong 1</strong>
<br>
<strong>Strong 2</strong></p>
</div>
But this wont:
<div class="yolo">
<p><strong>Strong 1</strong></p>
<p><strong>Strong 2</strong></p>
</div>
Because in the second example each of the <strong> is the first in its <p> container. But in the first example, the two <strong> tags are both in the same <p> container, so Strong 1 goes blue, being the first one in the paragraph, and Strong 2 goes yellow, not being the the first in the paragraph.

Why are duplicate ID's an error in HTML5 checkup?

I have the following code in HTML:
<span>
<a href="#">
<span class="caption">
<p id="first">Text1</p>
<p id="desc">click to read</p>
</span>
<img class="img_link" src="img/thing1.jpg" width="218" height="181"
alt="thing1"/>
</a>
</span>
<span>
<a href="#">
<span class="caption">
<p id="first">Text2</p>
<p id="desc">click to read</p>
</span>
<img class="img_link" src="img/thing2.jpg" width="218" height="181"
alt="thing2"/>
</a>
</span>
This code is used for making an overlayed text transition for images in CSS, but if I want to validate this HTML code, it says I have a duplicate ID (here "first" and "desc") but I honestly wouldn't know how I can simplify this. I need to resize "first" with font-size, and "desc" too.
For example: the paragraph with id "first" has to be 14px, and the paragraph with "desc" has to be 12px.
Only those <"p"> (without the quote) elements can not be a child element in the "span" element.
I wouldn't know how to solve this, do you guys have a solution?
Thanks for the answers, I've already changed the ID's to a class.
Still, I wouldn't know how to resize class "first" and "desc" in two different font sizes, because it's apparently "not done" to put a block element in an inline element
EDIT 3: Solved! Using div's is the best solution, I'm using this for school (kind of a project) for making a gallery. With float: left; I can place those images next to eachother.
Thanks for the tips!
You've made several mistakes:
id attribute is of type #ID which by the HTML/SGML standard is defined to be unique, if you want to show duplicates you should use class attribute (this is part of why there's getElementsByClassName returning a list but getElementById returning only a single item in the JavaScript DOM API)
span is inline element, while p is a block element, HTML does not allow block element inside inline element. You should replace your span with div. You can use display: inline or display: inline-block if you want it to appear like inline level elements. Example of inline elements include: a, span, etc; example of block elements include: div, p, ul, li, etc.
That is due to the element type.
<p> tag is block level element
<span> tag is a inline element
Therefore encapsulating a block level element inside an inline level element is incorrect.
Because you can use classes.
Change:
1.
id="first" -- into --> class="first"
id="desc" -- into --> class="desc"
2.
You cannot put another tags into a span tag except <i>, <b>, <strong>, and <br /> ...
With <br/ > you can have 2 lines in your span tag
Just change it to:
<p class="first">
and
<p class="desc">
EDIT:
You best remove the spans completely. You don't need them. If you feel you need them to wrap block-level elements, you can do that with divs

css style for :nth-child selector on class includes other elements

Hi smart people of stack, I have this completely unreasonable issue with :nth-child. Its not "locking" on to the specific class Im trying to attach it too.
In my first picture I had to make it skipp the first 3 excessive elements I want to skipp even though I've specified it to apply to the ".pageGrid" class. As you can see the first <hr>, then the <div>, then another <hr> have no class.
My second issue uses the same css as in another place and I had to add a invisible element because the :nth-child is again not applying to only the element I want to apply it on.
What am I missing?! Im really not getting this..
Edit:
Heres some code:
.wrapperProductList .prodListPage:nth-child(4n+1) {
margin-right: 0;
}
The "+1" is to skipp the first element..
.pageGrid:nth-child(3n+3) {
margin-right: 0!important;
}
The "+3" here is to skipp the 3 first element that dont even have the .pageGrid class :(
<div class="clearfix wrapperProductList pageGrid">
<h1>Compact/Stackable</h1>
<a class="prodListPage" href="">
<a class="prodListPage" href="">
<a class="prodListPage" href="">
<a class="prodListPage" href="">
Belongs to this markup
:nth-child() doesn't "lock" onto class names or tag names the way you think it does. It only cares that the element is the nth child of its parent together with all of its other siblings, regardless of whether the other siblings are different elements or don't have specific classes, etc.
Having the +1 and +3 there is fine if you know you always want to skip the first element and first 3 elements respectively. That's just how :nth-child() works.

What's wrong with selecting the first div this way

I'm trying to have some css applied for the first div with id=div1. When I do .alldivs:first, it doesn't work. What am I doing wrong?
<div class="alldivs">
<div class="onediv" id="div1">
</div>
<div class="onediv" id="div2">
</div>
<div class="onediv" id="div3">
</div>
</div>
If you want to select the first child: .alldivs>:first-child should do the trick.
Edit:
Su edited my post to say .alldivs:first-child. This actually isn't right and I've restored it to what I originally put. The :first-child syntax selects the first child of its parent that matches the selector immediately previous to the colon. Therefore, p:first-child would match any paragraph that was the first child of its parent. Thus, .alldivs> matches any child of .alldivs and :first-child matches the first one. Please make sure you're correct before editing others posts.
What you want is:
.alldivs div:first-child
If the div has an id already, just select it by id.
#div1 {
/* yes that's all you need */
}
There's no such thing as two elements with the same id (if you're paying attention to the rules), so it doesn't matter if it's first or thirty-first.
If you're looking for the first div no matter what the id, use .alldivs :first-child
Here's some reference for further understanding:
http://www.w3.org/TR/CSS2/selector.html#first-child
.alldivs is not a selector, if you wanted to select the first div in the dom it would be div:first-child or if you wanted to select the first div with the class onediv it would be .onediv:first-child
I hope this helps you

wildcard * in CSS for classes

I have these divs that I'm styling with .tocolor, but I also need the unique identifier 1,2,3,4 etc. so I'm adding that it as another class tocolor-1.
<div class="tocolor tocolor-1"> tocolor 1 </div>
<div class="tocolor tocolor-2"> tocolor 2 </div>
<div class="tocolor tocolor-3"> tocolor 3 </div>
<div class="tocolor tocolor-4"> tocolor 4 </div>
.tocolor{
background: red;
}
Is there a way to have just 1 class tocolor-*. I tried using a wildcard * as in this css, but it didn't work.
.tocolor-*{
background: red;
}
What you need is called attribute selector. An example, using your html structure, is the following:
div[class^="tocolor-"], div[class*=" tocolor-"] {
color:red
}
In the place of div you can add any element or remove it altogether, and in the place of class you can add any attribute of the specified element.
[class^="tocolor-"] — starts with "tocolor-".
[class*=" tocolor-"] — contains the substring "tocolor-" occurring directly after a space character.
Demo: http://jsfiddle.net/K3693/1/
More information on CSS attribute selectors, you can find here and here.
And from MDN Docs MDN Docs
Yes you can do this.
*[id^='term-']{
[css here]
}
This will select all ids that start with 'term-'.
As for the reason for not doing this, I see where it would be preferable to select this way; as for style, I wouldn't do it myself, but it's possible.
An alternative solution:
div[class|='tocolor'] will match for values of the "class" attribute that begin with "tocolor-", including "tocolor-1", "tocolor-2", etc.
Beware that this won't match
<div class="foo tocolor-">
Reference:
https://www.w3.org/TR/css3-selectors/#attribute-representation
[att|=val]
Represents an element with the att attribute, its value either being exactly "val" or beginning with "val" immediately followed by "-" (U+002D)
If you don't need the unique identifier for further styling of the divs and are using HTML5 you could try and go with custom Data Attributes. Read on here or try a google search for HTML5 Custom Data Attributes

Resources