How to take in account children for :nth-child - html

I have some simple html
<div>row1</div>
<div>row2</div>
<div>row3</div>
<div>
<div>row4.1</div>
<div>
<div>row4.2.1</div>
<div>row4.2.2</div>
</div>
<div>row4.3</div>
<div>row4.4</div>
</div>
<div>row5</div>
and css file
div:nth-child(even)
{
background-color:green;
}
I want to make all odd rows green and to not take care of hierarchy. But in result I have this
What am I doing wrong? how to make green rows 2, 4.1, 4.2.2 and 4.4. All other shoud be white.
Is it possible without javascript by css only?

Basically, no it is not possible. CSS doesn't work by counting the elements in the document. It treats the document as a tree and you can't treat it any other way.
Your options are to remove the nesting (which ruins the semantics), to style the individual elements (with a class, say, perhaps dynamically generated) or to use Javascript.
One other thing you could do to make it make sense is to add this:
div {
background-color: white;
}
This is better but still not quite what you want.

Unfortunately, what you're describing is strictly not possible with CSS selectors.
The :nth-child selector (like :nth-of-type) only operates within the context of a single isolated group of children (not descendants). And indeed, that is exactly what you're seeing: the even children of each parent being highlighted. As you've written that selector, it will match rows 2, 4 (i.e. the parent of all rows 4.x), 4.2 (i.e. the parent of all rows 4.2.x), and 4.4, because they are each even-indexed children of their parents.
I'm afraid your options are (as I see it):
Flattening the DOM so that all of the rows are children of the same parent element. I suspect this might not be possible in your application.
Manually specifying whether a row is highlighted using JS and some sort of .highlighted CSS class. Not hard, but also kinda annoying to keep up to date if rows are added/removed/moved. Can be easily accomplished in jQuery by adding a .row CSS class to each row and using $('.row:even').addClass('highlighted');. See this jsfiddle. The jQuery-less method is more verbose but also quite simple.
Creating a vertically-repeating background image (or set of evenly-spaced divs) for the line highlights. If you know the height of each line beforehand, you can simply create a 1px-wide image with twice the height of the row. Highlight the bottom half of the image and set the background image to repeat. On the one hand, this can be done entirely in CSS (especially with inline base64-encoded images). On the other hand, it can't handle variable-height rows.

Alternative Solution for this is to using a class, provided your html structure is not a large.
<div>row1</div>
<div class="green">row2</div>
<div>row3</div>
<div>
<div class="green">row4.1</div>
<div>
<div>row4.2.1</div>
<div class="green">row4.2.2</div>
</div>
<div>row4.3</div>
<div class="green">row4.4</div>
</div>
<div>row5</div>
<style>
div.green
{
background-color:green;
}
div {
background-color: white;
}
</style>

Related

Does using pseudo elements like :first-child or :last-child

I firstly say that i don't know anything about how css rules are assigned to DOM elements by browser, so that my question is more around it, but i got wondering this in this particular situation I got into, so I use it for formalizing my curiosity:
I do have an HTML snippet like this:
<section>
<div>I'd like to be blue</div>
<div style="color:green">I am quite <p style="font-weight: bold">self confident</p> about my styles</div>
<p>I'd like to be biig</p>
</section>
The text's content of the divs tries to describe my requirements: The first div MUST be blue, the second one i don't care because I will probably use inherited properties or I will set through js or whatever.
The p should be bold,
So I want to assign styles to do that, and I do something like this:
section div {
color: blue;
}
section p {
font-weight: bold;
}
And that obviously works as expected. But, CSS has nice features to target more specific elements. So I could do, for doing the same thing:
section > div:first-child {
color: blue;
}
section > p {
font-weight: bold;
}
This will affect only elements that are direct children of the section, and only the first div of the set, so that i will have the same result, but selecting elements more specifically.
I wonder if this helps browsers assigning css rules to elements.
I think that at some level the browser check for each DOM element the css' rules that target it, and if it finds matches (a css class is actually targeting it), it checks for conflicts and performs overriding if needed.
Would excluding elements from that sets, by targeting them more specifically help the browser to assign style (increase performance or decrease) ?
If it increases, is it meaningful or it is so little that everyone ignores it ?
If it decreases, how much and why ?
Thanks for any advice.
According to this article from Mozilla Development Network, the more specific your selectors are, the better. So if you do not bother how many divs get colored blue, the general selector section div is better. The longer your selector chain is, the harder it is for the browser to find that element since it needs to match more things. The most performant option in this case would actually assigning a class named for example .blue to the div you want blue.
The element>element (direct child) selector is more performant than the element element (descendand) selector in the sandbox but will probably force you to write a longer selector chain if you wish to overwrite it at another point.
To answer your question, in your example (at least in a nutshell), the overall performance will probably decrease by a little (meaningless) bit since pseudo-elements like :first-child are the least performant selectors and you furtherly have a longer selector chain.
If you actually asked me which of those to use in a project with more than just six lines of css, I'd encourage you to use the first example aswell since it's much more easy to overwrite and reuse.

CSS: Why use style classes when i can target them?

I wonder about something, why should i name classes and style them, when i can just target then with css3 pseudo-classes? Will not be lesser "html code"?
<header>
<nav>
Link 1
Link 2
</nav>
</header>
In my CSS instead of i style the menu like this
.menu {
background-color: red;
width 50px;
}
I can just write like this?
header nav a:link {
background-color: red;
width 50px;
}
This is just an demostration/example i wrote fast, because if this is "smarter" or "better" coding then alot of webpages can get rid of alot unncesseriy classes and divs then they just target them as an Child-element?
Is this better or not?
Short answer: because it makes things easier.
It may be:
very difficult to write specific rules to target very specific elements
impossible to target elements directly if the HTML is very dynamic
cumbersome to add a lot of specific selectors if you want to style several elements the same in different parts of the document
difficult to move elements around in the document, because you need to touch the CSS rules as well every time
Classes identify groups of elements which you all want to treat equally, completely independently of their position within the document. This enables you to decouple your CSS and your document structure and reuse CSS efficiently for different documents.
The content of a web is often (very often) dinamic. that means it is developed in a team when (in my case) I do all the styles and they do all the programing stuff. You may have a container (div) and you may know what is going to be inside (links) but you will never know if you may have one or 200 links inside. You can control the html container and give it a class but even if my mates could make that any link inside has a class as it is generated, why bother them if I can target perfectly the links through header nav a:link

I would like to hide my outer div if inner div is empty

I have two div a child and a parent. the child contains a contact number. If there is no contact number I want the parent div to display none. I am trying to use the :empty CSS statement but I think I am using the wrong logic.
#inter #inter-content:empty {
display:none;
}
<div id="inter" class="telephone">Intl: <div id="inter-content">{{contact_number_international}}</div></div>
I'm not sure if CSS is the right route either. I have tried using the bottom as well:
#inter + #inter-content:empty {
display:none;
}
You cant do this in the way you are approaching it due to how CSS works, and that you can only write selectors to isolate child/subsequent DOM nodes. :empty also works on selecting elements with no child nodes (elements or text).
The :empty pseudo-class represents any element that has no children at
all. Only element nodes and text (including whitespace) are
considered.
As such, you cannot select a parent element using CSS- and you cannot determine a node to be empty, if it contains another node (whether that node is empty or not).
One way to potentially get around this, is to apply the label in your code as a pseudo element, with its content conditionally sourced from a (data) attribute if the element is not empty. This will give the impression of the parent not displaying content if no number is present.
That said, if you actually dont want to display the parent at all- you will run into trouble using CSS alone. It looks like you are using angular (or similar), in which case you may want to use a logical check to toggle the parent's visibility.
.inter div:not(:empty):before {
display: block;
content: attr(data-label);
}
<div class="inter" class="telephone">
<div data-label="Intl: ">21342213</div>
</div>
<div class="inter" class="telephone">
<div data-label="Intl: "></div>
</div>
If you are using for example angular you could write
<div id="inter" class="telephone" ng-if="contact_number_international != null">
<div id="inter-content">Intl: {{contact_number_international}}</div>
</div>
Other frameworks should have such functions too. (I assume u use something because of "{{}}")
Fast forward a few years and CSS has a solution for this:
.outer-content:has(.inner-content:empty) { display: none; }
I was searching myself and none of the relevant answers were recently updated so I thought I'd write it down here.
The browser support :has to be considered of course
"Hide an empty container" questions are redirected here. So here's the simplest solution:
.hide-if-empty:empty { display: none !important; }
<div class="hide-if-empty">
<!-- if empty then hidden -->
</div>

Difference in Class and ID for CSS

Okay, so I understand how to use both, but really what is the point other than semantics? I mean, what negative effect would it have if I created a class for a single, unique, element and only used it on that element?
Also, I know you can assign only certain elements to be effected by a class, for instance:
p.class{blazziblazzi}
Now, only the element 'p' will be effect by that class, if that element is assigned to that class. So why would anybody ever assign that class to an element if they didn't want that element to take on the attributes of that class?
I just don't get why they even made ID and Class separate, it seems pointless to me.
Any pointers would help, thanks!
ID's are unique
Each element can have only one ID
Each page can have only one element with that ID
Classes are NOT unique
You can use the same class on multiple elements.
You can use multiple classes on the same element.
http://css-tricks.com/the-difference-between-id-and-class/
Classes should not use it to rewrite code, I mean you must avoid writing the same, then for that you use a class, instead of assigning each id the same attributes.
For example:
If you have two elements:
<div id="div1" class="divYellow">
</div>
<div id="div2" class="divYellow">
</div>
if you want yellow background color, you could do so:
# div1
{
background-color: yellow;
}
\# div2
{
background-color: yellow;
}
but it would be best that you did so:
. divYellow
{
background-color: yellow;
}
This way when you want to make a change, you just do it in class, and not in two places
Specificity is one of the reasons. You can follow the link in the comments for info on that. Additionally, when you need to add anchor links, you have to use id's, classes will not work. Also, id's are particularly useful for specifying items while using javascript and other languages. In CSS, there is no harm in specifying a class for a single item, but it is a better practice to use id's for unique elements and classes for elements that may mimic the styles of other elements.
if using an ID will stop at the first occurrence.
If it is a class, it will scan the entirety of the document to make sure there aren't other occurrences.
Even if there is 1 occurance of a class, it still needs to scan the entire document to make sure there are none. It leads to issues with selection and runtime of fetching data, given various selectors.
U could for example shorten your CSS. By using a classname multiple times you could save some lines inside your CSS. I would only recommend this if you want to use a large part of your CSS for multiple div's. The small changes could be made within the different ID's if the classnames remain the same.

CSS Rule: Give style to all with children [duplicate]

This question already has answers here:
Complex CSS selector for parent of active child [duplicate]
(10 answers)
Closed 9 years ago.
I'm trying to give a style to all <div> with children and not to those with no children.
Or, give style to all, and give a different style to those with no children.
The structure is similar to this
<div>
<div>
<div>
<div>Don't style me</div>
<div>Don't style me</div>
</div>
<div>Don't style me</div>
<div>Don't style me</div>
<div>
<div>
<div>Don't style me</div>
</div>
</div>
</div>
</div>
CSS level 4 is being worked on, and will include selectors that can do what you're asking.
When it does become available, the syntax will look like this:
.myclass! div { ... }
This will select the .myclass element that has a div element as a child. It's basically a normal CSS selector, but with the exclamation mark to tell it which element to select. (although note that the preferred syntax has changed a couple of times during the drafting process, and they've not finalised it yet!)
If you're interested in following up about this, you can read the full spec in its current form here: http://dev.w3.org/csswg/selectors4/
However that's in the future. For current browsers, what you want to achieve isn't really possible with pure CSS.
So what options do you have?
The most obvious work-around is to use javascript to achieve the effect you want. jQuery is perfectly capable of selecting elements in the way you've described, like so:
$('.myclass:has(div)');
Also obvious would be adding a class to the elements you want to style, and just using that. This could be done in Javascript or in your server-side code. Probably the most obvious answer, really, in the absence of an actual CSS selector you can use.
Depending on what you're trying to do, you could try re-arranging you HTML structure; in some cases, a bit of lateral thinking can help you achieve results that appear to do this, even with the CSS selectors available today. In particular, hover effects can often be worked around this way.
Again, depending on what your code looks like and what you're trying to do with it, you could try making use of some of the more esoteric CSS selectors. For example, div:empty will select divs that have no content. This won't work for the examples you've given (as you have text in the 'empty' divs), but would work in other cases where they really are empty.
It can be done in 2 ways :-
1) Giving a specific class to the parent div and the child div will inherit the style.
2) Giving class to divs individually.
The better option would be implementing via the 1st option.
Use the ">" operator.
Some documentation
Like div > div {}
http://jsfiddle.net/9tLXP/
div {
padding: 10px;
background: red;
}
div > div {
padding: 10px;
background: blue;
}
div > div > div {
padding: 10px;
background: orange;
}
div > div > div > div {
padding: 10px;
background: green;
}
Edit: Obviously I went ahead and styled each one with a different background color to demonstrate the point. In your case you would delete some of the extra styling I provided.
If you are truly looking to use the structure you posted, one where no classes or id's are assigned to any elements, then you can not accurately detect the bottom element in a group with n amount of children.
Operators such as > can give you a direct descendant but they can not tell you if it has any further children without further loops as Michael has shown. The issue therefore with Michaels method is you could not detect a div at level 3, and a div at level 4 and style them the same, as all div's at level 3 now inherit this style.
Long and the short - without adding in a class or 2 you can't accurately detect the bottom most child of a nested structure without effecting it's siblings.